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 ::rtl::OUString & inRealm,
57 : const ::rtl::OUString & inHostName,
58 : ::rtl::OUString & inoutUserName,
59 : ::rtl::OUString & outPassWord,
60 : sal_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, ::rtl::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 : sal_Bool bUseSystemCredentials = sal_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 = rtl::OUString();
110 0 : outPassWord = rtl::OUString();
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 0 : DAVResourceAccess::DAVResourceAccess(
142 : const uno::Reference< uno::XComponentContext > & rxContext,
143 : rtl::Reference< DAVSessionFactory > const & rSessionFactory,
144 : const rtl::OUString & rURL )
145 : : m_aURL( rURL ),
146 : m_xSessionFactory( rSessionFactory ),
147 0 : m_xContext( rxContext )
148 : {
149 0 : }
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 : rtl::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< rtl::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 : rtl::OUString( "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 : rtl::OUString( "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 : rtl::OUString( "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< rtl::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 : rtl::OUString("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 : rtl::OUString("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 : rtl::OUString("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< rtl::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 : rtl::OUString("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< rtl::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 : rtl::OUString("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 : // 17.11.09 (tkr): abort currently disabled caused by issue i106766
557 : // initialize();
558 : // m_xSession->abort();
559 : OSL_TRACE( "Not implemented. -> #i106766#" );
560 0 : }
561 :
562 : //=========================================================================
563 : namespace {
564 :
565 0 : void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
566 : throw( DAVException )
567 : {
568 : try
569 : {
570 : uno::Reference< io::XSeekable > xSeekable(
571 0 : rStream, uno::UNO_QUERY );
572 0 : if ( xSeekable.is() )
573 : {
574 0 : xSeekable->seek( 0 );
575 0 : return;
576 0 : }
577 : }
578 0 : catch ( lang::IllegalArgumentException const & )
579 : {
580 : }
581 0 : catch ( io::IOException const & )
582 : {
583 : }
584 :
585 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
586 : }
587 :
588 : } // namespace
589 :
590 : //=========================================================================
591 0 : void DAVResourceAccess::PUT(
592 : const uno::Reference< io::XInputStream > & rStream,
593 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
594 : throw( DAVException )
595 : {
596 0 : initialize();
597 :
598 : // Make stream seekable, if it not. Needed, if request must be retried.
599 : uno::Reference< io::XInputStream > xSeekableStream
600 : = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
601 0 : rStream, m_xContext );
602 :
603 0 : int errorCount = 0;
604 0 : bool bRetry = false;
605 0 : do
606 : {
607 0 : if ( bRetry )
608 0 : resetInputStream( xSeekableStream );
609 :
610 0 : bRetry = false;
611 : try
612 : {
613 0 : DAVRequestHeaders aHeaders;
614 : getUserRequestHeaders( xEnv,
615 0 : getRequestURI(),
616 : rtl::OUString("PUT"),
617 0 : aHeaders );
618 :
619 0 : m_xSession->PUT( getRequestURI(),
620 : xSeekableStream,
621 : DAVRequestEnvironment(
622 0 : getRequestURI(),
623 0 : new DAVAuthListener_Impl( xEnv, m_aURL ),
624 0 : aHeaders, xEnv ) );
625 : }
626 0 : catch ( const DAVException & e )
627 : {
628 0 : errorCount++;
629 0 : bRetry = handleException( e, errorCount );
630 0 : if ( !bRetry )
631 0 : throw;
632 : }
633 : }
634 0 : while ( bRetry );
635 0 : }
636 :
637 : //=========================================================================
638 0 : uno::Reference< io::XInputStream > DAVResourceAccess::POST(
639 : const rtl::OUString & rContentType,
640 : const rtl::OUString & rReferer,
641 : const uno::Reference< io::XInputStream > & rInputStream,
642 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
643 : throw ( DAVException )
644 : {
645 0 : initialize();
646 :
647 : // Make stream seekable, if it not. Needed, if request must be retried.
648 : uno::Reference< io::XInputStream > xSeekableStream
649 : = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
650 0 : rInputStream, m_xContext );
651 :
652 0 : uno::Reference< io::XInputStream > xStream;
653 0 : int errorCount = 0;
654 0 : bool bRetry = false;
655 0 : do
656 : {
657 0 : if ( bRetry )
658 : {
659 0 : resetInputStream( xSeekableStream );
660 0 : bRetry = false;
661 : }
662 :
663 : try
664 : {
665 0 : DAVRequestHeaders aHeaders;
666 : getUserRequestHeaders( xEnv,
667 0 : getRequestURI(),
668 : rtl::OUString("POST"),
669 0 : aHeaders );
670 :
671 0 : xStream = m_xSession->POST( getRequestURI(),
672 : rContentType,
673 : rReferer,
674 : xSeekableStream,
675 : DAVRequestEnvironment(
676 0 : getRequestURI(),
677 : new DAVAuthListener_Impl(
678 0 : xEnv, m_aURL ),
679 0 : aHeaders, xEnv ) );
680 : }
681 0 : catch ( const DAVException & e )
682 : {
683 0 : errorCount++;
684 0 : bRetry = handleException( e, errorCount );
685 0 : if ( !bRetry )
686 0 : throw;
687 :
688 0 : if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
689 : {
690 : // #i74980# - Upon POST redirect, do a GET.
691 0 : return GET( xEnv );
692 : }
693 : }
694 : }
695 : while ( bRetry );
696 :
697 0 : return xStream;
698 : }
699 :
700 : //=========================================================================
701 0 : void DAVResourceAccess::POST(
702 : const rtl::OUString & rContentType,
703 : const rtl::OUString & rReferer,
704 : const uno::Reference< io::XInputStream > & rInputStream,
705 : uno::Reference< io::XOutputStream > & rOutputStream,
706 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
707 : throw ( DAVException )
708 : {
709 0 : initialize();
710 :
711 : // Make stream seekable, if it not. Needed, if request must be retried.
712 : uno::Reference< io::XInputStream > xSeekableStream
713 : = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
714 0 : rInputStream, m_xContext );
715 :
716 0 : int errorCount = 0;
717 0 : bool bRetry = false;
718 0 : do
719 : {
720 0 : if ( bRetry )
721 : {
722 0 : resetInputStream( xSeekableStream );
723 0 : bRetry = false;
724 : }
725 :
726 : try
727 : {
728 0 : DAVRequestHeaders aHeaders;
729 : getUserRequestHeaders( xEnv,
730 0 : getRequestURI(),
731 : rtl::OUString("POST"),
732 0 : aHeaders );
733 :
734 0 : m_xSession->POST( getRequestURI(),
735 : rContentType,
736 : rReferer,
737 : xSeekableStream,
738 : rOutputStream,
739 : DAVRequestEnvironment(
740 0 : getRequestURI(),
741 0 : new DAVAuthListener_Impl( xEnv, m_aURL ),
742 0 : aHeaders, xEnv ) );
743 : }
744 0 : catch ( const DAVException & e )
745 : {
746 0 : errorCount++;
747 0 : bRetry = handleException( e, errorCount );
748 0 : if ( !bRetry )
749 0 : throw;
750 :
751 0 : if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
752 : {
753 : // #i74980# - Upon POST redirect, do a GET.
754 0 : GET( rOutputStream, xEnv );
755 0 : return;
756 : }
757 : }
758 : }
759 0 : while ( bRetry );
760 : }
761 :
762 : //=========================================================================
763 0 : void DAVResourceAccess::MKCOL(
764 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
765 : throw( DAVException )
766 : {
767 0 : initialize();
768 :
769 0 : int errorCount = 0;
770 : bool bRetry;
771 0 : do
772 : {
773 0 : bRetry = false;
774 : try
775 : {
776 0 : DAVRequestHeaders aHeaders;
777 : getUserRequestHeaders( xEnv,
778 0 : getRequestURI(),
779 : rtl::OUString("MKCOL"),
780 0 : aHeaders );
781 :
782 0 : m_xSession->MKCOL( getRequestURI(),
783 : DAVRequestEnvironment(
784 0 : getRequestURI(),
785 0 : new DAVAuthListener_Impl( xEnv, m_aURL ),
786 0 : aHeaders, xEnv ) );
787 : }
788 0 : catch ( const DAVException & e )
789 : {
790 0 : errorCount++;
791 0 : bRetry = handleException( e, errorCount );
792 0 : if ( !bRetry )
793 0 : throw;
794 : }
795 : }
796 : while ( bRetry );
797 0 : }
798 :
799 : //=========================================================================
800 0 : void DAVResourceAccess::COPY(
801 : const ::rtl::OUString & rSourcePath,
802 : const ::rtl::OUString & rDestinationURI,
803 : sal_Bool bOverwrite,
804 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
805 : throw( DAVException )
806 : {
807 0 : initialize();
808 :
809 0 : int errorCount = 0;
810 : bool bRetry;
811 0 : do
812 : {
813 0 : bRetry = false;
814 : try
815 : {
816 0 : DAVRequestHeaders aHeaders;
817 : getUserRequestHeaders( xEnv,
818 0 : getRequestURI(),
819 : rtl::OUString("COPY"),
820 0 : aHeaders );
821 :
822 0 : m_xSession->COPY( rSourcePath,
823 : rDestinationURI,
824 : DAVRequestEnvironment(
825 0 : getRequestURI(),
826 0 : new DAVAuthListener_Impl( xEnv, m_aURL ),
827 : aHeaders, xEnv ),
828 0 : bOverwrite );
829 : }
830 0 : catch ( const DAVException & e )
831 : {
832 0 : errorCount++;
833 0 : bRetry = handleException( e, errorCount );
834 0 : if ( !bRetry )
835 0 : throw;
836 : }
837 : }
838 : while ( bRetry );
839 0 : }
840 :
841 : //=========================================================================
842 0 : void DAVResourceAccess::MOVE(
843 : const ::rtl::OUString & rSourcePath,
844 : const ::rtl::OUString & rDestinationURI,
845 : sal_Bool bOverwrite,
846 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
847 : throw( DAVException )
848 : {
849 0 : initialize();
850 :
851 0 : int errorCount = 0;
852 : bool bRetry;
853 0 : do
854 : {
855 0 : bRetry = false;
856 : try
857 : {
858 0 : DAVRequestHeaders aHeaders;
859 : getUserRequestHeaders( xEnv,
860 0 : getRequestURI(),
861 : rtl::OUString("MOVE"),
862 0 : aHeaders );
863 :
864 0 : m_xSession->MOVE( rSourcePath,
865 : rDestinationURI,
866 : DAVRequestEnvironment(
867 0 : getRequestURI(),
868 0 : new DAVAuthListener_Impl( xEnv, m_aURL ),
869 : aHeaders, xEnv ),
870 0 : bOverwrite );
871 : }
872 0 : catch ( const DAVException & e )
873 : {
874 0 : errorCount++;
875 0 : bRetry = handleException( e, errorCount );
876 0 : if ( !bRetry )
877 0 : throw;
878 : }
879 : }
880 : while ( bRetry );
881 0 : }
882 :
883 : //=========================================================================
884 0 : void DAVResourceAccess::DESTROY(
885 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
886 : throw( DAVException )
887 : {
888 0 : initialize();
889 :
890 0 : int errorCount = 0;
891 : bool bRetry;
892 0 : do
893 : {
894 0 : bRetry = false;
895 : try
896 : {
897 0 : DAVRequestHeaders aHeaders;
898 : getUserRequestHeaders( xEnv,
899 0 : getRequestURI(),
900 : rtl::OUString( "DESTROY" ),
901 0 : aHeaders );
902 :
903 0 : m_xSession->DESTROY( getRequestURI(),
904 : DAVRequestEnvironment(
905 0 : getRequestURI(),
906 0 : new DAVAuthListener_Impl( xEnv, m_aURL ),
907 0 : aHeaders, xEnv ) );
908 : }
909 0 : catch ( const DAVException & e )
910 : {
911 0 : errorCount++;
912 0 : bRetry = handleException( e, errorCount );
913 0 : if ( !bRetry )
914 0 : throw;
915 : }
916 : }
917 : while ( bRetry );
918 0 : }
919 :
920 : //=========================================================================
921 : // set new lock.
922 0 : void DAVResourceAccess::LOCK(
923 : ucb::Lock & inLock,
924 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
925 : throw ( DAVException )
926 : {
927 0 : initialize();
928 :
929 0 : int errorCount = 0;
930 : bool bRetry;
931 0 : do
932 : {
933 0 : bRetry = false;
934 : try
935 : {
936 0 : DAVRequestHeaders aHeaders;
937 : getUserRequestHeaders( xEnv,
938 0 : getRequestURI(),
939 : rtl::OUString("LOCK"),
940 0 : aHeaders );
941 :
942 0 : m_xSession->LOCK( getRequestURI(),
943 : inLock,
944 : DAVRequestEnvironment(
945 0 : getRequestURI(),
946 0 : new DAVAuthListener_Impl( xEnv, m_aURL ),
947 0 : aHeaders, xEnv ) );
948 : }
949 0 : catch ( const DAVException & e )
950 : {
951 0 : errorCount++;
952 0 : bRetry = handleException( e, errorCount );
953 0 : if ( !bRetry )
954 0 : throw;
955 : }
956 : }
957 : while ( bRetry );
958 0 : }
959 :
960 : #if 0 // currently not used, but please don't remove code
961 : //=========================================================================
962 : // refresh existing lock.
963 : sal_Int64 DAVResourceAccess::LOCK(
964 : sal_Int64 nTimeout,
965 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
966 : throw ( DAVException )
967 : {
968 : initialize();
969 :
970 : sal_Int64 nNewTimeout = 0;
971 : int errorCount = 0;
972 : bool bRetry;
973 : do
974 : {
975 : bRetry = false;
976 : try
977 : {
978 : DAVRequestHeaders aHeaders;
979 : getUserRequestHeaders( xEnv,
980 : getRequestURI(),
981 : rtl::OUString("LOCK"),
982 : aHeaders );
983 :
984 : nNewTimeout = m_xSession->LOCK( getRequestURI(),
985 : nTimeout,
986 : DAVRequestEnvironment(
987 : getRequestURI(),
988 : new DAVAuthListener_Impl(
989 : xEnv, m_aURL ),
990 : aHeaders, xEnv ) );
991 : }
992 : catch ( const DAVException & e )
993 : {
994 : errorCount++;
995 : bRetry = handleException( e, errorCount );
996 : if ( !bRetry )
997 : throw;
998 : }
999 : }
1000 : while ( bRetry );
1001 :
1002 : return nNewTimeout;
1003 : }
1004 : #endif
1005 :
1006 : //=========================================================================
1007 0 : void DAVResourceAccess::UNLOCK(
1008 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1009 : throw ( DAVException )
1010 : {
1011 0 : initialize();
1012 :
1013 0 : int errorCount = 0;
1014 : bool bRetry;
1015 0 : do
1016 : {
1017 0 : bRetry = false;
1018 : try
1019 : {
1020 0 : DAVRequestHeaders aHeaders;
1021 : getUserRequestHeaders( xEnv,
1022 0 : getRequestURI(),
1023 : rtl::OUString("UNLOCK"),
1024 0 : aHeaders );
1025 :
1026 0 : m_xSession->UNLOCK( getRequestURI(),
1027 : DAVRequestEnvironment(
1028 0 : getRequestURI(),
1029 0 : new DAVAuthListener_Impl( xEnv, m_aURL ),
1030 0 : aHeaders, xEnv ) );
1031 : }
1032 0 : catch ( const DAVException & e )
1033 : {
1034 0 : errorCount++;
1035 0 : bRetry = handleException( e, errorCount );
1036 0 : if ( !bRetry )
1037 0 : throw;
1038 : }
1039 : }
1040 : while ( bRetry );
1041 0 : }
1042 :
1043 : //=========================================================================
1044 0 : void DAVResourceAccess::setFlags( const uno::Sequence< beans::NamedValue >& rFlags )
1045 : throw ( DAVException )
1046 : {
1047 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1048 0 : m_aFlags = rFlags;
1049 0 : }
1050 :
1051 : //=========================================================================
1052 0 : void DAVResourceAccess::setURL( const rtl::OUString & rNewURL )
1053 : throw( DAVException )
1054 : {
1055 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1056 0 : m_aURL = rNewURL;
1057 0 : m_aPath = rtl::OUString(); // Next initialize() will create new session.
1058 0 : }
1059 :
1060 : //=========================================================================
1061 : // init dav session and path
1062 0 : void DAVResourceAccess::initialize()
1063 : throw ( DAVException )
1064 : {
1065 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1066 0 : if ( m_aPath.isEmpty() )
1067 : {
1068 0 : NeonUri aURI( m_aURL );
1069 0 : rtl::OUString aPath( aURI.GetPath() );
1070 :
1071 : /* #134089# - Check URI */
1072 0 : if ( aPath.isEmpty() )
1073 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
1074 :
1075 : /* #134089# - Check URI */
1076 0 : if ( aURI.GetHost().isEmpty() )
1077 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
1078 :
1079 0 : if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL, m_aFlags ) )
1080 : {
1081 0 : m_xSession.clear();
1082 :
1083 : // create new webdav session
1084 : m_xSession
1085 0 : = m_xSessionFactory->createDAVSession( m_aURL, m_aFlags, m_xContext );
1086 :
1087 0 : if ( !m_xSession.is() )
1088 0 : return;
1089 : }
1090 :
1091 : // Own URI is needed for redirect cycle detection.
1092 0 : m_aRedirectURIs.push_back( aURI );
1093 :
1094 : // Success.
1095 0 : m_aPath = aPath;
1096 :
1097 : // Not only the path has to be encoded
1098 0 : m_aURL = aURI.GetURI();
1099 0 : }
1100 : }
1101 :
1102 : //=========================================================================
1103 0 : const rtl::OUString & DAVResourceAccess::getRequestURI() const
1104 : {
1105 : OSL_ENSURE( m_xSession.is(),
1106 : "DAVResourceAccess::getRequestURI - Not initialized!" );
1107 :
1108 : // In case a proxy is used we have to use the absolute URI for a request.
1109 0 : if ( m_xSession->UsesProxy() )
1110 0 : return m_aURL;
1111 :
1112 0 : return m_aPath;
1113 : }
1114 :
1115 : //=========================================================================
1116 : // static
1117 0 : void DAVResourceAccess::getUserRequestHeaders(
1118 : const uno::Reference< ucb::XCommandEnvironment > & xEnv,
1119 : const rtl::OUString & rURI,
1120 : const rtl::OUString & rMethod,
1121 : DAVRequestHeaders & rRequestHeaders )
1122 : {
1123 0 : if ( xEnv.is() )
1124 : {
1125 : uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
1126 0 : xEnv, uno::UNO_QUERY );
1127 :
1128 0 : if ( xDAVEnv.is() )
1129 : {
1130 : uno::Sequence< beans::NamedValue > aRequestHeaders
1131 0 : = xDAVEnv->getUserRequestHeaders( rURI, rMethod );
1132 :
1133 0 : for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n )
1134 : {
1135 0 : rtl::OUString aValue;
1136 0 : sal_Bool isString = aRequestHeaders[ n ].Value >>= aValue;
1137 :
1138 : if ( !isString )
1139 : {
1140 : OSL_ENSURE( isString,
1141 : "DAVResourceAccess::getUserRequestHeaders :"
1142 : "Value is not a string! Ignoring..." );
1143 : }
1144 :
1145 : rRequestHeaders.push_back(
1146 0 : DAVRequestHeader( aRequestHeaders[ n ].Name, aValue ) );
1147 0 : }
1148 0 : }
1149 : }
1150 :
1151 : // Make sure a User-Agent header is always included, as at least
1152 : // en.wikipedia.org:80 forces back 403 "Scripts should use an informative
1153 : // User-Agent string with contact information, or they may be IP-blocked
1154 : // without notice" otherwise:
1155 0 : for ( DAVRequestHeaders::iterator i(rRequestHeaders.begin());
1156 0 : i != rRequestHeaders.end(); ++i )
1157 : {
1158 0 : if ( i->first.equalsIgnoreAsciiCase( "User-Agent" ) )
1159 : {
1160 0 : return;
1161 : }
1162 : }
1163 : rRequestHeaders.push_back(
1164 0 : DAVRequestHeader( "User-Agent", "LibreOffice" ) );
1165 : }
1166 :
1167 : //=========================================================================
1168 0 : sal_Bool DAVResourceAccess::detectRedirectCycle(
1169 : const rtl::OUString& rRedirectURL )
1170 : throw ( DAVException )
1171 : {
1172 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1173 :
1174 0 : NeonUri aUri( rRedirectURL );
1175 :
1176 0 : std::vector< NeonUri >::const_iterator it = m_aRedirectURIs.begin();
1177 0 : std::vector< NeonUri >::const_iterator end = m_aRedirectURIs.end();
1178 :
1179 0 : while ( it != end )
1180 : {
1181 0 : if ( aUri == (*it) )
1182 0 : return sal_True;
1183 :
1184 0 : ++it;
1185 : }
1186 :
1187 0 : return sal_False;
1188 : }
1189 :
1190 : //=========================================================================
1191 0 : void DAVResourceAccess::resetUri()
1192 : {
1193 0 : osl::Guard< osl::Mutex > aGuard( m_aMutex );
1194 0 : if ( !m_aRedirectURIs.empty() )
1195 : {
1196 0 : std::vector< NeonUri >::const_iterator it = m_aRedirectURIs.begin();
1197 :
1198 0 : NeonUri aUri( (*it) );
1199 0 : m_aRedirectURIs.clear();
1200 0 : setURL ( aUri.GetURI() );
1201 0 : initialize();
1202 0 : }
1203 0 : }
1204 :
1205 : //=========================================================================
1206 0 : sal_Bool DAVResourceAccess::handleException( const DAVException & e, int errorCount )
1207 : throw ( DAVException )
1208 : {
1209 0 : switch ( e.getError() )
1210 : {
1211 : case DAVException::DAV_HTTP_REDIRECT:
1212 0 : if ( !detectRedirectCycle( e.getData() ) )
1213 : {
1214 : // set new URL and path.
1215 0 : setURL( e.getData() );
1216 0 : initialize();
1217 0 : return sal_True;
1218 : }
1219 0 : return sal_False;
1220 : // #67048# copy & paste images doesn't display.
1221 : // if we have a bad connection try again. Up to three times.
1222 : case DAVException::DAV_HTTP_ERROR:
1223 : // retry up to three times, if not a client-side error.
1224 0 : if ( ( e.getStatus() < 400 || e.getStatus() >= 500 ) &&
1225 : errorCount < 3 )
1226 : {
1227 0 : return sal_True;
1228 : }
1229 0 : return sal_False;
1230 : // if connection has said retry then retry!
1231 : case DAVException::DAV_HTTP_RETRY:
1232 0 : return sal_True;
1233 : default:
1234 0 : return sal_False; // Abort
1235 : }
1236 : }
1237 :
1238 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|