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