xref: /trunk/main/ucb/source/ucp/webdav/DAVResourceAccess.cxx (revision 45c5a00162811bd03b87fcb4fe9996782f2b59ec)
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
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 //=========================================================================
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 //=========================================================================
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 //=========================================================================
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 //=========================================================================
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 {
182     initialize();
183 
184     int errorCount = 0;
185     bool bRetry;
186     do
187     {
188         bRetry = false;
189         try
190         {
191             DAVRequestHeaders aHeaders;
192 
193             getUserRequestHeaders( xEnv,
194                                    getRequestURI(),
195                                    ucb::WebDAVHTTPMethod_PROPFIND,
196                                    aHeaders );
197 
198             m_xSession->PROPFIND( getRequestURI(),
199                                   nDepth,
200                                   rPropertyNames,
201                                   rResources,
202                                   DAVRequestEnvironment(
203                                       getRequestURI(),
204                                       new DAVAuthListener_Impl( xEnv, m_aURL ),
205                                       aHeaders, xEnv ) );
206         }
207         catch ( DAVException & e )
208         {
209             errorCount++;
210             bRetry = handleException( e, errorCount );
211             if ( !bRetry )
212                 throw;
213         }
214     }
215     while ( bRetry );
216 }
217 
218 //=========================================================================
219 void DAVResourceAccess::PROPFIND(
220     const Depth nDepth,
221     std::vector< DAVResourceInfo > & rResInfo,
222     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
223 {
224     initialize();
225 
226     int errorCount = 0;
227     bool bRetry;
228     do
229     {
230         bRetry = false;
231         try
232         {
233             DAVRequestHeaders aHeaders;
234             getUserRequestHeaders( xEnv,
235                                    getRequestURI(),
236                                    ucb::WebDAVHTTPMethod_PROPFIND,
237                                    aHeaders );
238 
239             m_xSession->PROPFIND( getRequestURI(),
240                                   nDepth,
241                                   rResInfo,
242                                   DAVRequestEnvironment(
243                                       getRequestURI(),
244                                       new DAVAuthListener_Impl( xEnv, m_aURL ),
245                                       aHeaders, xEnv ) ) ;
246         }
247         catch ( DAVException & e )
248         {
249             errorCount++;
250             bRetry = handleException( e, errorCount );
251             if ( !bRetry )
252                 throw;
253         }
254     }
255     while ( bRetry );
256 }
257 
258 //=========================================================================
259 void DAVResourceAccess::PROPPATCH(
260     const std::vector< ProppatchValue >& rValues,
261     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
262 {
263     initialize();
264 
265     int errorCount = 0;
266     bool bRetry;
267     do
268     {
269         bRetry = false;
270         try
271         {
272             DAVRequestHeaders aHeaders;
273             getUserRequestHeaders( xEnv,
274                                    getRequestURI(),
275                                    ucb::WebDAVHTTPMethod_PROPPATCH,
276                                    aHeaders );
277 
278             m_xSession->PROPPATCH( getRequestURI(),
279                                    rValues,
280                                    DAVRequestEnvironment(
281                                        getRequestURI(),
282                                        new DAVAuthListener_Impl( xEnv, m_aURL ),
283                                        aHeaders, xEnv ) );
284         }
285         catch ( DAVException & e )
286         {
287             errorCount++;
288             bRetry = handleException( e, errorCount );
289             if ( !bRetry )
290                 throw;
291         }
292     }
293     while ( bRetry );
294 }
295 
296 //=========================================================================
297 void DAVResourceAccess::HEAD(
298     const std::vector< rtl::OUString > & rHeaderNames,
299     DAVResource & rResource,
300     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
301 {
302     initialize();
303 
304     int errorCount = 0;
305     bool bRetry;
306     do
307     {
308         bRetry = false;
309         try
310         {
311             DAVRequestHeaders aHeaders;
312             getUserRequestHeaders( xEnv,
313                                    getRequestURI(),
314                                    ucb::WebDAVHTTPMethod_HEAD,
315                                    aHeaders );
316 
317             m_xSession->HEAD( getRequestURI(),
318                               rHeaderNames,
319                               rResource,
320                               DAVRequestEnvironment(
321                                   getRequestURI(),
322                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
323                                   aHeaders, xEnv ) );
324         }
325         catch ( DAVException & e )
326         {
327             errorCount++;
328             bRetry = handleException( e, errorCount );
329             if ( !bRetry )
330                 throw;
331         }
332     }
333     while ( bRetry );
334 }
335 
336 //=========================================================================
337 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
338     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
339 {
340     initialize();
341 
342     uno::Reference< io::XInputStream > xStream;
343     int errorCount = 0;
344     bool bRetry;
345     do
346     {
347         bRetry = false;
348         try
349         {
350             DAVRequestHeaders aHeaders;
351             getUserRequestHeaders( xEnv,
352                                    getRequestURI(),
353                                    ucb::WebDAVHTTPMethod_GET,
354                                    aHeaders );
355 
356             xStream = m_xSession->GET( getRequestURI(),
357                                        DAVRequestEnvironment(
358                                            getRequestURI(),
359                                            new DAVAuthListener_Impl(
360                                                xEnv, m_aURL ),
361                                            aHeaders, xEnv ) );
362         }
363         catch ( DAVException & e )
364         {
365             errorCount++;
366             bRetry = handleException( e, errorCount );
367             if ( !bRetry )
368                 throw;
369         }
370     }
371     while ( bRetry );
372 
373     return xStream;
374 }
375 
376 //=========================================================================
377 void DAVResourceAccess::GET(
378     uno::Reference< io::XOutputStream > & rStream,
379     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
380 {
381     initialize();
382 
383     int errorCount = 0;
384     bool bRetry;
385     do
386     {
387         bRetry = false;
388         try
389         {
390             DAVRequestHeaders aHeaders;
391             getUserRequestHeaders( xEnv,
392                                    getRequestURI(),
393                                    ucb::WebDAVHTTPMethod_GET,
394                                    aHeaders );
395 
396             m_xSession->GET( getRequestURI(),
397                              rStream,
398                              DAVRequestEnvironment(
399                                  getRequestURI(),
400                                  new DAVAuthListener_Impl( xEnv, m_aURL ),
401                                  aHeaders, xEnv ) );
402         }
403         catch ( DAVException & e )
404         {
405             errorCount++;
406             bRetry = handleException( e, errorCount );
407             if ( !bRetry )
408                 throw;
409         }
410     }
411     while ( bRetry );
412 }
413 
414 //=========================================================================
415 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
416     const std::vector< rtl::OUString > & rHeaderNames,
417     DAVResource & rResource,
418     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
419 {
420     initialize();
421 
422     uno::Reference< io::XInputStream > xStream;
423     int errorCount = 0;
424     bool bRetry;
425     do
426     {
427         bRetry = false;
428         try
429         {
430             DAVRequestHeaders aHeaders;
431             getUserRequestHeaders( xEnv,
432                                    getRequestURI(),
433                                    ucb::WebDAVHTTPMethod_GET,
434                                    aHeaders );
435 
436             xStream = m_xSession->GET( getRequestURI(),
437                                        rHeaderNames,
438                                        rResource,
439                                        DAVRequestEnvironment(
440                                            getRequestURI(),
441                                            new DAVAuthListener_Impl(
442                                                xEnv, m_aURL ),
443                                            aHeaders, xEnv ) );
444         }
445         catch ( DAVException & e )
446         {
447             errorCount++;
448             bRetry = handleException( e, errorCount );
449             if ( !bRetry )
450                 throw;
451         }
452     }
453     while ( bRetry );
454 
455     return xStream;
456 }
457 
458 //=========================================================================
459 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
460     DAVRequestHeaders &rRequestHeaders,
461     const std::vector< rtl::OUString > & rHeaderNames,
462     DAVResource & rResource,
463     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
464 {
465     initialize();
466 
467     uno::Reference< io::XInputStream > xStream;
468     int errorCount = 0;
469     bool bRetry;
470     do
471     {
472         bRetry = false;
473         try
474         {
475             getUserRequestHeaders( xEnv,
476                                    getRequestURI(),
477                                    ucb::WebDAVHTTPMethod_GET,
478                                    rRequestHeaders );
479 
480             xStream = m_xSession->GET( getRequestURI(),
481                                        rHeaderNames,
482                                        rResource,
483                                        DAVRequestEnvironment(
484                                            getRequestURI(),
485                                            new DAVAuthListener_Impl(
486                                                xEnv, m_aURL ),
487                                            rRequestHeaders, xEnv ) );
488         }
489         catch ( DAVException & e )
490         {
491             errorCount++;
492             bRetry = handleException( e, errorCount );
493             if ( !bRetry )
494                 throw;
495         }
496     }
497     while ( bRetry );
498 
499     return xStream;
500 }
501 
502 //=========================================================================
503 void DAVResourceAccess::GET(
504     uno::Reference< io::XOutputStream > & rStream,
505     const std::vector< rtl::OUString > & rHeaderNames,
506     DAVResource & rResource,
507     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
508 {
509     initialize();
510 
511     bool bRetry;
512     int errorCount = 0;
513     do
514     {
515         bRetry = false;
516         try
517         {
518             DAVRequestHeaders aHeaders;
519             getUserRequestHeaders( xEnv,
520                                    getRequestURI(),
521                                    ucb::WebDAVHTTPMethod_GET,
522                                    aHeaders );
523 
524             m_xSession->GET( getRequestURI(),
525                              rStream,
526                              rHeaderNames,
527                              rResource,
528                              DAVRequestEnvironment(
529                                  getRequestURI(),
530                                  new DAVAuthListener_Impl( xEnv, m_aURL ),
531                                  aHeaders, xEnv ) );
532         }
533         catch ( DAVException & e )
534         {
535             errorCount++;
536             bRetry = handleException( e, errorCount );
537             if ( !bRetry )
538                 throw;
539         }
540     }
541     while ( bRetry );
542 }
543 
544 //=========================================================================
545 void DAVResourceAccess::abort()
546 {
547     // 17.11.09 (tkr): abort currently disabled caused by issue i106766
548     // initialize();
549     // m_xSession->abort();
550     OSL_TRACE( "Not implemented. -> #i106766#" );
551 }
552 
553 //=========================================================================
554 namespace {
555 
556     void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
557     {
558         try
559         {
560             uno::Reference< io::XSeekable > xSeekable(
561                 rStream, uno::UNO_QUERY );
562             if ( xSeekable.is() )
563             {
564                 xSeekable->seek( 0 );
565                 return;
566             }
567         }
568         catch ( lang::IllegalArgumentException const & )
569         {
570         }
571         catch ( io::IOException const & )
572         {
573         }
574 
575         throw DAVException( DAVException::DAV_INVALID_ARG );
576     }
577 
578 } // namespace
579 
580 //=========================================================================
581 void DAVResourceAccess::PUT(
582     const uno::Reference< io::XInputStream > & rStream,
583     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
584 {
585     initialize();
586 
587     // Make stream seekable, if it not. Needed, if request must be retried.
588     uno::Reference< io::XInputStream > xSeekableStream
589         = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
590             rStream, m_xSMgr );
591 
592     int errorCount = 0;
593     bool bRetry = false;
594     do
595     {
596         if ( bRetry )
597             resetInputStream( xSeekableStream );
598 
599         bRetry = false;
600         try
601         {
602             DAVRequestHeaders aHeaders;
603             getUserRequestHeaders( xEnv,
604                                    getRequestURI(),
605                                    ucb::WebDAVHTTPMethod_PUT,
606                                    aHeaders );
607 
608             m_xSession->PUT( getRequestURI(),
609                              xSeekableStream,
610                              DAVRequestEnvironment(
611                                  getRequestURI(),
612                                  new DAVAuthListener_Impl( xEnv, m_aURL ),
613                                  aHeaders, xEnv ) );
614         }
615         catch ( DAVException & e )
616         {
617             errorCount++;
618             bRetry = handleException( e, errorCount );
619             if ( !bRetry )
620                 throw;
621         }
622     }
623     while ( bRetry );
624 }
625 
626 //=========================================================================
627 uno::Reference< io::XInputStream > DAVResourceAccess::POST(
628     const rtl::OUString & rContentType,
629     const rtl::OUString & rReferer,
630     const uno::Reference< io::XInputStream > & rInputStream,
631     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
632 {
633     initialize();
634 
635     // Make stream seekable, if it not. Needed, if request must be retried.
636     uno::Reference< io::XInputStream > xSeekableStream
637         = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
638             rInputStream, m_xSMgr );
639 
640     uno::Reference< io::XInputStream > xStream;
641     int errorCount = 0;
642     bool bRetry = false;
643     do
644     {
645         if ( bRetry )
646         {
647             resetInputStream( xSeekableStream );
648             bRetry = false;
649         }
650 
651         try
652         {
653             DAVRequestHeaders aHeaders;
654             getUserRequestHeaders( xEnv,
655                                    getRequestURI(),
656                                    ucb::WebDAVHTTPMethod_POST,
657                                    aHeaders );
658 
659             xStream = m_xSession->POST( getRequestURI(),
660                                         rContentType,
661                                         rReferer,
662                                         xSeekableStream,
663                                         DAVRequestEnvironment(
664                                             getRequestURI(),
665                                             new DAVAuthListener_Impl(
666                                                 xEnv, m_aURL ),
667                                             aHeaders, xEnv ) );
668         }
669         catch ( DAVException & e )
670         {
671             errorCount++;
672             bRetry = handleException( e, errorCount );
673             if ( !bRetry )
674                 throw;
675 
676             if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
677             {
678                 // #i74980# - Upon POST redirect, do a GET.
679                 return GET( xEnv );
680             }
681         }
682     }
683     while ( bRetry );
684 
685     return xStream;
686 }
687 
688 //=========================================================================
689 void DAVResourceAccess::POST(
690     const rtl::OUString & rContentType,
691     const rtl::OUString & rReferer,
692     const uno::Reference< io::XInputStream > & rInputStream,
693     uno::Reference< io::XOutputStream > & rOutputStream,
694     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
695 {
696     initialize();
697 
698     // Make stream seekable, if it not. Needed, if request must be retried.
699     uno::Reference< io::XInputStream > xSeekableStream
700         = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
701             rInputStream, m_xSMgr );
702 
703     int errorCount = 0;
704     bool bRetry  = false;
705     do
706     {
707         if ( bRetry )
708         {
709             resetInputStream( xSeekableStream );
710             bRetry = false;
711         }
712 
713         try
714         {
715             DAVRequestHeaders aHeaders;
716             getUserRequestHeaders( xEnv,
717                                    getRequestURI(),
718                                    ucb::WebDAVHTTPMethod_POST,
719                                    aHeaders );
720 
721             m_xSession->POST( getRequestURI(),
722                               rContentType,
723                               rReferer,
724                               xSeekableStream,
725                               rOutputStream,
726                               DAVRequestEnvironment(
727                                   getRequestURI(),
728                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
729                                   aHeaders, xEnv ) );
730         }
731         catch ( DAVException & e )
732         {
733             errorCount++;
734             bRetry = handleException( e, errorCount );
735             if ( !bRetry )
736                 throw;
737 
738             if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
739             {
740                 // #i74980# - Upon POST redirect, do a GET.
741                 GET( rOutputStream, xEnv );
742                 return;
743             }
744         }
745     }
746     while ( bRetry );
747 }
748 
749 //=========================================================================
750 void DAVResourceAccess::MKCOL(
751     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
752 {
753     initialize();
754 
755     int errorCount = 0;
756     bool bRetry;
757     do
758     {
759         bRetry = false;
760         try
761         {
762             DAVRequestHeaders aHeaders;
763             getUserRequestHeaders( xEnv,
764                                    getRequestURI(),
765                                    ucb::WebDAVHTTPMethod_MKCOL,
766                                    aHeaders );
767 
768             m_xSession->MKCOL( getRequestURI(),
769                                DAVRequestEnvironment(
770                                    getRequestURI(),
771                                    new DAVAuthListener_Impl( xEnv, m_aURL ),
772                                    aHeaders, xEnv ) );
773         }
774         catch ( DAVException & e )
775         {
776             errorCount++;
777             bRetry = handleException( e, errorCount );
778             if ( !bRetry )
779                 throw;
780         }
781     }
782     while ( bRetry );
783 }
784 
785 //=========================================================================
786 void DAVResourceAccess::COPY(
787     const ::rtl::OUString & rSourcePath,
788     const ::rtl::OUString & rDestinationURI,
789     sal_Bool bOverwrite,
790     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
791 {
792     initialize();
793 
794     int errorCount = 0;
795     bool bRetry;
796     do
797     {
798         bRetry = false;
799         try
800         {
801             DAVRequestHeaders aHeaders;
802             getUserRequestHeaders( xEnv,
803                                    getRequestURI(),
804                                    ucb::WebDAVHTTPMethod_COPY,
805                                    aHeaders );
806 
807             m_xSession->COPY( rSourcePath,
808                               rDestinationURI,
809                               DAVRequestEnvironment(
810                                   getRequestURI(),
811                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
812                                   aHeaders, xEnv ),
813                               bOverwrite );
814         }
815         catch ( DAVException & e )
816         {
817             errorCount++;
818             bRetry = handleException( e, errorCount );
819             if ( !bRetry )
820                 throw;
821         }
822     }
823     while ( bRetry );
824 }
825 
826 //=========================================================================
827 void DAVResourceAccess::MOVE(
828     const ::rtl::OUString & rSourcePath,
829     const ::rtl::OUString & rDestinationURI,
830     sal_Bool bOverwrite,
831     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
832 {
833     initialize();
834 
835     int errorCount = 0;
836     bool bRetry;
837     do
838     {
839         bRetry = false;
840         try
841         {
842             DAVRequestHeaders aHeaders;
843             getUserRequestHeaders( xEnv,
844                                    getRequestURI(),
845                                    ucb::WebDAVHTTPMethod_MOVE,
846                                    aHeaders );
847 
848             m_xSession->MOVE( rSourcePath,
849                               rDestinationURI,
850                               DAVRequestEnvironment(
851                                   getRequestURI(),
852                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
853                                   aHeaders, xEnv ),
854                               bOverwrite );
855         }
856         catch ( DAVException & e )
857         {
858             errorCount++;
859             bRetry = handleException( e, errorCount );
860             if ( !bRetry )
861                 throw;
862         }
863     }
864     while ( bRetry );
865 }
866 
867 //=========================================================================
868 void DAVResourceAccess::DESTROY(
869     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
870 {
871     initialize();
872 
873     int errorCount = 0;
874     bool bRetry;
875     do
876     {
877         bRetry = false;
878         try
879         {
880             DAVRequestHeaders aHeaders;
881             getUserRequestHeaders( xEnv,
882                                    getRequestURI(),
883                                    ucb::WebDAVHTTPMethod_DELETE,
884                                    aHeaders );
885 
886             m_xSession->DESTROY( getRequestURI(),
887                                  DAVRequestEnvironment(
888                                      getRequestURI(),
889                                      new DAVAuthListener_Impl( xEnv, m_aURL ),
890                                      aHeaders, xEnv ) );
891         }
892         catch ( DAVException & e )
893         {
894             errorCount++;
895             bRetry = handleException( e, errorCount );
896             if ( !bRetry )
897                 throw;
898         }
899     }
900     while ( bRetry );
901 }
902 
903 //=========================================================================
904 // set new lock.
905 void DAVResourceAccess::LOCK(
906     ucb::Lock & inLock,
907     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
908 {
909     initialize();
910 
911     int errorCount = 0;
912     bool bRetry;
913     do
914     {
915         bRetry = false;
916         try
917         {
918             DAVRequestHeaders aHeaders;
919             getUserRequestHeaders( xEnv,
920                                    getRequestURI(),
921                                    ucb::WebDAVHTTPMethod_LOCK,
922                                    aHeaders );
923 
924             m_xSession->LOCK( getRequestURI(),
925                               inLock,
926                               DAVRequestEnvironment(
927                                   getRequestURI(),
928                                   new DAVAuthListener_Impl( xEnv, m_aURL ),
929                                   aHeaders, xEnv ) );
930         }
931         catch ( DAVException & e )
932         {
933             errorCount++;
934             bRetry = handleException( e, errorCount );
935             if ( !bRetry )
936                 throw;
937         }
938     }
939     while ( bRetry );
940 }
941 
942 #if 0 // currently not used, but please don't remove code
943 //=========================================================================
944 // refresh existing lock.
945 sal_Int64 DAVResourceAccess::LOCK(
946     sal_Int64 nTimeout,
947     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
948 {
949     initialize();
950 
951     sal_Int64 nNewTimeout = 0;
952     int errorCount = 0;
953     bool bRetry;
954     do
955     {
956         bRetry = false;
957         try
958         {
959             DAVRequestHeaders aHeaders;
960             getUserRequestHeaders( xEnv,
961                                    getRequestURI(),
962                                    ucb::WebDAVHTTPMethod_LOCK,
963                                    aHeaders );
964 
965             nNewTimeout = m_xSession->LOCK( getRequestURI(),
966                                             nTimeout,
967                                             DAVRequestEnvironment(
968                                                 getRequestURI(),
969                                                 new DAVAuthListener_Impl(
970                                                     xEnv, m_aURL ),
971                                             aHeaders, xEnv ) );
972         }
973         catch ( DAVException & e )
974         {
975             errorCount++;
976             bRetry = handleException( e, errorCount );
977             if ( !bRetry )
978                 throw;
979         }
980     }
981     while ( bRetry );
982 
983     return nNewTimeout;
984 }
985 #endif
986 
987 //=========================================================================
988 void DAVResourceAccess::UNLOCK(
989     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
990 {
991     initialize();
992 
993     int errorCount = 0;
994     bool bRetry;
995     do
996     {
997         bRetry = false;
998         try
999         {
1000             DAVRequestHeaders aHeaders;
1001             getUserRequestHeaders( xEnv,
1002                                    getRequestURI(),
1003                                    ucb::WebDAVHTTPMethod_UNLOCK,
1004                                    aHeaders );
1005 
1006             m_xSession->UNLOCK( getRequestURI(),
1007                                 DAVRequestEnvironment(
1008                                     getRequestURI(),
1009                                     new DAVAuthListener_Impl( xEnv, m_aURL ),
1010                                     aHeaders, xEnv ) );
1011         }
1012         catch ( DAVException & e )
1013         {
1014             errorCount++;
1015             bRetry = handleException( e, errorCount );
1016             if ( !bRetry )
1017                 throw;
1018         }
1019     }
1020     while ( bRetry );
1021 }
1022 
1023 //=========================================================================
1024 void DAVResourceAccess::setURL( const rtl::OUString & rNewURL )
1025 {
1026     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1027     m_aURL  = rNewURL;
1028     m_aPath = rtl::OUString(); // Next initialize() will create new session.
1029 }
1030 
1031 //=========================================================================
1032 // init dav session and path
1033 void DAVResourceAccess::initialize()
1034 {
1035     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1036     if ( m_aPath.getLength() == 0 )
1037     {
1038         CurlUri aURI( m_aURL );
1039         rtl::OUString aPath( aURI.GetPath() );
1040 
1041         /* #134089# - Check URI */
1042         if ( !aPath.getLength() )
1043             throw DAVException( DAVException::DAV_INVALID_ARG );
1044 
1045         /* #134089# - Check URI */
1046         if ( !aURI.GetHost().getLength() )
1047             throw DAVException( DAVException::DAV_INVALID_ARG );
1048 
1049         if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL ) )
1050         {
1051             m_xSession.clear();
1052 
1053             // create new webdav session
1054             m_xSession
1055                 = m_xSessionFactory->createDAVSession( m_aURL, m_xSMgr );
1056 
1057             if ( !m_xSession.is() )
1058                 return;
1059         }
1060 
1061         // Own URI is needed for redirect cycle detection.
1062         m_aRedirectURIs.push_back( aURI );
1063 
1064         // Success.
1065         m_aPath = aPath;
1066 
1067         // Not only the path has to be encoded
1068         m_aURL = aURI.GetURI();
1069     }
1070 }
1071 
1072 //=========================================================================
1073 const rtl::OUString & DAVResourceAccess::getRequestURI() const
1074 {
1075     OSL_ENSURE( m_xSession.is(),
1076                 "DAVResourceAccess::getRequestURI - Not initialized!" );
1077 
1078     // In case a proxy is used we have to use the absolute URI for a request.
1079     if ( m_xSession->UsesProxy() )
1080         return m_aURL;
1081 
1082     return m_aPath;
1083 }
1084 
1085 //=========================================================================
1086 // static
1087 void DAVResourceAccess::getUserRequestHeaders(
1088     const uno::Reference< ucb::XCommandEnvironment > & xEnv,
1089     const rtl::OUString & rURI,
1090     ucb::WebDAVHTTPMethod eMethod,
1091     DAVRequestHeaders & rRequestHeaders )
1092 {
1093     if ( !xEnv.is() )
1094         return;
1095 
1096     uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
1097         xEnv, uno::UNO_QUERY );
1098 
1099     if ( !xDAVEnv.is() )
1100         return;
1101 
1102     uno::Sequence< beans::StringPair > aRequestHeaders
1103         = xDAVEnv->getUserRequestHeaders( rURI, eMethod );
1104 
1105     for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n )
1106     {
1107         rRequestHeaders.push_back(
1108             DAVRequestHeader( aRequestHeaders[ n ].First,
1109                               aRequestHeaders[ n ].Second ) );
1110     }
1111 }
1112 
1113 //=========================================================================
1114 sal_Bool DAVResourceAccess::detectRedirectCycle(
1115                                 const rtl::OUString& rRedirectURL )
1116 {
1117     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1118 
1119     CurlUri aUri( rRedirectURL );
1120 
1121     std::vector< CurlUri >::const_iterator it  = m_aRedirectURIs.begin();
1122     std::vector< CurlUri >::const_iterator end = m_aRedirectURIs.end();
1123 
1124     while ( it != end )
1125     {
1126         if ( aUri == (*it) )
1127             return sal_True;
1128 
1129         it++;
1130     }
1131 
1132     return sal_False;
1133 }
1134 
1135 //=========================================================================
1136 void DAVResourceAccess::resetUri()
1137 {
1138     osl::Guard< osl::Mutex > aGuard( m_aMutex );
1139     if ( m_aRedirectURIs.size() > 0 )
1140     {
1141         std::vector< CurlUri >::const_iterator it  = m_aRedirectURIs.begin();
1142 
1143         CurlUri aUri( (*it) );
1144         m_aRedirectURIs.clear();
1145         setURL ( aUri.GetURI() );
1146         initialize();
1147     }
1148 }
1149 
1150 //=========================================================================
1151 sal_Bool DAVResourceAccess::handleException( DAVException & e, int errorCount )
1152 {
1153     switch ( e.getError() )
1154     {
1155     case DAVException::DAV_HTTP_REDIRECT:
1156         if ( !detectRedirectCycle( e.getData() ) )
1157         {
1158             // set new URL and path.
1159             setURL( e.getData() );
1160             initialize();
1161             return sal_True;
1162         }
1163         return sal_False;
1164     // --> tkr #67048# copy & paste images doesn't display.
1165     // if we have a bad connection try again. Up to three times.
1166     case DAVException::DAV_HTTP_ERROR:
1167         // retry up to three times, if not a client-side error.
1168         if ( ( e.getStatus() < 400 || e.getStatus() >= 500 ||
1169                e.getStatus() == 413 ) &&
1170              errorCount < 3 )
1171         {
1172             return sal_True;
1173         }
1174         return sal_False;
1175     // <--
1176     // --> tkr: if connection has said retry then retry!
1177     case DAVException::DAV_HTTP_RETRY:
1178         return sal_True;
1179     // <--
1180     default:
1181         return sal_False; // Abort
1182     }
1183 }
1184