Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / ucb / source / ucp / webdav-curl / DAVResourceAccess.cxx
blobfa324b0493e9ec4a3b6d631b93dc2d584536036a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/task/XInteractionAbort.hpp>
22 #include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
24 #include <ucbhelper/simpleauthenticationrequest.hxx>
25 #include <comphelper/seekableinput.hxx>
27 #include "DAVAuthListenerImpl.hxx"
28 #include "DAVResourceAccess.hxx"
30 #include <com/sun/star/lang/IllegalArgumentException.hpp>
31 #include <com/sun/star/io/IOException.hpp>
32 #include <utility>
34 using namespace http_dav_ucp;
35 using namespace com::sun::star;
38 // DAVAuthListener_Impl Implementation.
41 // virtual
42 int DAVAuthListener_Impl::authenticate(
43 const OUString & inRealm,
44 const OUString & inHostName,
45 OUString & inoutUserName,
46 OUString & outPassWord,
47 bool bCanUseSystemCredentials,
48 bool bUsePreviousCredentials )
50 if ( m_xEnv.is() )
52 uno::Reference< task::XInteractionHandler > xIH
53 = m_xEnv->getInteractionHandler();
55 if ( xIH.is() )
57 // Providing previously retrieved credentials will cause the password
58 // container to reject these. Thus, the credential input dialog will be shown again.
59 // #102871# - Supply username and password from previous try.
60 // Password container service depends on this!
61 if ( inoutUserName.isEmpty() && bUsePreviousCredentials )
62 inoutUserName = m_aPrevUsername;
64 if ( outPassWord.isEmpty() && bUsePreviousCredentials )
65 outPassWord = m_aPrevPassword;
67 rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
68 = new ucbhelper::SimpleAuthenticationRequest(
69 m_aURL, inHostName, inRealm, inoutUserName,
70 outPassWord,
71 bCanUseSystemCredentials );
72 xIH->handle( xRequest );
74 rtl::Reference< ucbhelper::InteractionContinuation > xSelection
75 = xRequest->getSelection();
77 if ( xSelection.is() )
79 // Handler handled the request.
80 uno::Reference< task::XInteractionAbort > xAbort(
81 xSelection.get(), uno::UNO_QUERY );
82 if ( !xAbort.is() )
84 const rtl::Reference<
85 ucbhelper::InteractionSupplyAuthentication > & xSupp
86 = xRequest->getAuthenticationSupplier();
88 bool bUseSystemCredentials = false;
90 if ( bCanUseSystemCredentials )
91 bUseSystemCredentials
92 = xSupp->getUseSystemCredentials();
94 if ( bUseSystemCredentials )
96 // This is the (strange) way to tell neon to use
97 // system credentials.
98 inoutUserName.clear();
99 outPassWord.clear();
101 else
103 inoutUserName = xSupp->getUserName();
104 outPassWord = xSupp->getPassword();
107 // #102871# - Remember username and password.
108 m_aPrevUsername = inoutUserName;
109 m_aPrevPassword = outPassWord;
111 // go on.
112 return 0;
117 // Abort.
118 return -1;
122 // DAVResourceAccess Implementation.
124 constexpr size_t g_nRedirectLimit = 5;
126 DAVResourceAccess::DAVResourceAccess(
127 uno::Reference< uno::XComponentContext > xContext,
128 rtl::Reference< DAVSessionFactory > xSessionFactory,
129 OUString aURL )
130 : m_aURL(std::move( aURL )),
131 m_xSessionFactory(std::move( xSessionFactory )),
132 m_xContext(std::move( xContext ))
137 DAVResourceAccess::DAVResourceAccess( const DAVResourceAccess & rOther )
138 : m_aURL( rOther.m_aURL ),
139 m_aPath( rOther.m_aPath ),
140 m_aFlags( rOther.m_aFlags ),
141 m_xSession( rOther.m_xSession ),
142 m_xSessionFactory( rOther.m_xSessionFactory ),
143 m_xContext( rOther.m_xContext ),
144 m_aRedirectURIs( rOther.m_aRedirectURIs )
149 DAVResourceAccess & DAVResourceAccess::operator=(
150 const DAVResourceAccess & rOther )
152 m_aURL = rOther.m_aURL;
153 m_aPath = rOther.m_aPath;
154 m_aFlags = rOther.m_aFlags;
155 m_xSession = rOther.m_xSession;
156 m_xSessionFactory = rOther.m_xSessionFactory;
157 m_xContext = rOther.m_xContext;
158 m_aRedirectURIs = rOther.m_aRedirectURIs;
160 return *this;
163 void DAVResourceAccess::OPTIONS(
164 DAVOptions & rOptions,
165 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
167 initialize();
169 int errorCount = 0;
170 bool bRetry;
173 bRetry = false;
176 DAVRequestHeaders aHeaders;
178 getUserRequestHeaders( xEnv,
179 getRequestURI(),
180 ucb::WebDAVHTTPMethod_OPTIONS,
181 aHeaders );
183 m_xSession->OPTIONS( getRequestURI(),
184 rOptions,
185 DAVRequestEnvironment(
186 new DAVAuthListener_Impl( xEnv, m_aURL ),
187 aHeaders ) );
189 catch (DAVException const& e)
191 errorCount++;
192 bRetry = handleException( e, errorCount );
193 if ( !bRetry )
194 throw;
197 while ( bRetry );
200 void DAVResourceAccess::PROPFIND(
201 const Depth nDepth,
202 const std::vector< OUString > & rPropertyNames,
203 std::vector< DAVResource > & rResources,
204 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
206 initialize();
208 int errorCount = 0;
209 bool bRetry;
212 bRetry = false;
215 DAVRequestHeaders aHeaders;
217 getUserRequestHeaders( xEnv,
218 getRequestURI(),
219 ucb::WebDAVHTTPMethod_PROPFIND,
220 aHeaders );
222 m_xSession->PROPFIND( getRequestURI(),
223 nDepth,
224 rPropertyNames,
225 rResources,
226 DAVRequestEnvironment(
227 new DAVAuthListener_Impl( xEnv, m_aURL ),
228 aHeaders ) );
230 catch (DAVException const& e)
232 errorCount++;
233 bRetry = handleException( e, errorCount );
234 if ( !bRetry )
235 throw;
238 while ( bRetry );
242 void DAVResourceAccess::PROPFIND(
243 const Depth nDepth,
244 std::vector< DAVResourceInfo > & rResInfo,
245 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
247 initialize();
249 int errorCount = 0;
250 bool bRetry;
253 bRetry = false;
256 DAVRequestHeaders aHeaders;
257 getUserRequestHeaders( xEnv,
258 getRequestURI(),
259 ucb::WebDAVHTTPMethod_PROPFIND,
260 aHeaders );
262 m_xSession->PROPFIND( getRequestURI(),
263 nDepth,
264 rResInfo,
265 DAVRequestEnvironment(
266 new DAVAuthListener_Impl( xEnv, m_aURL ),
267 aHeaders ) ) ;
269 catch (DAVException const& e)
271 errorCount++;
272 bRetry = handleException( e, errorCount );
273 if ( !bRetry )
274 throw;
277 while ( bRetry );
281 void DAVResourceAccess::PROPPATCH(
282 const std::vector< ProppatchValue >& rValues,
283 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
285 initialize();
287 int errorCount = 0;
288 bool bRetry;
291 bRetry = false;
294 DAVRequestHeaders aHeaders;
295 getUserRequestHeaders( xEnv,
296 getRequestURI(),
297 ucb::WebDAVHTTPMethod_PROPPATCH,
298 aHeaders );
300 m_xSession->PROPPATCH( getRequestURI(),
301 rValues,
302 DAVRequestEnvironment(
303 new DAVAuthListener_Impl( xEnv, m_aURL ),
304 aHeaders ) );
306 catch (DAVException const& e)
308 errorCount++;
309 bRetry = handleException( e, errorCount );
310 if ( !bRetry )
311 throw;
314 while ( bRetry );
318 void DAVResourceAccess::HEAD(
319 const std::vector< OUString > & rHeaderNames,
320 DAVResource & rResource,
321 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
323 initialize();
325 int errorCount = 0;
326 bool bRetry;
329 bRetry = false;
332 DAVRequestHeaders aHeaders;
333 getUserRequestHeaders( xEnv,
334 getRequestURI(),
335 ucb::WebDAVHTTPMethod_HEAD,
336 aHeaders );
338 m_xSession->HEAD( getRequestURI(),
339 rHeaderNames,
340 rResource,
341 DAVRequestEnvironment(
342 new DAVAuthListener_Impl( xEnv, m_aURL ),
343 aHeaders ) );
345 catch (DAVException const& e)
347 errorCount++;
348 bRetry = handleException( e, errorCount );
349 if ( !bRetry )
350 throw;
353 while ( bRetry );
357 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
358 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
360 initialize();
362 uno::Reference< io::XInputStream > xStream;
363 int errorCount = 0;
364 bool bRetry;
367 bRetry = false;
370 DAVRequestHeaders aHeaders;
371 getUserRequestHeaders( xEnv,
372 getRequestURI(),
373 ucb::WebDAVHTTPMethod_GET,
374 aHeaders );
376 xStream = m_xSession->GET( getRequestURI(),
377 DAVRequestEnvironment(
378 new DAVAuthListener_Impl(
379 xEnv, m_aURL ),
380 aHeaders ) );
382 catch (DAVException const& e)
384 errorCount++;
385 bRetry = handleException( e, errorCount );
386 if ( !bRetry )
387 throw;
390 while ( bRetry );
392 return xStream;
396 void DAVResourceAccess::GET(
397 uno::Reference< io::XOutputStream > & rStream,
398 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
400 initialize();
402 int errorCount = 0;
403 bool bRetry;
406 bRetry = false;
409 DAVRequestHeaders aHeaders;
410 getUserRequestHeaders( xEnv,
411 getRequestURI(),
412 ucb::WebDAVHTTPMethod_GET,
413 aHeaders );
415 m_xSession->GET( getRequestURI(),
416 rStream,
417 DAVRequestEnvironment(
418 new DAVAuthListener_Impl( xEnv, m_aURL ),
419 aHeaders ) );
421 catch (DAVException const& e)
423 errorCount++;
424 bRetry = handleException( e, errorCount );
425 if ( !bRetry )
426 throw;
429 while ( bRetry );
433 uno::Reference< io::XInputStream > DAVResourceAccess::GET(
434 const std::vector< OUString > & rHeaderNames,
435 DAVResource & rResource,
436 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
438 initialize();
440 uno::Reference< io::XInputStream > xStream;
441 int errorCount = 0;
442 bool bRetry;
445 bRetry = false;
448 DAVRequestHeaders aHeaders;
449 getUserRequestHeaders( xEnv,
450 getRequestURI(),
451 ucb::WebDAVHTTPMethod_GET,
452 aHeaders );
454 xStream = m_xSession->GET( getRequestURI(),
455 rHeaderNames,
456 rResource,
457 DAVRequestEnvironment(
458 new DAVAuthListener_Impl(
459 xEnv, m_aURL ),
460 aHeaders ) );
462 catch (DAVException const& e)
464 errorCount++;
465 bRetry = handleException( e, errorCount );
466 if ( !bRetry )
467 throw;
470 while ( bRetry );
472 return xStream;
476 // used as HEAD substitute when HEAD is not implemented on server
477 void DAVResourceAccess::GET0(
478 DAVRequestHeaders &rRequestHeaders,
479 const std::vector< OUString > & rHeaderNames,
480 DAVResource & rResource,
481 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
483 initialize();
485 int errorCount = 0;
486 bool bRetry;
489 bRetry = false;
492 getUserRequestHeaders( xEnv,
493 getRequestURI(),
494 ucb::WebDAVHTTPMethod_GET,
495 rRequestHeaders );
497 m_xSession->GET( getRequestURI(),
498 rHeaderNames,
499 rResource,
500 DAVRequestEnvironment(
501 new DAVAuthListener_Impl(
502 xEnv, m_aURL ),
503 rRequestHeaders ) );
505 catch (DAVException const& e)
507 errorCount++;
508 bRetry = handleException( e, errorCount );
509 if ( !bRetry )
510 throw;
513 while ( bRetry );
517 void DAVResourceAccess::GET(
518 uno::Reference< io::XOutputStream > & rStream,
519 const std::vector< OUString > & rHeaderNames,
520 DAVResource & rResource,
521 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
523 initialize();
525 bool bRetry;
526 int errorCount = 0;
529 bRetry = false;
532 DAVRequestHeaders aHeaders;
533 getUserRequestHeaders( xEnv,
534 getRequestURI(),
535 ucb::WebDAVHTTPMethod_GET,
536 aHeaders );
538 m_xSession->GET( getRequestURI(),
539 rStream,
540 rHeaderNames,
541 rResource,
542 DAVRequestEnvironment(
543 new DAVAuthListener_Impl( xEnv, m_aURL ),
544 aHeaders ) );
546 catch (DAVException const& e)
548 errorCount++;
549 bRetry = handleException( e, errorCount );
550 if ( !bRetry )
551 throw;
554 while ( bRetry );
558 void DAVResourceAccess::abort()
560 // seems pointless to call initialize() here, but prepare for nullptr
561 decltype(m_xSession) xSession;
563 osl::Guard<osl::Mutex> const g(m_aMutex);
564 xSession = m_xSession;
566 if (xSession.is())
568 xSession->abort();
573 namespace {
575 /// @throws DAVException
576 void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
580 uno::Reference< io::XSeekable > xSeekable(
581 rStream, uno::UNO_QUERY );
582 if ( xSeekable.is() )
584 xSeekable->seek( 0 );
585 return;
588 catch ( lang::IllegalArgumentException const & )
591 catch ( io::IOException const & )
595 throw DAVException( DAVException::DAV_INVALID_ARG );
598 } // namespace
601 void DAVResourceAccess::PUT(
602 const uno::Reference< io::XInputStream > & rStream,
603 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
605 initialize();
607 // Make stream seekable, if it not. Needed, if request must be retried.
608 uno::Reference< io::XInputStream > xSeekableStream
609 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
610 rStream, m_xContext );
612 int errorCount = 0;
613 bool bRetry = false;
616 if ( bRetry )
617 resetInputStream( xSeekableStream );
619 bRetry = false;
622 DAVRequestHeaders aHeaders;
623 getUserRequestHeaders( xEnv,
624 getRequestURI(),
625 ucb::WebDAVHTTPMethod_PUT,
626 aHeaders );
628 m_xSession->PUT( getRequestURI(),
629 xSeekableStream,
630 DAVRequestEnvironment(
631 new DAVAuthListener_Impl( xEnv, m_aURL ),
632 aHeaders ) );
634 catch (DAVException const& e)
636 errorCount++;
637 bRetry = handleException( e, errorCount );
638 if ( !bRetry )
639 throw;
642 while ( bRetry );
646 uno::Reference< io::XInputStream > DAVResourceAccess::POST(
647 const OUString & rContentType,
648 const OUString & rReferer,
649 const uno::Reference< io::XInputStream > & rInputStream,
650 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
652 initialize();
654 // Make stream seekable, if it not. Needed, if request must be retried.
655 uno::Reference< io::XInputStream > xSeekableStream
656 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
657 rInputStream, m_xContext );
659 uno::Reference< io::XInputStream > xStream;
660 int errorCount = 0;
661 bool bRetry = false;
664 if ( bRetry )
666 resetInputStream( xSeekableStream );
667 bRetry = false;
672 DAVRequestHeaders aHeaders;
673 getUserRequestHeaders( xEnv,
674 getRequestURI(),
675 ucb::WebDAVHTTPMethod_POST,
676 aHeaders );
678 xStream = m_xSession->POST( getRequestURI(),
679 rContentType,
680 rReferer,
681 xSeekableStream,
682 DAVRequestEnvironment(
683 new DAVAuthListener_Impl(
684 xEnv, m_aURL ),
685 aHeaders ) );
687 catch (DAVException const& e)
689 errorCount++;
690 bRetry = handleException( e, errorCount );
691 if ( !bRetry )
692 throw;
694 if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
696 // #i74980# - Upon POST redirect, do a GET.
697 return GET( xEnv );
701 while ( bRetry );
703 return xStream;
707 void DAVResourceAccess::POST(
708 const OUString & rContentType,
709 const OUString & rReferer,
710 const uno::Reference< io::XInputStream > & rInputStream,
711 uno::Reference< io::XOutputStream > & rOutputStream,
712 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
714 initialize();
716 // Make stream seekable, if it not. Needed, if request must be retried.
717 uno::Reference< io::XInputStream > xSeekableStream
718 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
719 rInputStream, m_xContext );
721 int errorCount = 0;
722 bool bRetry = false;
725 if ( bRetry )
727 resetInputStream( xSeekableStream );
728 bRetry = false;
733 DAVRequestHeaders aHeaders;
734 getUserRequestHeaders( xEnv,
735 getRequestURI(),
736 ucb::WebDAVHTTPMethod_POST,
737 aHeaders );
739 m_xSession->POST( getRequestURI(),
740 rContentType,
741 rReferer,
742 xSeekableStream,
743 rOutputStream,
744 DAVRequestEnvironment(
745 new DAVAuthListener_Impl( xEnv, m_aURL ),
746 aHeaders ) );
748 catch (DAVException const& e)
750 errorCount++;
751 bRetry = handleException( e, errorCount );
752 if ( !bRetry )
753 throw;
755 if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
757 // #i74980# - Upon POST redirect, do a GET.
758 GET( rOutputStream, xEnv );
759 return;
763 while ( bRetry );
767 void DAVResourceAccess::MKCOL(
768 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
770 initialize();
772 int errorCount = 0;
773 bool bRetry;
776 bRetry = false;
779 DAVRequestHeaders aHeaders;
780 getUserRequestHeaders( xEnv,
781 getRequestURI(),
782 ucb::WebDAVHTTPMethod_MKCOL,
783 aHeaders );
785 m_xSession->MKCOL( getRequestURI(),
786 DAVRequestEnvironment(
787 new DAVAuthListener_Impl( xEnv, m_aURL ),
788 aHeaders ) );
790 catch (DAVException const& e)
792 errorCount++;
793 bRetry = handleException( e, errorCount );
794 if ( !bRetry )
795 throw;
798 while ( bRetry );
802 void DAVResourceAccess::COPY(
803 const OUString & rSourcePath,
804 const OUString & rDestinationURI,
805 bool bOverwrite,
806 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
808 initialize();
810 int errorCount = 0;
811 bool bRetry;
814 bRetry = false;
817 DAVRequestHeaders aHeaders;
818 getUserRequestHeaders( xEnv,
819 getRequestURI(),
820 ucb::WebDAVHTTPMethod_COPY,
821 aHeaders );
823 m_xSession->COPY( rSourcePath,
824 rDestinationURI,
825 DAVRequestEnvironment(
826 new DAVAuthListener_Impl( xEnv, m_aURL ),
827 aHeaders ),
828 bOverwrite );
830 catch (DAVException const& e)
832 errorCount++;
833 bRetry = handleException( e, errorCount );
834 if ( !bRetry )
835 throw;
838 while ( bRetry );
842 void DAVResourceAccess::MOVE(
843 const OUString & rSourcePath,
844 const OUString & rDestinationURI,
845 bool bOverwrite,
846 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
848 initialize();
850 int errorCount = 0;
851 bool bRetry;
854 bRetry = false;
857 DAVRequestHeaders aHeaders;
858 getUserRequestHeaders( xEnv,
859 getRequestURI(),
860 ucb::WebDAVHTTPMethod_MOVE,
861 aHeaders );
863 m_xSession->MOVE( rSourcePath,
864 rDestinationURI,
865 DAVRequestEnvironment(
866 new DAVAuthListener_Impl( xEnv, m_aURL ),
867 aHeaders ),
868 bOverwrite );
870 catch (DAVException const& e)
872 errorCount++;
873 bRetry = handleException( e, errorCount );
874 if ( !bRetry )
875 throw;
878 while ( bRetry );
882 void DAVResourceAccess::DESTROY(
883 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
885 initialize();
887 int errorCount = 0;
888 bool bRetry;
891 bRetry = false;
894 DAVRequestHeaders aHeaders;
895 getUserRequestHeaders( xEnv,
896 getRequestURI(),
897 ucb::WebDAVHTTPMethod_DELETE,
898 aHeaders );
900 m_xSession->DESTROY( getRequestURI(),
901 DAVRequestEnvironment(
902 new DAVAuthListener_Impl( xEnv, m_aURL ),
903 aHeaders ) );
905 catch (DAVException const& e)
907 errorCount++;
908 bRetry = handleException( e, errorCount );
909 if ( !bRetry )
910 throw;
913 while ( bRetry );
917 // set new lock.
918 void DAVResourceAccess::LOCK(
919 ucb::Lock & inLock,
920 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
922 initialize();
924 int errorCount = 0;
925 bool bRetry;
928 bRetry = false;
931 DAVRequestHeaders aHeaders;
932 getUserRequestHeaders( xEnv,
933 getRequestURI(),
934 ucb::WebDAVHTTPMethod_LOCK,
935 aHeaders );
937 m_xSession->LOCK( getRequestURI(),
938 inLock,
939 DAVRequestEnvironment(
940 new DAVAuthListener_Impl( xEnv, m_aURL ),
941 aHeaders ) );
943 catch (DAVException const& e)
945 errorCount++;
946 bRetry = handleException( e, errorCount );
947 if ( !bRetry )
948 throw;
951 while ( bRetry );
954 void DAVResourceAccess::UNLOCK(
955 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
957 initialize();
959 int errorCount = 0;
960 bool bRetry;
963 bRetry = false;
966 DAVRequestHeaders aHeaders;
967 getUserRequestHeaders( xEnv,
968 getRequestURI(),
969 ucb::WebDAVHTTPMethod_UNLOCK,
970 aHeaders );
972 m_xSession->UNLOCK( getRequestURI(),
973 DAVRequestEnvironment(
974 new DAVAuthListener_Impl( xEnv, m_aURL ),
975 aHeaders ) );
977 catch (DAVException const& e)
979 errorCount++;
980 bRetry = handleException( e, errorCount );
981 if ( !bRetry )
982 throw;
985 while ( bRetry );
988 void DAVResourceAccess::setFlags( const uno::Sequence< beans::NamedValue >& rFlags )
990 osl::Guard< osl::Mutex > aGuard( m_aMutex );
991 m_aFlags = rFlags;
994 void DAVResourceAccess::setURL( const OUString & rNewURL )
996 osl::Guard< osl::Mutex > aGuard( m_aMutex );
997 m_aURL = rNewURL;
998 m_aPath.clear(); // Next initialize() will create new session.
1002 // init dav session and path
1003 void DAVResourceAccess::initialize()
1005 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1006 if ( m_aPath.isEmpty() )
1008 CurlUri const aURI( m_aURL );
1009 OUString aPath( aURI.GetRelativeReference() );
1011 /* #134089# - Check URI */
1012 if ( aPath.isEmpty() )
1013 throw DAVException( DAVException::DAV_INVALID_ARG );
1015 /* #134089# - Check URI */
1016 if ( aURI.GetHost().isEmpty() )
1017 throw DAVException( DAVException::DAV_INVALID_ARG );
1019 if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL, m_aFlags ) )
1021 m_xSession.clear();
1023 // create new webdav session
1024 m_xSession
1025 = m_xSessionFactory->createDAVSession( m_aURL, m_aFlags, m_xContext );
1027 if ( !m_xSession.is() )
1028 return;
1031 // Own URI is needed to redirect cycle detection.
1032 m_aRedirectURIs.push_back( aURI );
1034 // Success.
1035 m_aPath = aPath;
1037 // Not only the path has to be encoded
1038 m_aURL = aURI.GetURI();
1043 const OUString & DAVResourceAccess::getRequestURI() const
1045 assert(m_xSession.is() &&
1046 "DAVResourceAccess::getRequestURI - Not initialized!");
1048 // In case a proxy is used we have to use the absolute URI for a request.
1049 if ( m_xSession->UsesProxy() )
1050 return m_aURL;
1052 return m_aPath;
1056 // static
1057 void DAVResourceAccess::getUserRequestHeaders(
1058 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
1059 const OUString & rURI,
1060 ucb::WebDAVHTTPMethod eMethod,
1061 DAVRequestHeaders & rRequestHeaders )
1063 if ( !xEnv.is() )
1064 return;
1066 uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
1067 xEnv, uno::UNO_QUERY );
1069 if ( !xDAVEnv.is() )
1070 return;
1072 uno::Sequence< beans::StringPair > aRequestHeaders
1073 = xDAVEnv->getUserRequestHeaders( rURI, eMethod );
1075 for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n )
1077 rRequestHeaders.push_back(
1078 DAVRequestHeader( aRequestHeaders[ n ].First,
1079 aRequestHeaders[ n ].Second ) );
1083 // This function member implements the control on cyclical redirections
1084 bool DAVResourceAccess::detectRedirectCycle(
1085 ::std::u16string_view const rRedirectURL)
1087 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1089 CurlUri const aUri( rRedirectURL );
1091 // Check for maximum number of redirections
1092 // according to <https://tools.ietf.org/html/rfc7231#section-6.4>.
1093 // A practical limit may be 5, due to earlier specifications:
1094 // <https://tools.ietf.org/html/rfc2068#section-10.3>
1095 // it can be raised keeping in mind the added net activity.
1096 if( g_nRedirectLimit <= m_aRedirectURIs.size() )
1097 return true;
1099 // try to detect a cyclical redirection
1100 return std::any_of(m_aRedirectURIs.begin(), m_aRedirectURIs.end(),
1101 [&aUri](const CurlUri& rUri) { return aUri == rUri; });
1105 void DAVResourceAccess::resetUri()
1107 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1108 if ( ! m_aRedirectURIs.empty() )
1110 auto const it = m_aRedirectURIs.begin();
1112 CurlUri const aUri( *it );
1113 m_aRedirectURIs.clear();
1114 setURL ( aUri.GetURI() );
1115 initialize();
1120 bool DAVResourceAccess::handleException(DAVException const& e, int const errorCount)
1122 switch ( e.getError() )
1124 case DAVException::DAV_HTTP_REDIRECT:
1125 if ( !detectRedirectCycle( e.getData() ) )
1127 // set new URL and path.
1128 setURL( e.getData() );
1129 initialize();
1130 return true;
1132 return false;
1133 // i#67048 copy & paste images doesn't display. This bug refers
1134 // to an old OOo problem about getting resources from sites with a bad connection.
1135 // If we have a bad connection try again. Up to three times.
1136 case DAVException::DAV_HTTP_ERROR:
1137 // retry up to three times, if not a client-side error (4xx error codes)
1138 if ( e.getStatus() < SC_BAD_REQUEST && errorCount < 3 )
1139 return true;
1140 // check the server side errors
1141 switch( e.getStatus() )
1143 // the HTTP server side response status codes that can be retried
1144 // [Serf TODO? i#119036] case SC_REQUEST_ENTITY_TOO_LARGE:
1145 case SC_BAD_GATEWAY: // retry, can be an excessive load
1146 case SC_GATEWAY_TIMEOUT: // retry, may be we get lucky
1147 case SC_SERVICE_UNAVAILABLE: // retry, the service may become available
1148 case SC_INSUFFICIENT_STORAGE: // space may be freed, retry
1150 if ( errorCount < 3 )
1151 return true;
1152 else
1153 return false;
1155 break;
1156 // all the other HTTP server response status codes are NOT retry
1157 default:
1158 return false;
1160 break;
1161 // if connection has said retry then retry!
1162 case DAVException::DAV_HTTP_RETRY:
1163 return true;
1164 // <--
1165 default:
1166 return false; // Abort
1170 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */