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