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