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