1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_webdav.hxx"
26 
27 #include <osl/diagnose.h>
28 
29 #include <com/sun/star/task/XInteractionAbort.hpp>
30 #include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
31 
32 #include <ucbhelper/simpleauthenticationrequest.hxx>
33 #include <comphelper/seekableinput.hxx>
34 
35 #include "DAVAuthListenerImpl.hxx"
36 #include "DAVResourceAccess.hxx"
37 
38 using namespace http_dav_ucp;
39 using namespace com::sun::star;
40 
41 //=========================================================================
42 //=========================================================================
43 //
44 // DAVAuthListener_Impl Implementation.
45 //
46 //=========================================================================
47 //=========================================================================
48 
49 //=========================================================================
50 // virtual
authenticate(const::rtl::OUString & inRealm,const::rtl::OUString & inHostName,::rtl::OUString & inoutUserName,::rtl::OUString & outPassWord,sal_Bool bCanUseSystemCredentials,sal_Bool bUsePreviousCredentials)51 int DAVAuthListener_Impl::authenticate(
52     const ::rtl::OUString & inRealm,
53     const ::rtl::OUString & inHostName,
54     ::rtl::OUString & inoutUserName,
55     ::rtl::OUString & outPassWord,
56     sal_Bool bCanUseSystemCredentials,
57     sal_Bool bUsePreviousCredentials )
58 {
59     if ( m_xEnv.is() )
60     {
61         uno::Reference< task::XInteractionHandler > xIH
62             = m_xEnv->getInteractionHandler();
63 
64         if ( xIH.is() )
65         {
66             // Providing previously retrieved credentials will cause the password
67             // container to reject these. Thus, the credential input dialog will be shown again.
68             // #102871# - Supply username and password from previous try.
69             // Password container service depends on this!
70             if ( inoutUserName.getLength() == 0 && bUsePreviousCredentials )
71                 inoutUserName = m_aPrevUsername;
72 
73             if ( outPassWord.getLength() == 0 && bUsePreviousCredentials )
74                 outPassWord = m_aPrevPassword;
75 
76             rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
77                 = new ucbhelper::SimpleAuthenticationRequest(
78                     m_aURL, inHostName, inRealm, inoutUserName,
79                     outPassWord, ::rtl::OUString(),
80                     true /*bAllowPersistentStoring*/,
81                     bCanUseSystemCredentials );
82             xIH->handle( xRequest.get() );
83 
84             rtl::Reference< ucbhelper::InteractionContinuation > xSelection
85                 = xRequest->getSelection();
86 
87             if ( xSelection.is() )
88             {
89                 // Handler handled the request.
90                 uno::Reference< task::XInteractionAbort > xAbort(
91                     xSelection.get(), uno::UNO_QUERY );
92                 if ( !xAbort.is() )
93                 {
94                     const rtl::Reference<
95                         ucbhelper::InteractionSupplyAuthentication > & xSupp
96                         = xRequest->getAuthenticationSupplier();
97 
98                     sal_Bool bUseSystemCredentials = sal_False;
99 
100                     if ( bCanUseSystemCredentials )
101                         bUseSystemCredentials
102                             = xSupp->getUseSystemCredentials();
103 
104                     if ( bUseSystemCredentials )
105                     {
106                         // This is the (strange) way to tell neon to use
107                         // system credentials.
108                         inoutUserName = rtl::OUString();
109                         outPassWord   = rtl::OUString();
110                     }
111                     else
112                     {
113                         inoutUserName = xSupp->getUserName();
114                         outPassWord   = xSupp->getPassword();
115                     }
116 
117                     // #102871# - Remember username and password.
118                     m_aPrevUsername = inoutUserName;
119                     m_aPrevPassword = outPassWord;
120 
121                     // go on.
122                     return 0;
123                 }
124             }
125         }
126     }
127     // Abort.
128     return -1;
129 }
130 
131 //=========================================================================
132 //=========================================================================
133 //
134 // DAVResourceAccess Implementation.
135 //
136 //=========================================================================
137 //=========================================================================
138 
139 //=========================================================================
DAVResourceAccess(const uno::Reference<lang::XMultiServiceFactory> & rSMgr,rtl::Reference<DAVSessionFactory> const & rSessionFactory,const rtl::OUString & rURL)140 DAVResourceAccess::DAVResourceAccess(
141     const uno::Reference< lang::XMultiServiceFactory > & rSMgr,
142     rtl::Reference< DAVSessionFactory > const & rSessionFactory,
143     const rtl::OUString & rURL )
144 : m_aURL( rURL ),
145   m_xSessionFactory( rSessionFactory ),
146   m_xSMgr( rSMgr )
147 {
148 }
149 
150 //=========================================================================
DAVResourceAccess(const DAVResourceAccess & rOther)151 DAVResourceAccess::DAVResourceAccess( const DAVResourceAccess & rOther )
152 : m_aURL( rOther.m_aURL ),
153   m_aPath( rOther.m_aPath ),
154   m_xSession( rOther.m_xSession ),
155   m_xSessionFactory( rOther.m_xSessionFactory ),
156   m_xSMgr( rOther.m_xSMgr ),
157   m_aRedirectURIs( rOther.m_aRedirectURIs )
158 {
159 }
160 
161 //=========================================================================
operator =(const DAVResourceAccess & rOther)162 DAVResourceAccess & DAVResourceAccess::operator=(
163     const DAVResourceAccess & rOther )
164 {
165     m_aURL            = rOther.m_aURL;
166     m_aPath           = rOther.m_aPath;
167     m_xSession        = rOther.m_xSession;
168     m_xSessionFactory = rOther.m_xSessionFactory;
169     m_xSMgr           = rOther.m_xSMgr;
170     m_aRedirectURIs   = rOther.m_aRedirectURIs;
171 
172     return *this;
173 }
174 
175 //=========================================================================
PROPFIND(const Depth nDepth,const std::vector<rtl::OUString> & rPropertyNames,std::vector<DAVResource> & rResources,const uno::Reference<ucb::XCommandEnvironment> & xEnv)176 void DAVResourceAccess::PROPFIND(
177     const Depth nDepth,
178     const std::vector< rtl::OUString > & rPropertyNames,
179     std::vector< DAVResource > & rResources,
180     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
181   throw( DAVException )
182 {
183     initialize();
184 
185     int errorCount = 0;
186     bool bRetry;
187     do
188     {
189         bRetry = false;
190         try
191         {
192             DAVRequestHeaders aHeaders;
193 
194             getUserRequestHeaders( xEnv,
195                                    getRequestURI(),
196                                    ucb::WebDAVHTTPMethod_PROPFIND,
197                                    aHeaders );
198 
199             m_xSession->PROPFIND( getRequestURI(),
200                                   nDepth,
201                                   rPropertyNames,
202                                   rResources,
203                                   DAVRequestEnvironment(
204                                       getRequestURI(),
205                                       new DAVAuthListener_Impl( xEnv, m_aURL ),
206                                       aHeaders, xEnv ) );
207         }
208         catch ( DAVException & e )
209         {
210             errorCount++;
211             bRetry = handleException( e, errorCount );
212             if ( !bRetry )
213                 throw;
214         }
215     }
216     while ( bRetry );
217 }
218 
219 //=========================================================================
PROPFIND(const Depth nDepth,std::vector<DAVResourceInfo> & rResInfo,const uno::Reference<ucb::XCommandEnvironment> & xEnv)220 void DAVResourceAccess::PROPFIND(
221     const Depth nDepth,
222     std::vector< DAVResourceInfo > & rResInfo,
223     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
224   throw( DAVException )
225 {
226     initialize();
227 
228     int errorCount = 0;
229     bool bRetry;
230     do
231     {
232         bRetry = false;
233         try
234         {
235             DAVRequestHeaders aHeaders;
236             getUserRequestHeaders( xEnv,
237                                    getRequestURI(),
238                                    ucb::WebDAVHTTPMethod_PROPFIND,
239                                    aHeaders );
240 
241             m_xSession->PROPFIND( getRequestURI(),
242                                   nDepth,
243                                   rResInfo,
244                                   DAVRequestEnvironment(
245                                       getRequestURI(),
246                                       new DAVAuthListener_Impl( xEnv, m_aURL ),
247                                       aHeaders, xEnv ) ) ;
248         }
249         catch ( DAVException & e )
250         {
251             errorCount++;
252             bRetry = handleException( e, errorCount );
253             if ( !bRetry )
254                 throw;
255         }
256     }
257     while ( bRetry );
258 }
259 
260 //=========================================================================
PROPPATCH(const std::vector<ProppatchValue> & rValues,const uno::Reference<ucb::XCommandEnvironment> & xEnv)261 void DAVResourceAccess::PROPPATCH(
262     const std::vector< ProppatchValue >& rValues,
263     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
264   throw( DAVException )
265 {
266     initialize();
267 
268     int errorCount = 0;
269     bool bRetry;
270     do
271     {
272         bRetry = false;
273         try
274         {
275             DAVRequestHeaders aHeaders;
276             getUserRequestHeaders( xEnv,
277                                    getRequestURI(),
278                                    ucb::WebDAVHTTPMethod_PROPPATCH,
279                                    aHeaders );
280 
281             m_xSession->PROPPATCH( getRequestURI(),
282                                    rValues,
283                                    DAVRequestEnvironment(
284                                        getRequestURI(),
285                                        new DAVAuthListener_Impl( xEnv, m_aURL ),
286                                        aHeaders, xEnv ) );
287         }
288         catch ( DAVException & e )
289         {
290             errorCount++;
291             bRetry = handleException( e, errorCount );
292             if ( !bRetry )
293                 throw;
294         }
295     }
296     while ( bRetry );
297 }
298 
299 //=========================================================================
HEAD(const std::vector<rtl::OUString> & rHeaderNames,DAVResource & rResource,const uno::Reference<ucb::XCommandEnvironment> & xEnv)300 void DAVResourceAccess::HEAD(
301     const std::vector< rtl::OUString > & rHeaderNames,
302     DAVResource & rResource,
303     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
304   throw( DAVException )
305 {
306     initialize();
307 
308     int errorCount = 0;
309     bool bRetry;
310     do
311     {
312         bRetry = false;
313         try
314         {
315             DAVRequestHeaders aHeaders;
316             getUserRequestHeaders( xEnv,
317                                    getRequestURI(),
318                                    ucb::WebDAVHTTPMethod_HEAD,
319                                    aHeaders );
320 
321             m_xSession->HEAD( getRequestURI(),
322                               rHeaderNames,
323                               rResource,
324                               DAVRequestEnvironment(
325                                   getRequestURI(),
326                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
327                                   aHeaders, xEnv ) );
328         }
329         catch ( DAVException & e )
330         {
331             errorCount++;
332             bRetry = handleException( e, errorCount );
333             if ( !bRetry )
334                 throw;
335         }
336     }
337     while ( bRetry );
338 }
339 
340 //=========================================================================
GET(const uno::Reference<ucb::XCommandEnvironment> & xEnv)341 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
342     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
343   throw( DAVException )
344 {
345     initialize();
346 
347     uno::Reference< io::XInputStream > xStream;
348     int errorCount = 0;
349     bool bRetry;
350     do
351     {
352         bRetry = false;
353         try
354         {
355             DAVRequestHeaders aHeaders;
356             getUserRequestHeaders( xEnv,
357                                    getRequestURI(),
358                                    ucb::WebDAVHTTPMethod_GET,
359                                    aHeaders );
360 
361             xStream = m_xSession->GET( getRequestURI(),
362                                        DAVRequestEnvironment(
363                                            getRequestURI(),
364                                            new DAVAuthListener_Impl(
365                                                xEnv, m_aURL ),
366                                            aHeaders, xEnv ) );
367         }
368         catch ( DAVException & e )
369         {
370             errorCount++;
371             bRetry = handleException( e, errorCount );
372             if ( !bRetry )
373                 throw;
374         }
375     }
376     while ( bRetry );
377 
378     return xStream;
379 }
380 
381 //=========================================================================
GET(uno::Reference<io::XOutputStream> & rStream,const uno::Reference<ucb::XCommandEnvironment> & xEnv)382 void DAVResourceAccess::GET(
383     uno::Reference< io::XOutputStream > & rStream,
384     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
385   throw( DAVException )
386 {
387     initialize();
388 
389     int errorCount = 0;
390     bool bRetry;
391     do
392     {
393         bRetry = false;
394         try
395         {
396             DAVRequestHeaders aHeaders;
397             getUserRequestHeaders( xEnv,
398                                    getRequestURI(),
399                                    ucb::WebDAVHTTPMethod_GET,
400                                    aHeaders );
401 
402             m_xSession->GET( getRequestURI(),
403                              rStream,
404                              DAVRequestEnvironment(
405                                  getRequestURI(),
406                                  new DAVAuthListener_Impl( xEnv, m_aURL ),
407                                  aHeaders, xEnv ) );
408         }
409         catch ( DAVException & e )
410         {
411             errorCount++;
412             bRetry = handleException( e, errorCount );
413             if ( !bRetry )
414                 throw;
415         }
416     }
417     while ( bRetry );
418 }
419 
420 //=========================================================================
GET(const std::vector<rtl::OUString> & rHeaderNames,DAVResource & rResource,const uno::Reference<ucb::XCommandEnvironment> & xEnv)421 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
422     const std::vector< rtl::OUString > & rHeaderNames,
423     DAVResource & rResource,
424     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
425   throw( DAVException )
426 {
427     initialize();
428 
429     uno::Reference< io::XInputStream > xStream;
430     int errorCount = 0;
431     bool bRetry;
432     do
433     {
434         bRetry = false;
435         try
436         {
437             DAVRequestHeaders aHeaders;
438             getUserRequestHeaders( xEnv,
439                                    getRequestURI(),
440                                    ucb::WebDAVHTTPMethod_GET,
441                                    aHeaders );
442 
443             xStream = m_xSession->GET( getRequestURI(),
444                                        rHeaderNames,
445                                        rResource,
446                                        DAVRequestEnvironment(
447                                            getRequestURI(),
448                                            new DAVAuthListener_Impl(
449                                                xEnv, m_aURL ),
450                                            aHeaders, xEnv ) );
451         }
452         catch ( DAVException & e )
453         {
454             errorCount++;
455             bRetry = handleException( e, errorCount );
456             if ( !bRetry )
457                 throw;
458         }
459     }
460     while ( bRetry );
461 
462     return xStream;
463 }
464 
465 //=========================================================================
GET(DAVRequestHeaders & rRequestHeaders,const std::vector<rtl::OUString> & rHeaderNames,DAVResource & rResource,const uno::Reference<ucb::XCommandEnvironment> & xEnv)466 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
467     DAVRequestHeaders &rRequestHeaders,
468     const std::vector< rtl::OUString > & rHeaderNames,
469     DAVResource & rResource,
470     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
471   throw( DAVException )
472 {
473     initialize();
474 
475     uno::Reference< io::XInputStream > xStream;
476     int errorCount = 0;
477     bool bRetry;
478     do
479     {
480         bRetry = false;
481         try
482         {
483             getUserRequestHeaders( xEnv,
484                                    getRequestURI(),
485                                    ucb::WebDAVHTTPMethod_GET,
486                                    rRequestHeaders );
487 
488             xStream = m_xSession->GET( getRequestURI(),
489                                        rHeaderNames,
490                                        rResource,
491                                        DAVRequestEnvironment(
492                                            getRequestURI(),
493                                            new DAVAuthListener_Impl(
494                                                xEnv, m_aURL ),
495                                            rRequestHeaders, xEnv ) );
496         }
497         catch ( DAVException & e )
498         {
499             errorCount++;
500             bRetry = handleException( e, errorCount );
501             if ( !bRetry )
502                 throw;
503         }
504     }
505     while ( bRetry );
506 
507     return xStream;
508 }
509 
510 //=========================================================================
GET(uno::Reference<io::XOutputStream> & rStream,const std::vector<rtl::OUString> & rHeaderNames,DAVResource & rResource,const uno::Reference<ucb::XCommandEnvironment> & xEnv)511 void DAVResourceAccess::GET(
512     uno::Reference< io::XOutputStream > & rStream,
513     const std::vector< rtl::OUString > & rHeaderNames,
514     DAVResource & rResource,
515     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
516   throw( DAVException )
517 {
518     initialize();
519 
520     bool bRetry;
521     int errorCount = 0;
522     do
523     {
524         bRetry = false;
525         try
526         {
527             DAVRequestHeaders aHeaders;
528             getUserRequestHeaders( xEnv,
529                                    getRequestURI(),
530                                    ucb::WebDAVHTTPMethod_GET,
531                                    aHeaders );
532 
533             m_xSession->GET( getRequestURI(),
534                              rStream,
535                              rHeaderNames,
536                              rResource,
537                              DAVRequestEnvironment(
538                                  getRequestURI(),
539                                  new DAVAuthListener_Impl( xEnv, m_aURL ),
540                                  aHeaders, xEnv ) );
541         }
542         catch ( DAVException & e )
543         {
544             errorCount++;
545             bRetry = handleException( e, errorCount );
546             if ( !bRetry )
547                 throw;
548         }
549     }
550     while ( bRetry );
551 }
552 
553 //=========================================================================
abort()554 void DAVResourceAccess::abort()
555   throw( DAVException )
556 {
557     // 17.11.09 (tkr): abort currently disabled caused by issue i106766
558     // initialize();
559     // m_xSession->abort();
560     OSL_TRACE( "Not implemented. -> #i106766#" );
561 }
562 
563 //=========================================================================
564 namespace {
565 
resetInputStream(const uno::Reference<io::XInputStream> & rStream)566     void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
567         throw( DAVException )
568     {
569         try
570         {
571             uno::Reference< io::XSeekable > xSeekable(
572                 rStream, uno::UNO_QUERY );
573             if ( xSeekable.is() )
574             {
575                 xSeekable->seek( 0 );
576                 return;
577             }
578         }
579         catch ( lang::IllegalArgumentException const & )
580         {
581         }
582         catch ( io::IOException const & )
583         {
584         }
585 
586         throw DAVException( DAVException::DAV_INVALID_ARG );
587     }
588 
589 } // namespace
590 
591 //=========================================================================
PUT(const uno::Reference<io::XInputStream> & rStream,const uno::Reference<ucb::XCommandEnvironment> & xEnv)592 void DAVResourceAccess::PUT(
593     const uno::Reference< io::XInputStream > & rStream,
594     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
595   throw( DAVException )
596 {
597     initialize();
598 
599     // Make stream seekable, if it not. Needed, if request must be retried.
600     uno::Reference< io::XInputStream > xSeekableStream
601         = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
602             rStream, m_xSMgr );
603 
604     int errorCount = 0;
605     bool bRetry = false;
606     do
607     {
608         if ( bRetry )
609             resetInputStream( xSeekableStream );
610 
611         bRetry = false;
612         try
613         {
614             DAVRequestHeaders aHeaders;
615             getUserRequestHeaders( xEnv,
616                                    getRequestURI(),
617                                    ucb::WebDAVHTTPMethod_PUT,
618                                    aHeaders );
619 
620             m_xSession->PUT( getRequestURI(),
621                              xSeekableStream,
622                              DAVRequestEnvironment(
623                                  getRequestURI(),
624                                  new DAVAuthListener_Impl( xEnv, m_aURL ),
625                                  aHeaders, xEnv ) );
626         }
627         catch ( DAVException & e )
628         {
629             errorCount++;
630             bRetry = handleException( e, errorCount );
631             if ( !bRetry )
632                 throw;
633         }
634     }
635     while ( bRetry );
636 }
637 
638 //=========================================================================
POST(const rtl::OUString & rContentType,const rtl::OUString & rReferer,const uno::Reference<io::XInputStream> & rInputStream,const uno::Reference<ucb::XCommandEnvironment> & xEnv)639 uno::Reference< io::XInputStream > DAVResourceAccess::POST(
640     const rtl::OUString & rContentType,
641     const rtl::OUString & rReferer,
642     const uno::Reference< io::XInputStream > & rInputStream,
643     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
644   throw ( DAVException )
645 {
646     initialize();
647 
648     // Make stream seekable, if it not. Needed, if request must be retried.
649     uno::Reference< io::XInputStream > xSeekableStream
650         = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
651             rInputStream, m_xSMgr );
652 
653     uno::Reference< io::XInputStream > xStream;
654     int errorCount = 0;
655     bool bRetry = false;
656     do
657     {
658         if ( bRetry )
659         {
660             resetInputStream( xSeekableStream );
661             bRetry = false;
662         }
663 
664         try
665         {
666             DAVRequestHeaders aHeaders;
667             getUserRequestHeaders( xEnv,
668                                    getRequestURI(),
669                                    ucb::WebDAVHTTPMethod_POST,
670                                    aHeaders );
671 
672             xStream = m_xSession->POST( getRequestURI(),
673                                         rContentType,
674                                         rReferer,
675                                         xSeekableStream,
676                                         DAVRequestEnvironment(
677                                             getRequestURI(),
678                                             new DAVAuthListener_Impl(
679                                                 xEnv, m_aURL ),
680                                             aHeaders, xEnv ) );
681         }
682         catch ( DAVException & e )
683         {
684             errorCount++;
685             bRetry = handleException( e, errorCount );
686             if ( !bRetry )
687                 throw;
688 
689             if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
690             {
691                 // #i74980# - Upon POST redirect, do a GET.
692                 return GET( xEnv );
693             }
694         }
695     }
696     while ( bRetry );
697 
698     return xStream;
699 }
700 
701 //=========================================================================
POST(const rtl::OUString & rContentType,const rtl::OUString & rReferer,const uno::Reference<io::XInputStream> & rInputStream,uno::Reference<io::XOutputStream> & rOutputStream,const uno::Reference<ucb::XCommandEnvironment> & xEnv)702 void DAVResourceAccess::POST(
703     const rtl::OUString & rContentType,
704     const rtl::OUString & rReferer,
705     const uno::Reference< io::XInputStream > & rInputStream,
706     uno::Reference< io::XOutputStream > & rOutputStream,
707     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
708   throw ( DAVException )
709 {
710     initialize();
711 
712     // Make stream seekable, if it not. Needed, if request must be retried.
713     uno::Reference< io::XInputStream > xSeekableStream
714         = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
715             rInputStream, m_xSMgr );
716 
717     int errorCount = 0;
718     bool bRetry  = false;
719     do
720     {
721         if ( bRetry )
722         {
723             resetInputStream( xSeekableStream );
724             bRetry = false;
725         }
726 
727         try
728         {
729             DAVRequestHeaders aHeaders;
730             getUserRequestHeaders( xEnv,
731                                    getRequestURI(),
732                                    ucb::WebDAVHTTPMethod_POST,
733                                    aHeaders );
734 
735             m_xSession->POST( getRequestURI(),
736                               rContentType,
737                               rReferer,
738                               xSeekableStream,
739                               rOutputStream,
740                               DAVRequestEnvironment(
741                                   getRequestURI(),
742                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
743                                   aHeaders, xEnv ) );
744         }
745         catch ( DAVException & e )
746         {
747             errorCount++;
748             bRetry = handleException( e, errorCount );
749             if ( !bRetry )
750                 throw;
751 
752             if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
753             {
754                 // #i74980# - Upon POST redirect, do a GET.
755                 GET( rOutputStream, xEnv );
756                 return;
757             }
758         }
759     }
760     while ( bRetry );
761 }
762 
763 //=========================================================================
MKCOL(const uno::Reference<ucb::XCommandEnvironment> & xEnv)764 void DAVResourceAccess::MKCOL(
765     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
766   throw( DAVException )
767 {
768     initialize();
769 
770     int errorCount = 0;
771     bool bRetry;
772     do
773     {
774         bRetry = false;
775         try
776         {
777             DAVRequestHeaders aHeaders;
778             getUserRequestHeaders( xEnv,
779                                    getRequestURI(),
780                                    ucb::WebDAVHTTPMethod_MKCOL,
781                                    aHeaders );
782 
783             m_xSession->MKCOL( getRequestURI(),
784                                DAVRequestEnvironment(
785                                    getRequestURI(),
786                                    new DAVAuthListener_Impl( xEnv, m_aURL ),
787                                    aHeaders, xEnv ) );
788         }
789         catch ( DAVException & e )
790         {
791             errorCount++;
792             bRetry = handleException( e, errorCount );
793             if ( !bRetry )
794                 throw;
795         }
796     }
797     while ( bRetry );
798 }
799 
800 //=========================================================================
COPY(const::rtl::OUString & rSourcePath,const::rtl::OUString & rDestinationURI,sal_Bool bOverwrite,const uno::Reference<ucb::XCommandEnvironment> & xEnv)801 void DAVResourceAccess::COPY(
802     const ::rtl::OUString & rSourcePath,
803     const ::rtl::OUString & rDestinationURI,
804     sal_Bool bOverwrite,
805     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
806   throw( DAVException )
807 {
808     initialize();
809 
810     int errorCount = 0;
811     bool bRetry;
812     do
813     {
814         bRetry = false;
815         try
816         {
817             DAVRequestHeaders aHeaders;
818             getUserRequestHeaders( xEnv,
819                                    getRequestURI(),
820                                    ucb::WebDAVHTTPMethod_COPY,
821                                    aHeaders );
822 
823             m_xSession->COPY( rSourcePath,
824                               rDestinationURI,
825                               DAVRequestEnvironment(
826                                   getRequestURI(),
827                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
828                                   aHeaders, xEnv ),
829                               bOverwrite );
830         }
831         catch ( DAVException & e )
832         {
833             errorCount++;
834             bRetry = handleException( e, errorCount );
835             if ( !bRetry )
836                 throw;
837         }
838     }
839     while ( bRetry );
840 }
841 
842 //=========================================================================
MOVE(const::rtl::OUString & rSourcePath,const::rtl::OUString & rDestinationURI,sal_Bool bOverwrite,const uno::Reference<ucb::XCommandEnvironment> & xEnv)843 void DAVResourceAccess::MOVE(
844     const ::rtl::OUString & rSourcePath,
845     const ::rtl::OUString & rDestinationURI,
846     sal_Bool bOverwrite,
847     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
848   throw( DAVException )
849 {
850     initialize();
851 
852     int errorCount = 0;
853     bool bRetry;
854     do
855     {
856         bRetry = false;
857         try
858         {
859             DAVRequestHeaders aHeaders;
860             getUserRequestHeaders( xEnv,
861                                    getRequestURI(),
862                                    ucb::WebDAVHTTPMethod_MOVE,
863                                    aHeaders );
864 
865             m_xSession->MOVE( rSourcePath,
866                               rDestinationURI,
867                               DAVRequestEnvironment(
868                                   getRequestURI(),
869                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
870                                   aHeaders, xEnv ),
871                               bOverwrite );
872         }
873         catch ( DAVException & e )
874         {
875             errorCount++;
876             bRetry = handleException( e, errorCount );
877             if ( !bRetry )
878                 throw;
879         }
880     }
881     while ( bRetry );
882 }
883 
884 //=========================================================================
DESTROY(const uno::Reference<ucb::XCommandEnvironment> & xEnv)885 void DAVResourceAccess::DESTROY(
886     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
887   throw( DAVException )
888 {
889     initialize();
890 
891     int errorCount = 0;
892     bool bRetry;
893     do
894     {
895         bRetry = false;
896         try
897         {
898             DAVRequestHeaders aHeaders;
899             getUserRequestHeaders( xEnv,
900                                    getRequestURI(),
901                                    ucb::WebDAVHTTPMethod_DELETE,
902                                    aHeaders );
903 
904             m_xSession->DESTROY( getRequestURI(),
905                                  DAVRequestEnvironment(
906                                      getRequestURI(),
907                                      new DAVAuthListener_Impl( xEnv, m_aURL ),
908                                      aHeaders, xEnv ) );
909         }
910         catch ( DAVException & e )
911         {
912             errorCount++;
913             bRetry = handleException( e, errorCount );
914             if ( !bRetry )
915                 throw;
916         }
917     }
918     while ( bRetry );
919 }
920 
921 //=========================================================================
922 // set new lock.
LOCK(ucb::Lock & inLock,const uno::Reference<ucb::XCommandEnvironment> & xEnv)923 void DAVResourceAccess::LOCK(
924     ucb::Lock & inLock,
925     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
926   throw ( DAVException )
927 {
928     initialize();
929 
930     int errorCount = 0;
931     bool bRetry;
932     do
933     {
934         bRetry = false;
935         try
936         {
937             DAVRequestHeaders aHeaders;
938             getUserRequestHeaders( xEnv,
939                                    getRequestURI(),
940                                    ucb::WebDAVHTTPMethod_LOCK,
941                                    aHeaders );
942 
943             m_xSession->LOCK( getRequestURI(),
944                               inLock,
945                               DAVRequestEnvironment(
946                                   getRequestURI(),
947                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
948                                   aHeaders, xEnv ) );
949         }
950         catch ( DAVException & e )
951         {
952             errorCount++;
953             bRetry = handleException( e, errorCount );
954             if ( !bRetry )
955                 throw;
956         }
957     }
958     while ( bRetry );
959 }
960 
961 #if 0 // currently not used, but please don't remove code
962 //=========================================================================
963 // refresh existing lock.
964 sal_Int64 DAVResourceAccess::LOCK(
965     sal_Int64 nTimeout,
966     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
967   throw ( DAVException )
968 {
969     initialize();
970 
971     sal_Int64 nNewTimeout = 0;
972     int errorCount = 0;
973     bool bRetry;
974     do
975     {
976         bRetry = false;
977         try
978         {
979             DAVRequestHeaders aHeaders;
980             getUserRequestHeaders( xEnv,
981                                    getRequestURI(),
982                                    ucb::WebDAVHTTPMethod_LOCK,
983                                    aHeaders );
984 
985             nNewTimeout = m_xSession->LOCK( getRequestURI(),
986                                             nTimeout,
987                                             DAVRequestEnvironment(
988                                                 getRequestURI(),
989                                                 new DAVAuthListener_Impl(
990                                                     xEnv, m_aURL ),
991                                             aHeaders, xEnv ) );
992         }
993         catch ( DAVException & e )
994         {
995             errorCount++;
996             bRetry = handleException( e, errorCount );
997             if ( !bRetry )
998                 throw;
999         }
1000     }
1001     while ( bRetry );
1002 
1003     return nNewTimeout;
1004 }
1005 #endif
1006 
1007 //=========================================================================
UNLOCK(const uno::Reference<ucb::XCommandEnvironment> & xEnv)1008 void DAVResourceAccess::UNLOCK(
1009     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1010   throw ( DAVException )
1011 {
1012     initialize();
1013 
1014     int errorCount = 0;
1015     bool bRetry;
1016     do
1017     {
1018         bRetry = false;
1019         try
1020         {
1021             DAVRequestHeaders aHeaders;
1022             getUserRequestHeaders( xEnv,
1023                                    getRequestURI(),
1024                                    ucb::WebDAVHTTPMethod_UNLOCK,
1025                                    aHeaders );
1026 
1027             m_xSession->UNLOCK( getRequestURI(),
1028                                 DAVRequestEnvironment(
1029                                     getRequestURI(),
1030                                     new DAVAuthListener_Impl( xEnv, m_aURL ),
1031                                     aHeaders, xEnv ) );
1032         }
1033         catch ( DAVException & e )
1034         {
1035             errorCount++;
1036             bRetry = handleException( e, errorCount );
1037             if ( !bRetry )
1038                 throw;
1039         }
1040     }
1041     while ( bRetry );
1042 }
1043 
1044 //=========================================================================
setURL(const rtl::OUString & rNewURL)1045 void DAVResourceAccess::setURL( const rtl::OUString & rNewURL )
1046     throw( DAVException )
1047 {
1048     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1049     m_aURL  = rNewURL;
1050     m_aPath = rtl::OUString(); // Next initialize() will create new session.
1051 }
1052 
1053 //=========================================================================
1054 // init dav session and path
initialize()1055 void DAVResourceAccess::initialize()
1056     throw ( DAVException )
1057 {
1058     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1059     if ( m_aPath.getLength() == 0 )
1060     {
1061         CurlUri aURI( m_aURL );
1062         rtl::OUString aPath( aURI.GetPath() );
1063 
1064         /* #134089# - Check URI */
1065         if ( !aPath.getLength() )
1066             throw DAVException( DAVException::DAV_INVALID_ARG );
1067 
1068         /* #134089# - Check URI */
1069         if ( !aURI.GetHost().getLength() )
1070             throw DAVException( DAVException::DAV_INVALID_ARG );
1071 
1072         if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL ) )
1073         {
1074             m_xSession.clear();
1075 
1076             // create new webdav session
1077             m_xSession
1078                 = m_xSessionFactory->createDAVSession( m_aURL, m_xSMgr );
1079 
1080             if ( !m_xSession.is() )
1081                 return;
1082         }
1083 
1084         // Own URI is needed for redirect cycle detection.
1085         m_aRedirectURIs.push_back( aURI );
1086 
1087         // Success.
1088         m_aPath = aPath;
1089 
1090         // Not only the path has to be encoded
1091         m_aURL = aURI.GetURI();
1092     }
1093 }
1094 
1095 //=========================================================================
getRequestURI() const1096 const rtl::OUString & DAVResourceAccess::getRequestURI() const
1097 {
1098     OSL_ENSURE( m_xSession.is(),
1099                 "DAVResourceAccess::getRequestURI - Not initialized!" );
1100 
1101     // In case a proxy is used we have to use the absolute URI for a request.
1102     if ( m_xSession->UsesProxy() )
1103         return m_aURL;
1104 
1105     return m_aPath;
1106 }
1107 
1108 //=========================================================================
1109 // static
getUserRequestHeaders(const uno::Reference<ucb::XCommandEnvironment> & xEnv,const rtl::OUString & rURI,ucb::WebDAVHTTPMethod eMethod,DAVRequestHeaders & rRequestHeaders)1110 void DAVResourceAccess::getUserRequestHeaders(
1111     const uno::Reference< ucb::XCommandEnvironment > & xEnv,
1112     const rtl::OUString & rURI,
1113     ucb::WebDAVHTTPMethod eMethod,
1114     DAVRequestHeaders & rRequestHeaders )
1115 {
1116     if ( !xEnv.is() )
1117         return;
1118 
1119     uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
1120         xEnv, uno::UNO_QUERY );
1121 
1122     if ( !xDAVEnv.is() )
1123         return;
1124 
1125     uno::Sequence< beans::StringPair > aRequestHeaders
1126         = xDAVEnv->getUserRequestHeaders( rURI, eMethod );
1127 
1128     for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n )
1129     {
1130         rRequestHeaders.push_back(
1131             DAVRequestHeader( aRequestHeaders[ n ].First,
1132                               aRequestHeaders[ n ].Second ) );
1133     }
1134 }
1135 
1136 //=========================================================================
detectRedirectCycle(const rtl::OUString & rRedirectURL)1137 sal_Bool DAVResourceAccess::detectRedirectCycle(
1138                                 const rtl::OUString& rRedirectURL )
1139     throw ( DAVException )
1140 {
1141     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1142 
1143     CurlUri aUri( rRedirectURL );
1144 
1145     std::vector< CurlUri >::const_iterator it  = m_aRedirectURIs.begin();
1146     std::vector< CurlUri >::const_iterator end = m_aRedirectURIs.end();
1147 
1148     while ( it != end )
1149     {
1150         if ( aUri == (*it) )
1151             return sal_True;
1152 
1153         it++;
1154     }
1155 
1156     return sal_False;
1157 }
1158 
1159 //=========================================================================
resetUri()1160 void DAVResourceAccess::resetUri()
1161 {
1162     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1163     if ( m_aRedirectURIs.size() > 0 )
1164     {
1165         std::vector< CurlUri >::const_iterator it  = m_aRedirectURIs.begin();
1166 
1167         CurlUri aUri( (*it) );
1168         m_aRedirectURIs.clear();
1169         setURL ( aUri.GetURI() );
1170         initialize();
1171     }
1172 }
1173 
1174 //=========================================================================
handleException(DAVException & e,int errorCount)1175 sal_Bool DAVResourceAccess::handleException( DAVException & e, int errorCount )
1176     throw ( DAVException )
1177 {
1178     switch ( e.getError() )
1179     {
1180     case DAVException::DAV_HTTP_REDIRECT:
1181         if ( !detectRedirectCycle( e.getData() ) )
1182         {
1183             // set new URL and path.
1184             setURL( e.getData() );
1185             initialize();
1186             return sal_True;
1187         }
1188         return sal_False;
1189     // --> tkr #67048# copy & paste images doesn't display.
1190     // if we have a bad connection try again. Up to three times.
1191     case DAVException::DAV_HTTP_ERROR:
1192         // retry up to three times, if not a client-side error.
1193         if ( ( e.getStatus() < 400 || e.getStatus() >= 500 ||
1194                e.getStatus() == 413 ) &&
1195              errorCount < 3 )
1196         {
1197             return sal_True;
1198         }
1199         return sal_False;
1200     // <--
1201     // --> tkr: if connection has said retry then retry!
1202     case DAVException::DAV_HTTP_RETRY:
1203         return sal_True;
1204     // <--
1205     default:
1206         return sal_False; // Abort
1207     }
1208 }
1209