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