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