Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / ucb / source / ucp / webdav-neon / DAVResourceAccess.cxx
blobf0576e049aad40929471b4920c7a9f20944fdf01
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
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.
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).
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.
27 ************************************************************************/
30 #include <com/sun/star/io/IOException.hpp>
31 #include <com/sun/star/lang/IllegalArgumentException.hpp>
32 #include <com/sun/star/task/XInteractionAbort.hpp>
33 #include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
35 #include <ucbhelper/simpleauthenticationrequest.hxx>
36 #include <comphelper/seekableinput.hxx>
38 #include "DAVAuthListenerImpl.hxx"
39 #include "DAVResourceAccess.hxx"
41 using namespace webdav_ucp;
42 using namespace com::sun::star;
45 // DAVAuthListener_Impl Implementation.
47 static constexpr sal_uInt32 g_nRedirectLimit = 5;
49 // virtual
50 int DAVAuthListener_Impl::authenticate(
51 const OUString & inRealm,
52 const OUString & inHostName,
53 OUString & inoutUserName,
54 OUString & outPassWord,
55 bool bCanUseSystemCredentials )
57 if ( m_xEnv.is() )
59 uno::Reference< task::XInteractionHandler > xIH
60 = m_xEnv->getInteractionHandler();
62 if ( xIH.is() )
64 // #102871# - Supply username and password from previous try.
65 // Password container service depends on this!
66 if ( inoutUserName.isEmpty() )
67 inoutUserName = m_aPrevUsername;
69 if ( outPassWord.isEmpty() )
70 outPassWord = m_aPrevPassword;
72 rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
73 = new ucbhelper::SimpleAuthenticationRequest(
74 m_aURL, inHostName, inRealm, inoutUserName,
75 outPassWord, bCanUseSystemCredentials );
76 xIH->handle( xRequest.get() );
78 rtl::Reference< ucbhelper::InteractionContinuation > xSelection
79 = xRequest->getSelection();
81 if ( xSelection.is() )
83 // Handler handled the request.
84 uno::Reference< task::XInteractionAbort > xAbort(
85 xSelection.get(), uno::UNO_QUERY );
86 if ( !xAbort.is() )
88 const rtl::Reference<
89 ucbhelper::InteractionSupplyAuthentication > & xSupp
90 = xRequest->getAuthenticationSupplier();
92 bool bUseSystemCredentials = false;
94 if ( bCanUseSystemCredentials )
95 bUseSystemCredentials
96 = xSupp->getUseSystemCredentials();
98 if ( bUseSystemCredentials )
100 // This is the (strange) way to tell neon to use
101 // system credentials.
102 inoutUserName.clear();
103 outPassWord.clear();
105 else
107 inoutUserName = xSupp->getUserName();
108 outPassWord = xSupp->getPassword();
111 // #102871# - Remember username and password.
112 m_aPrevUsername = inoutUserName;
113 m_aPrevPassword = outPassWord;
115 // go on.
116 return 0;
121 // Abort.
122 return -1;
126 // DAVResourceAccess Implementation.
129 DAVResourceAccess::DAVResourceAccess(
130 const uno::Reference< uno::XComponentContext > & rxContext,
131 rtl::Reference< DAVSessionFactory > const & rSessionFactory,
132 const OUString & rURL )
133 : m_aURL( rURL ),
134 m_xSessionFactory( rSessionFactory ),
135 m_xContext( rxContext )
140 DAVResourceAccess::DAVResourceAccess( const DAVResourceAccess & rOther )
141 : m_aURL( rOther.m_aURL ),
142 m_aPath( rOther.m_aPath ),
143 m_aFlags( rOther.m_aFlags ),
144 m_xSession( rOther.m_xSession ),
145 m_xSessionFactory( rOther.m_xSessionFactory ),
146 m_xContext( rOther.m_xContext ),
147 m_aRedirectURIs( rOther.m_aRedirectURIs )
152 DAVResourceAccess & DAVResourceAccess::operator=(
153 const DAVResourceAccess & rOther )
155 m_aURL = rOther.m_aURL;
156 m_aPath = rOther.m_aPath;
157 m_aFlags = rOther.m_aFlags;
158 m_xSession = rOther.m_xSession;
159 m_xSessionFactory = rOther.m_xSessionFactory;
160 m_xContext = rOther.m_xContext;
161 m_aRedirectURIs = rOther.m_aRedirectURIs;
163 return *this;
166 void DAVResourceAccess::OPTIONS(
167 DAVOptions & rOptions,
168 const css::uno::Reference<
169 css::ucb::XCommandEnvironment > & xEnv )
171 initialize();
173 int errorCount = 0;
174 bool bRetry;
177 bRetry = false;
180 DAVRequestHeaders aHeaders;
182 getUserRequestHeaders( xEnv,
183 getRequestURI(),
184 css::ucb::WebDAVHTTPMethod_OPTIONS,
185 aHeaders );
187 m_xSession->OPTIONS( getRequestURI(),
188 rOptions,
189 DAVRequestEnvironment(
190 getRequestURI(),
191 new DAVAuthListener_Impl( xEnv, m_aURL ),
192 aHeaders, xEnv ) );
194 catch ( const DAVException & e )
196 errorCount++;
197 bRetry = handleException( e, errorCount );
198 if ( !bRetry )
199 throw;
202 while ( bRetry );
205 void DAVResourceAccess::PROPFIND(
206 const Depth nDepth,
207 const std::vector< OUString > & rPropertyNames,
208 std::vector< DAVResource > & rResources,
209 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
211 initialize();
213 int errorCount = 0;
214 bool bRetry;
217 bRetry = false;
220 DAVRequestHeaders aHeaders;
222 getUserRequestHeaders( xEnv,
223 getRequestURI(),
224 ucb::WebDAVHTTPMethod_PROPFIND,
225 aHeaders );
227 m_xSession->PROPFIND( getRequestURI(),
228 nDepth,
229 rPropertyNames,
230 rResources,
231 DAVRequestEnvironment(
232 getRequestURI(),
233 new DAVAuthListener_Impl( xEnv, m_aURL ),
234 aHeaders, xEnv ) );
236 catch ( const DAVException & e )
238 errorCount++;
239 bRetry = handleException( e, errorCount );
240 if ( !bRetry )
241 throw;
244 while ( bRetry );
248 void DAVResourceAccess::PROPFIND(
249 const Depth nDepth,
250 std::vector< DAVResourceInfo > & rResInfo,
251 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
253 initialize();
255 int errorCount = 0;
256 bool bRetry;
259 bRetry = false;
262 DAVRequestHeaders aHeaders;
263 getUserRequestHeaders( xEnv,
264 getRequestURI(),
265 ucb::WebDAVHTTPMethod_PROPFIND,
266 aHeaders );
268 m_xSession->PROPFIND( getRequestURI(),
269 nDepth,
270 rResInfo,
271 DAVRequestEnvironment(
272 getRequestURI(),
273 new DAVAuthListener_Impl( xEnv, m_aURL ),
274 aHeaders, xEnv ) ) ;
276 catch ( const DAVException & e )
278 errorCount++;
279 bRetry = handleException( e, errorCount );
280 if ( !bRetry )
281 throw;
284 while ( bRetry );
288 void DAVResourceAccess::PROPPATCH(
289 const std::vector< ProppatchValue >& rValues,
290 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
292 initialize();
294 int errorCount = 0;
295 bool bRetry;
298 bRetry = false;
301 DAVRequestHeaders aHeaders;
302 getUserRequestHeaders( xEnv,
303 getRequestURI(),
304 ucb::WebDAVHTTPMethod_PROPPATCH,
305 aHeaders );
307 m_xSession->PROPPATCH( getRequestURI(),
308 rValues,
309 DAVRequestEnvironment(
310 getRequestURI(),
311 new DAVAuthListener_Impl( xEnv, m_aURL ),
312 aHeaders, xEnv ) );
314 catch ( const DAVException & e )
316 errorCount++;
317 bRetry = handleException( e, errorCount );
318 if ( !bRetry )
319 throw;
322 while ( bRetry );
326 void DAVResourceAccess::HEAD(
327 const std::vector< OUString > & rHeaderNames,
328 DAVResource & rResource,
329 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
331 initialize();
333 int errorCount = 0;
334 bool bRetry;
337 bRetry = false;
340 DAVRequestHeaders aHeaders;
341 getUserRequestHeaders( xEnv,
342 getRequestURI(),
343 ucb::WebDAVHTTPMethod_HEAD,
344 aHeaders );
346 m_xSession->HEAD( getRequestURI(),
347 rHeaderNames,
348 rResource,
349 DAVRequestEnvironment(
350 getRequestURI(),
351 new DAVAuthListener_Impl( xEnv, m_aURL ),
352 aHeaders, xEnv ) );
354 catch ( const DAVException & e )
356 errorCount++;
357 bRetry = handleException( e, errorCount );
358 if ( !bRetry )
359 throw;
362 while ( bRetry );
366 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
367 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
369 initialize();
371 uno::Reference< io::XInputStream > xStream;
372 int errorCount = 0;
373 bool bRetry;
376 bRetry = false;
379 DAVRequestHeaders aHeaders;
380 getUserRequestHeaders( xEnv,
381 getRequestURI(),
382 ucb::WebDAVHTTPMethod_GET,
383 aHeaders );
385 xStream = m_xSession->GET( getRequestURI(),
386 DAVRequestEnvironment(
387 getRequestURI(),
388 new DAVAuthListener_Impl(
389 xEnv, m_aURL ),
390 aHeaders, xEnv ) );
392 catch ( const DAVException & e )
394 errorCount++;
395 bRetry = handleException( e, errorCount );
396 if ( !bRetry )
397 throw;
400 while ( bRetry );
402 return xStream;
406 void DAVResourceAccess::GET(
407 uno::Reference< io::XOutputStream > & rStream,
408 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
410 initialize();
412 int errorCount = 0;
413 bool bRetry;
416 bRetry = false;
419 DAVRequestHeaders aHeaders;
420 getUserRequestHeaders( xEnv,
421 getRequestURI(),
422 ucb::WebDAVHTTPMethod_GET,
423 aHeaders );
425 m_xSession->GET( getRequestURI(),
426 rStream,
427 DAVRequestEnvironment(
428 getRequestURI(),
429 new DAVAuthListener_Impl( xEnv, m_aURL ),
430 aHeaders, xEnv ) );
432 catch ( const DAVException & e )
434 errorCount++;
435 bRetry = handleException( e, errorCount );
436 if ( !bRetry )
437 throw;
440 while ( bRetry );
443 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
444 const std::vector< OUString > & rHeaderNames,
445 DAVResource & rResource,
446 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
448 initialize();
450 uno::Reference< io::XInputStream > xStream;
451 int errorCount = 0;
452 bool bRetry;
455 bRetry = false;
458 DAVRequestHeaders aHeaders;
459 getUserRequestHeaders( xEnv,
460 getRequestURI(),
461 ucb::WebDAVHTTPMethod_GET,
462 aHeaders );
464 xStream = m_xSession->GET( getRequestURI(),
465 rHeaderNames,
466 rResource,
467 DAVRequestEnvironment(
468 getRequestURI(),
469 new DAVAuthListener_Impl(
470 xEnv, m_aURL ),
471 aHeaders, xEnv ) );
473 catch ( const DAVException & e )
475 errorCount++;
476 bRetry = handleException( e, errorCount );
477 if ( !bRetry )
478 throw;
481 while ( bRetry );
483 return xStream;
486 // used as HEAD substitute when HEAD is not implemented on server
487 void DAVResourceAccess::GET0(
488 DAVRequestHeaders &rRequestHeaders,
489 const std::vector< OUString > & rHeaderNames,
490 DAVResource & rResource,
491 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
493 initialize();
495 int errorCount = 0;
496 bool bRetry;
499 bRetry = false;
502 getUserRequestHeaders( xEnv,
503 getRequestURI(),
504 ucb::WebDAVHTTPMethod_GET,
505 rRequestHeaders );
507 m_xSession->GET0( getRequestURI(),
508 rHeaderNames,
509 rResource,
510 DAVRequestEnvironment(
511 getRequestURI(),
512 new DAVAuthListener_Impl(
513 xEnv, m_aURL ),
514 rRequestHeaders, xEnv ) );
516 catch ( const DAVException & e )
518 errorCount++;
519 bRetry = handleException( e, errorCount );
520 if ( !bRetry )
521 throw;
524 while ( bRetry );
528 void DAVResourceAccess::GET(
529 uno::Reference< io::XOutputStream > & rStream,
530 const std::vector< OUString > & rHeaderNames,
531 DAVResource & rResource,
532 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
534 initialize();
536 bool bRetry;
537 int errorCount = 0;
540 bRetry = false;
543 DAVRequestHeaders aHeaders;
544 getUserRequestHeaders( xEnv,
545 getRequestURI(),
546 ucb::WebDAVHTTPMethod_GET,
547 aHeaders );
549 m_xSession->GET( getRequestURI(),
550 rStream,
551 rHeaderNames,
552 rResource,
553 DAVRequestEnvironment(
554 getRequestURI(),
555 new DAVAuthListener_Impl( xEnv, m_aURL ),
556 aHeaders, xEnv ) );
558 catch ( const DAVException & e )
560 errorCount++;
561 bRetry = handleException( e, errorCount );
562 if ( !bRetry )
563 throw;
566 while ( bRetry );
570 void DAVResourceAccess::abort()
572 initialize();
573 m_xSession->abort();
577 namespace {
579 /// @throws DAVException
580 void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
584 uno::Reference< io::XSeekable > xSeekable(
585 rStream, uno::UNO_QUERY );
586 if ( xSeekable.is() )
588 xSeekable->seek( 0 );
589 return;
592 catch ( lang::IllegalArgumentException const & )
595 catch ( io::IOException const & )
599 throw DAVException( DAVException::DAV_INVALID_ARG );
602 } // namespace
605 void DAVResourceAccess::PUT(
606 const uno::Reference< io::XInputStream > & rStream,
607 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
609 initialize();
611 // Make stream seekable, if it not. Needed, if request must be retried.
612 uno::Reference< io::XInputStream > xSeekableStream
613 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
614 rStream, m_xContext );
616 int errorCount = 0;
617 bool bRetry = false;
620 if ( bRetry )
621 resetInputStream( xSeekableStream );
623 bRetry = false;
626 DAVRequestHeaders aHeaders;
627 getUserRequestHeaders( xEnv,
628 getRequestURI(),
629 ucb::WebDAVHTTPMethod_PUT,
630 aHeaders );
632 m_xSession->PUT( getRequestURI(),
633 xSeekableStream,
634 DAVRequestEnvironment(
635 getRequestURI(),
636 new DAVAuthListener_Impl( xEnv, m_aURL ),
637 aHeaders, xEnv ) );
639 catch ( const DAVException & e )
641 errorCount++;
642 bRetry = handleException( e, errorCount );
643 if ( !bRetry )
644 throw;
647 while ( bRetry );
651 uno::Reference< io::XInputStream > DAVResourceAccess::POST(
652 const OUString & rContentType,
653 const OUString & rReferer,
654 const uno::Reference< io::XInputStream > & rInputStream,
655 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
657 initialize();
659 // Make stream seekable, if it not. Needed, if request must be retried.
660 uno::Reference< io::XInputStream > xSeekableStream
661 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
662 rInputStream, m_xContext );
664 uno::Reference< io::XInputStream > xStream;
665 int errorCount = 0;
666 bool bRetry = false;
669 if ( bRetry )
671 resetInputStream( xSeekableStream );
672 bRetry = false;
677 DAVRequestHeaders aHeaders;
678 getUserRequestHeaders( xEnv,
679 getRequestURI(),
680 ucb::WebDAVHTTPMethod_POST,
681 aHeaders );
683 xStream = m_xSession->POST( getRequestURI(),
684 rContentType,
685 rReferer,
686 xSeekableStream,
687 DAVRequestEnvironment(
688 getRequestURI(),
689 new DAVAuthListener_Impl(
690 xEnv, m_aURL ),
691 aHeaders, xEnv ) );
693 catch ( const DAVException & e )
695 errorCount++;
696 bRetry = handleException( e, errorCount );
697 if ( !bRetry )
698 throw;
700 if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
702 // #i74980# - Upon POST redirect, do a GET.
703 return GET( xEnv );
707 while ( bRetry );
709 return xStream;
713 void DAVResourceAccess::POST(
714 const OUString & rContentType,
715 const OUString & rReferer,
716 const uno::Reference< io::XInputStream > & rInputStream,
717 uno::Reference< io::XOutputStream > & rOutputStream,
718 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
720 initialize();
722 // Make stream seekable, if it not. Needed, if request must be retried.
723 uno::Reference< io::XInputStream > xSeekableStream
724 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
725 rInputStream, m_xContext );
727 int errorCount = 0;
728 bool bRetry = false;
731 if ( bRetry )
733 resetInputStream( xSeekableStream );
734 bRetry = false;
739 DAVRequestHeaders aHeaders;
740 getUserRequestHeaders( xEnv,
741 getRequestURI(),
742 ucb::WebDAVHTTPMethod_POST,
743 aHeaders );
745 m_xSession->POST( getRequestURI(),
746 rContentType,
747 rReferer,
748 xSeekableStream,
749 rOutputStream,
750 DAVRequestEnvironment(
751 getRequestURI(),
752 new DAVAuthListener_Impl( xEnv, m_aURL ),
753 aHeaders, xEnv ) );
755 catch ( const DAVException & e )
757 errorCount++;
758 bRetry = handleException( e, errorCount );
759 if ( !bRetry )
760 throw;
762 if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
764 // #i74980# - Upon POST redirect, do a GET.
765 GET( rOutputStream, xEnv );
766 return;
770 while ( bRetry );
774 void DAVResourceAccess::MKCOL(
775 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
777 initialize();
779 int errorCount = 0;
780 bool bRetry;
783 bRetry = false;
786 DAVRequestHeaders aHeaders;
787 getUserRequestHeaders( xEnv,
788 getRequestURI(),
789 ucb::WebDAVHTTPMethod_MKCOL,
790 aHeaders );
792 m_xSession->MKCOL( getRequestURI(),
793 DAVRequestEnvironment(
794 getRequestURI(),
795 new DAVAuthListener_Impl( xEnv, m_aURL ),
796 aHeaders, xEnv ) );
798 catch ( const DAVException & e )
800 errorCount++;
801 bRetry = handleException( e, errorCount );
802 if ( !bRetry )
803 throw;
806 while ( bRetry );
810 void DAVResourceAccess::COPY(
811 const OUString & rSourcePath,
812 const OUString & rDestinationURI,
813 bool bOverwrite,
814 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
816 initialize();
818 int errorCount = 0;
819 bool bRetry;
822 bRetry = false;
825 DAVRequestHeaders aHeaders;
826 getUserRequestHeaders( xEnv,
827 getRequestURI(),
828 ucb::WebDAVHTTPMethod_COPY,
829 aHeaders );
831 m_xSession->COPY( rSourcePath,
832 rDestinationURI,
833 DAVRequestEnvironment(
834 getRequestURI(),
835 new DAVAuthListener_Impl( xEnv, m_aURL ),
836 aHeaders, xEnv ),
837 bOverwrite );
839 catch ( const DAVException & e )
841 errorCount++;
842 bRetry = handleException( e, errorCount );
843 if ( !bRetry )
844 throw;
847 while ( bRetry );
851 void DAVResourceAccess::MOVE(
852 const OUString & rSourcePath,
853 const OUString & rDestinationURI,
854 bool bOverwrite,
855 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
857 initialize();
859 int errorCount = 0;
860 bool bRetry;
863 bRetry = false;
866 DAVRequestHeaders aHeaders;
867 getUserRequestHeaders( xEnv,
868 getRequestURI(),
869 ucb::WebDAVHTTPMethod_MOVE,
870 aHeaders );
872 m_xSession->MOVE( rSourcePath,
873 rDestinationURI,
874 DAVRequestEnvironment(
875 getRequestURI(),
876 new DAVAuthListener_Impl( xEnv, m_aURL ),
877 aHeaders, xEnv ),
878 bOverwrite );
880 catch ( const DAVException & e )
882 errorCount++;
883 bRetry = handleException( e, errorCount );
884 if ( !bRetry )
885 throw;
888 while ( bRetry );
892 void DAVResourceAccess::DESTROY(
893 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
895 initialize();
897 int errorCount = 0;
898 bool bRetry;
901 bRetry = false;
904 DAVRequestHeaders aHeaders;
905 getUserRequestHeaders( xEnv,
906 getRequestURI(),
907 ucb::WebDAVHTTPMethod_DELETE,
908 aHeaders );
910 m_xSession->DESTROY( getRequestURI(),
911 DAVRequestEnvironment(
912 getRequestURI(),
913 new DAVAuthListener_Impl( xEnv, m_aURL ),
914 aHeaders, xEnv ) );
916 catch ( const DAVException & e )
918 errorCount++;
919 bRetry = handleException( e, errorCount );
920 if ( !bRetry )
921 throw;
924 while ( bRetry );
928 // set new lock.
929 void DAVResourceAccess::LOCK(
930 ucb::Lock & inLock,
931 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
933 initialize();
935 int errorCount = 0;
936 bool bRetry;
939 bRetry = false;
942 DAVRequestHeaders aHeaders;
943 getUserRequestHeaders( xEnv,
944 getRequestURI(),
945 ucb::WebDAVHTTPMethod_LOCK,
946 aHeaders );
948 m_xSession->LOCK( getRequestURI(),
949 inLock,
950 DAVRequestEnvironment(
951 getRequestURI(),
952 new DAVAuthListener_Impl( xEnv, m_aURL ),
953 aHeaders, xEnv ) );
955 catch ( const DAVException & e )
957 errorCount++;
958 bRetry = handleException( e, errorCount );
959 if ( !bRetry )
960 throw;
963 while ( bRetry );
966 void DAVResourceAccess::UNLOCK(
967 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
969 initialize();
971 int errorCount = 0;
972 bool bRetry;
975 bRetry = false;
978 DAVRequestHeaders aHeaders;
979 getUserRequestHeaders( xEnv,
980 getRequestURI(),
981 ucb::WebDAVHTTPMethod_UNLOCK,
982 aHeaders );
984 m_xSession->UNLOCK( getRequestURI(),
985 DAVRequestEnvironment(
986 getRequestURI(),
987 new DAVAuthListener_Impl( xEnv, m_aURL ),
988 aHeaders, xEnv ) );
990 catch ( const DAVException & e )
992 errorCount++;
993 bRetry = handleException( e, errorCount );
994 if ( !bRetry )
995 throw;
998 while ( bRetry );
1002 void DAVResourceAccess::setFlags( const uno::Sequence< beans::NamedValue >& rFlags )
1004 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1005 m_aFlags = rFlags;
1009 void DAVResourceAccess::setURL( const OUString & rNewURL )
1011 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1012 m_aURL = rNewURL;
1013 m_aPath.clear(); // Next initialize() will create new session.
1017 // init dav session and path
1018 void DAVResourceAccess::initialize()
1020 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1021 if ( m_aPath.isEmpty() )
1023 NeonUri aURI( m_aURL );
1024 const OUString& aPath( aURI.GetPath() );
1026 /* #134089# - Check URI */
1027 if ( aPath.isEmpty() )
1028 throw DAVException( DAVException::DAV_INVALID_ARG );
1030 /* #134089# - Check URI */
1031 if ( aURI.GetHost().isEmpty() )
1032 throw DAVException( DAVException::DAV_INVALID_ARG );
1034 if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL, m_aFlags ) )
1036 m_xSession.clear();
1038 // create new webdav session
1039 m_xSession
1040 = m_xSessionFactory->createDAVSession( m_aURL, m_aFlags, m_xContext );
1042 if ( !m_xSession.is() )
1043 return;
1046 // Own URI is needed to redirect cycle detection.
1047 m_aRedirectURIs.push_back( aURI );
1049 // Success.
1050 m_aPath = aPath;
1052 // Not only the path has to be encoded
1053 m_aURL = aURI.GetURI();
1058 const OUString & DAVResourceAccess::getRequestURI() const
1060 assert( m_xSession.is() && "DAVResourceAccess::getRequestURI - Not initialized!" );
1062 // In case a proxy is used we have to use the absolute URI for a request.
1063 if ( m_xSession->UsesProxy() )
1064 return m_aURL;
1066 return m_aPath;
1070 // static
1071 void DAVResourceAccess::getUserRequestHeaders(
1072 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
1073 const OUString & rURI,
1074 ucb::WebDAVHTTPMethod eMethod,
1075 DAVRequestHeaders & rRequestHeaders )
1077 if ( xEnv.is() )
1079 uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
1080 xEnv, uno::UNO_QUERY );
1082 if ( xDAVEnv.is() )
1084 const uno::Sequence< beans::StringPair > aRequestHeaders
1085 = xDAVEnv->getUserRequestHeaders( rURI, eMethod );
1087 for ( const auto& rRequestHeader : aRequestHeaders )
1089 rRequestHeaders.emplace_back(
1090 rRequestHeader.First,
1091 rRequestHeader.Second );
1096 // Make sure a User-Agent header is always included, as at least
1097 // en.wikipedia.org:80 forces back 403 "Scripts should use an informative
1098 // User-Agent string with contact information, or they may be IP-blocked
1099 // without notice" otherwise:
1100 if ( std::any_of(rRequestHeaders.begin(), rRequestHeaders.end(),
1101 [](const DAVRequestHeader& rHeader) { return rHeader.first.equalsIgnoreAsciiCase( "User-Agent" ); }) )
1103 return;
1105 rRequestHeaders.emplace_back( "User-Agent", "LibreOffice" );
1108 // This function member implements the control on cyclical redirections
1109 bool DAVResourceAccess::detectRedirectCycle(
1110 const OUString& rRedirectURL )
1112 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1114 NeonUri aUri( rRedirectURL );
1116 // Check for maximum number of redirections
1117 // according to <https://tools.ietf.org/html/rfc7231#section-6.4>.
1118 // A practical limit may be 5, due to earlier specifications:
1119 // <https://tools.ietf.org/html/rfc2068#section-10.3>
1120 // it can be raised keeping in mind the added net activity.
1121 if( static_cast< size_t >( g_nRedirectLimit ) <= m_aRedirectURIs.size() )
1122 return true;
1124 // try to detect a cyclical redirection
1125 return std::any_of(m_aRedirectURIs.begin(), m_aRedirectURIs.end(),
1126 [&aUri](const NeonUri& rUri) {
1127 // if equal, cyclical redirection detected
1128 return aUri == rUri; });
1132 void DAVResourceAccess::resetUri()
1134 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1135 if ( !m_aRedirectURIs.empty() )
1137 std::vector< NeonUri >::const_iterator it = m_aRedirectURIs.begin();
1139 NeonUri aUri( *it );
1140 m_aRedirectURIs.clear();
1141 setURL ( aUri.GetURI() );
1142 initialize();
1147 bool DAVResourceAccess::handleException( const DAVException & e, int errorCount )
1149 switch ( e.getError() )
1151 case DAVException::DAV_HTTP_REDIRECT:
1152 if ( !detectRedirectCycle( e.getData() ) )
1154 // set new URL and path.
1155 setURL( e.getData() );
1156 initialize();
1157 return true;
1159 return false;
1160 // #67048# copy & paste images doesn't display. This bug refers
1161 // to an old OOo problem about getting resources from sites with a bad connection.
1162 // If we have a bad connection try again. Up to three times.
1163 case DAVException::DAV_HTTP_ERROR:
1164 // retry up to three times, if not a client-side error (4xx error codes)
1165 if ( e.getStatus() < SC_BAD_REQUEST && errorCount < 3 )
1166 return true;
1167 // check the server side errors
1168 switch( e.getStatus() )
1170 // the HTTP server side response status codes that can be retried
1171 case SC_BAD_GATEWAY: // retry, can be an excessive load
1172 case SC_GATEWAY_TIMEOUT: // retry, may be we get lucky
1173 case SC_SERVICE_UNAVAILABLE: // retry, the service may become available
1174 case SC_INSUFFICIENT_STORAGE: // space may be freed, retry
1176 return errorCount < 3;
1178 break;
1179 // all the other HTTP server response status codes are NOT retry
1180 default:
1181 return false;
1183 break;
1184 // if connection has said retry then retry!
1185 case DAVException::DAV_HTTP_RETRY:
1186 return true;
1187 default:
1188 return false; // Abort
1192 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */