1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
29 #include "webdavprovider.hxx"
31 #include <officecfg/Office/Security.hxx>
33 #include <com/sun/star/lang/IllegalArgumentException.hpp>
34 #include <com/sun/star/io/IOException.hpp>
37 using namespace http_dav_ucp
;
38 using namespace com::sun::star
;
41 // DAVAuthListener_Impl Implementation.
45 int DAVAuthListener_Impl::authenticate(
46 const OUString
& inRealm
,
47 const OUString
& inHostName
,
48 OUString
& inoutUserName
,
49 OUString
& outPassWord
,
50 bool bCanUseSystemCredentials
,
51 bool bUsePreviousCredentials
)
55 uno::Reference
< task::XInteractionHandler
> xIH
56 = m_xEnv
->getInteractionHandler();
60 // Providing previously retrieved credentials will cause the password
61 // container to reject these. Thus, the credential input dialog will be shown again.
62 // #102871# - Supply username and password from previous try.
63 // Password container service depends on this!
64 if ( inoutUserName
.isEmpty() && bUsePreviousCredentials
)
65 inoutUserName
= m_aPrevUsername
;
67 if ( outPassWord
.isEmpty() && bUsePreviousCredentials
)
68 outPassWord
= m_aPrevPassword
;
70 rtl::Reference
< ucbhelper::SimpleAuthenticationRequest
> xRequest
71 = new ucbhelper::SimpleAuthenticationRequest(
72 m_aURL
, inHostName
, inRealm
, inoutUserName
,
74 bCanUseSystemCredentials
);
75 xIH
->handle( xRequest
);
77 rtl::Reference
< ucbhelper::InteractionContinuation
> xSelection
78 = xRequest
->getSelection();
80 if ( xSelection
.is() )
82 // Handler handled the request.
83 uno::Reference
< task::XInteractionAbort
> xAbort(
84 xSelection
.get(), uno::UNO_QUERY
);
88 ucbhelper::InteractionSupplyAuthentication
> & xSupp
89 = xRequest
->getAuthenticationSupplier();
91 bool bUseSystemCredentials
= false;
93 if ( bCanUseSystemCredentials
)
95 = xSupp
->getUseSystemCredentials();
97 if ( bUseSystemCredentials
)
99 // This is the (strange) way to tell neon to use
100 // system credentials.
101 inoutUserName
.clear();
106 inoutUserName
= xSupp
->getUserName();
107 outPassWord
= xSupp
->getPassword();
110 // #102871# - Remember username and password.
111 m_aPrevUsername
= inoutUserName
;
112 m_aPrevPassword
= outPassWord
;
125 // DAVResourceAccess Implementation.
127 constexpr size_t g_nRedirectLimit
= 5;
129 DAVResourceAccess::DAVResourceAccess(
130 uno::Reference
< uno::XComponentContext
> xContext
,
131 rtl::Reference
< DAVSessionFactory
> xSessionFactory
,
133 : m_aURL(std::move( aURL
)),
134 m_xSessionFactory(std::move( xSessionFactory
)),
135 m_xContext(std::move( xContext
))
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
;
166 void DAVResourceAccess::OPTIONS(
167 DAVOptions
& rOptions
,
168 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
179 DAVRequestHeaders aHeaders
;
181 getUserRequestHeaders( xEnv
,
183 ucb::WebDAVHTTPMethod_OPTIONS
,
186 m_xSession
->OPTIONS( getRequestURI(),
188 DAVRequestEnvironment(
189 new DAVAuthListener_Impl( xEnv
, m_aURL
),
192 catch (DAVException
const& e
)
195 bRetry
= handleException( e
, errorCount
);
203 void DAVResourceAccess::PROPFIND(
205 const std::vector
< OUString
> & rPropertyNames
,
206 std::vector
< DAVResource
> & rResources
,
207 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
218 DAVRequestHeaders aHeaders
;
220 getUserRequestHeaders( xEnv
,
222 ucb::WebDAVHTTPMethod_PROPFIND
,
225 m_xSession
->PROPFIND( getRequestURI(),
229 DAVRequestEnvironment(
230 new DAVAuthListener_Impl( xEnv
, m_aURL
),
233 catch (DAVException
const& e
)
236 bRetry
= handleException( e
, errorCount
);
245 void DAVResourceAccess::PROPFIND(
247 std::vector
< DAVResourceInfo
> & rResInfo
,
248 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
259 DAVRequestHeaders aHeaders
;
260 getUserRequestHeaders( xEnv
,
262 ucb::WebDAVHTTPMethod_PROPFIND
,
265 m_xSession
->PROPFIND( getRequestURI(),
268 DAVRequestEnvironment(
269 new DAVAuthListener_Impl( xEnv
, m_aURL
),
272 catch (DAVException
const& e
)
275 bRetry
= handleException( e
, errorCount
);
284 void DAVResourceAccess::PROPPATCH(
285 const std::vector
< ProppatchValue
>& rValues
,
286 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
297 DAVRequestHeaders aHeaders
;
298 getUserRequestHeaders( xEnv
,
300 ucb::WebDAVHTTPMethod_PROPPATCH
,
303 m_xSession
->PROPPATCH( getRequestURI(),
305 DAVRequestEnvironment(
306 new DAVAuthListener_Impl( xEnv
, m_aURL
),
309 catch (DAVException
const& e
)
312 bRetry
= handleException( e
, errorCount
);
321 void DAVResourceAccess::HEAD(
322 const std::vector
< OUString
> & rHeaderNames
,
323 DAVResource
& rResource
,
324 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
335 DAVRequestHeaders aHeaders
;
336 getUserRequestHeaders( xEnv
,
338 ucb::WebDAVHTTPMethod_HEAD
,
341 m_xSession
->HEAD( getRequestURI(),
344 DAVRequestEnvironment(
345 new DAVAuthListener_Impl( xEnv
, m_aURL
),
348 catch (DAVException
const& e
)
351 bRetry
= handleException( e
, errorCount
);
360 uno::Reference
< io::XInputStream
> DAVResourceAccess::GET(
361 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
365 uno::Reference
< io::XInputStream
> xStream
;
373 DAVRequestHeaders aHeaders
;
374 getUserRequestHeaders( xEnv
,
376 ucb::WebDAVHTTPMethod_GET
,
379 xStream
= m_xSession
->GET( getRequestURI(),
380 DAVRequestEnvironment(
381 new DAVAuthListener_Impl(
385 catch (DAVException
const& e
)
388 bRetry
= handleException( e
, errorCount
);
399 void DAVResourceAccess::GET(
400 uno::Reference
< io::XOutputStream
> & rStream
,
401 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
412 DAVRequestHeaders aHeaders
;
413 getUserRequestHeaders( xEnv
,
415 ucb::WebDAVHTTPMethod_GET
,
418 m_xSession
->GET( getRequestURI(),
420 DAVRequestEnvironment(
421 new DAVAuthListener_Impl( xEnv
, m_aURL
),
424 catch (DAVException
const& e
)
427 bRetry
= handleException( e
, errorCount
);
436 uno::Reference
< io::XInputStream
> DAVResourceAccess::GET(
437 const std::vector
< OUString
> & rHeaderNames
,
438 DAVResource
& rResource
,
439 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
443 uno::Reference
< io::XInputStream
> xStream
;
451 DAVRequestHeaders aHeaders
;
452 getUserRequestHeaders( xEnv
,
454 ucb::WebDAVHTTPMethod_GET
,
457 xStream
= m_xSession
->GET( getRequestURI(),
460 DAVRequestEnvironment(
461 new DAVAuthListener_Impl(
465 catch (DAVException
const& e
)
468 bRetry
= handleException( e
, errorCount
);
479 // used as HEAD substitute when HEAD is not implemented on server
480 void DAVResourceAccess::GET0(
481 DAVRequestHeaders
&rRequestHeaders
,
482 const std::vector
< OUString
> & rHeaderNames
,
483 DAVResource
& rResource
,
484 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
495 getUserRequestHeaders( xEnv
,
497 ucb::WebDAVHTTPMethod_GET
,
500 m_xSession
->GET( getRequestURI(),
503 DAVRequestEnvironment(
504 new DAVAuthListener_Impl(
508 catch (DAVException
const& e
)
511 bRetry
= handleException( e
, errorCount
);
520 void DAVResourceAccess::GET(
521 uno::Reference
< io::XOutputStream
> & rStream
,
522 const std::vector
< OUString
> & rHeaderNames
,
523 DAVResource
& rResource
,
524 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
535 DAVRequestHeaders aHeaders
;
536 getUserRequestHeaders( xEnv
,
538 ucb::WebDAVHTTPMethod_GET
,
541 m_xSession
->GET( getRequestURI(),
545 DAVRequestEnvironment(
546 new DAVAuthListener_Impl( xEnv
, m_aURL
),
549 catch (DAVException
const& e
)
552 bRetry
= handleException( e
, errorCount
);
561 void DAVResourceAccess::abort()
563 // seems pointless to call initialize() here, but prepare for nullptr
564 decltype(m_xSession
) xSession
;
566 osl::Guard
<osl::Mutex
> const g(m_aMutex
);
567 xSession
= m_xSession
;
578 /// @throws DAVException
579 void resetInputStream( const uno::Reference
< io::XInputStream
> & rStream
)
583 uno::Reference
< io::XSeekable
> xSeekable(
584 rStream
, uno::UNO_QUERY
);
585 if ( xSeekable
.is() )
587 xSeekable
->seek( 0 );
591 catch ( lang::IllegalArgumentException
const & )
594 catch ( io::IOException
const & )
598 throw DAVException( DAVException::DAV_INVALID_ARG
);
604 void DAVResourceAccess::PUT(
605 const uno::Reference
< io::XInputStream
> & rStream
,
606 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
610 // Make stream seekable, if it not. Needed, if request must be retried.
611 uno::Reference
< io::XInputStream
> xSeekableStream
612 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
613 rStream
, m_xContext
);
620 resetInputStream( xSeekableStream
);
625 DAVRequestHeaders aHeaders
;
626 getUserRequestHeaders( xEnv
,
628 ucb::WebDAVHTTPMethod_PUT
,
631 m_xSession
->PUT( getRequestURI(),
633 DAVRequestEnvironment(
634 new DAVAuthListener_Impl( xEnv
, m_aURL
),
637 catch (DAVException
const& e
)
640 bRetry
= handleException( e
, errorCount
);
649 uno::Reference
< io::XInputStream
> DAVResourceAccess::POST(
650 const OUString
& rContentType
,
651 const OUString
& rReferer
,
652 const uno::Reference
< io::XInputStream
> & rInputStream
,
653 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
657 // Make stream seekable, if it not. Needed, if request must be retried.
658 uno::Reference
< io::XInputStream
> xSeekableStream
659 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
660 rInputStream
, m_xContext
);
662 uno::Reference
< io::XInputStream
> xStream
;
669 resetInputStream( xSeekableStream
);
675 DAVRequestHeaders aHeaders
;
676 getUserRequestHeaders( xEnv
,
678 ucb::WebDAVHTTPMethod_POST
,
681 xStream
= m_xSession
->POST( getRequestURI(),
685 DAVRequestEnvironment(
686 new DAVAuthListener_Impl(
690 catch (DAVException
const& e
)
693 bRetry
= handleException( e
, errorCount
);
697 if ( e
.getError() == DAVException::DAV_HTTP_REDIRECT
)
699 // #i74980# - Upon POST redirect, do a GET.
710 void DAVResourceAccess::POST(
711 const OUString
& rContentType
,
712 const OUString
& rReferer
,
713 const uno::Reference
< io::XInputStream
> & rInputStream
,
714 uno::Reference
< io::XOutputStream
> & rOutputStream
,
715 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
719 // Make stream seekable, if it not. Needed, if request must be retried.
720 uno::Reference
< io::XInputStream
> xSeekableStream
721 = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
722 rInputStream
, m_xContext
);
730 resetInputStream( xSeekableStream
);
736 DAVRequestHeaders aHeaders
;
737 getUserRequestHeaders( xEnv
,
739 ucb::WebDAVHTTPMethod_POST
,
742 m_xSession
->POST( getRequestURI(),
747 DAVRequestEnvironment(
748 new DAVAuthListener_Impl( xEnv
, m_aURL
),
751 catch (DAVException
const& e
)
754 bRetry
= handleException( e
, errorCount
);
758 if ( e
.getError() == DAVException::DAV_HTTP_REDIRECT
)
760 // #i74980# - Upon POST redirect, do a GET.
761 GET( rOutputStream
, xEnv
);
770 void DAVResourceAccess::MKCOL(
771 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
782 DAVRequestHeaders aHeaders
;
783 getUserRequestHeaders( xEnv
,
785 ucb::WebDAVHTTPMethod_MKCOL
,
788 m_xSession
->MKCOL( getRequestURI(),
789 DAVRequestEnvironment(
790 new DAVAuthListener_Impl( xEnv
, m_aURL
),
793 catch (DAVException
const& e
)
796 bRetry
= handleException( e
, errorCount
);
805 void DAVResourceAccess::COPY(
806 const OUString
& rSourcePath
,
807 const OUString
& rDestinationURI
,
809 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
820 DAVRequestHeaders aHeaders
;
821 getUserRequestHeaders( xEnv
,
823 ucb::WebDAVHTTPMethod_COPY
,
826 m_xSession
->COPY( rSourcePath
,
828 DAVRequestEnvironment(
829 new DAVAuthListener_Impl( xEnv
, m_aURL
),
833 catch (DAVException
const& e
)
836 bRetry
= handleException( e
, errorCount
);
845 void DAVResourceAccess::MOVE(
846 const OUString
& rSourcePath
,
847 const OUString
& rDestinationURI
,
849 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
860 DAVRequestHeaders aHeaders
;
861 getUserRequestHeaders( xEnv
,
863 ucb::WebDAVHTTPMethod_MOVE
,
866 m_xSession
->MOVE( rSourcePath
,
868 DAVRequestEnvironment(
869 new DAVAuthListener_Impl( xEnv
, m_aURL
),
873 catch (DAVException
const& e
)
876 bRetry
= handleException( e
, errorCount
);
885 void DAVResourceAccess::DESTROY(
886 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
897 DAVRequestHeaders aHeaders
;
898 getUserRequestHeaders( xEnv
,
900 ucb::WebDAVHTTPMethod_DELETE
,
903 m_xSession
->DESTROY( getRequestURI(),
904 DAVRequestEnvironment(
905 new DAVAuthListener_Impl( xEnv
, m_aURL
),
908 catch (DAVException
const& e
)
911 bRetry
= handleException( e
, errorCount
);
921 void DAVResourceAccess::LOCK(
923 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
934 DAVRequestHeaders aHeaders
;
935 getUserRequestHeaders( xEnv
,
937 ucb::WebDAVHTTPMethod_LOCK
,
940 m_xSession
->LOCK( getRequestURI(),
942 DAVRequestEnvironment(
943 new DAVAuthListener_Impl( xEnv
, m_aURL
),
946 catch (DAVException
const& e
)
949 bRetry
= handleException( e
, errorCount
);
957 void DAVResourceAccess::UNLOCK(
958 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
969 DAVRequestHeaders aHeaders
;
970 getUserRequestHeaders( xEnv
,
972 ucb::WebDAVHTTPMethod_UNLOCK
,
975 m_xSession
->UNLOCK( getRequestURI(),
976 DAVRequestEnvironment(
977 new DAVAuthListener_Impl( xEnv
, m_aURL
),
980 catch (DAVException
const& e
)
983 bRetry
= handleException( e
, errorCount
);
991 void DAVResourceAccess::setFlags( const uno::Sequence
< beans::NamedValue
>& rFlags
)
993 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
997 void DAVResourceAccess::setURL( const OUString
& rNewURL
)
999 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1001 m_aPath
.clear(); // Next initialize() will create new session.
1005 // init dav session and path
1006 void DAVResourceAccess::initialize()
1008 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1009 if ( m_aPath
.isEmpty() )
1011 CurlUri
aURI(m_aURL
);
1012 assert(aURI
.GetScheme() == HTTP_URL_SCHEME
|| aURI
.GetScheme() == HTTPS_URL_SCHEME
);
1013 if (aURI
.GetScheme() == HTTP_URL_SCHEME
)
1015 if (!officecfg::Office::Security::Net::AllowInsecureProtocols::get())
1017 // "http" not allowed -> immediately redirect to "https",
1018 // better than showing confusing error to user
1019 aURI
.SetScheme(HTTPS_URL_SCHEME
);
1022 OUString
aPath( aURI
.GetRelativeReference() );
1024 /* #134089# - Check URI */
1025 if ( aPath
.isEmpty() )
1026 throw DAVException( DAVException::DAV_INVALID_ARG
);
1028 /* #134089# - Check URI */
1029 if ( aURI
.GetHost().isEmpty() )
1030 throw DAVException( DAVException::DAV_INVALID_ARG
);
1032 if ( !m_xSession
.is() || !m_xSession
->CanUse( m_aURL
, m_aFlags
) )
1036 // create new webdav session
1037 m_xSession
= m_xSessionFactory
->createDAVSession(aURI
.GetURI(), m_aFlags
, m_xContext
);
1039 if ( !m_xSession
.is() )
1043 // Own URI is needed to redirect cycle detection.
1044 m_aRedirectURIs
.push_back( aURI
);
1049 // Not only the path has to be encoded
1050 m_aURL
= aURI
.GetURI();
1055 const OUString
& DAVResourceAccess::getRequestURI() const
1057 assert(m_xSession
.is() &&
1058 "DAVResourceAccess::getRequestURI - Not initialized!");
1060 // In case a proxy is used we have to use the absolute URI for a request.
1061 if ( m_xSession
->UsesProxy() )
1069 void DAVResourceAccess::getUserRequestHeaders(
1070 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
1071 const OUString
& rURI
,
1072 ucb::WebDAVHTTPMethod eMethod
,
1073 DAVRequestHeaders
& rRequestHeaders
)
1078 uno::Reference
< ucb::XWebDAVCommandEnvironment
> xDAVEnv(
1079 xEnv
, uno::UNO_QUERY
);
1081 if ( !xDAVEnv
.is() )
1084 uno::Sequence
< beans::StringPair
> aRequestHeaders
1085 = xDAVEnv
->getUserRequestHeaders( rURI
, eMethod
);
1087 for ( sal_Int32 n
= 0; n
< aRequestHeaders
.getLength(); ++n
)
1089 rRequestHeaders
.push_back(
1090 DAVRequestHeader( aRequestHeaders
[ n
].First
,
1091 aRequestHeaders
[ n
].Second
) );
1095 // This function member implements the control on cyclical redirections
1096 bool DAVResourceAccess::detectRedirectCycle(
1097 ::std::u16string_view
const rRedirectURL
)
1099 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1101 CurlUri
const aUri( rRedirectURL
);
1103 // Check for maximum number of redirections
1104 // according to <https://tools.ietf.org/html/rfc7231#section-6.4>.
1105 // A practical limit may be 5, due to earlier specifications:
1106 // <https://tools.ietf.org/html/rfc2068#section-10.3>
1107 // it can be raised keeping in mind the added net activity.
1108 if( g_nRedirectLimit
<= m_aRedirectURIs
.size() )
1111 // try to detect a cyclical redirection
1112 return std::any_of(m_aRedirectURIs
.begin(), m_aRedirectURIs
.end(),
1113 [&aUri
](const CurlUri
& rUri
) { return aUri
== rUri
; });
1117 void DAVResourceAccess::resetUri()
1119 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
1120 if ( ! m_aRedirectURIs
.empty() )
1122 auto const it
= m_aRedirectURIs
.begin();
1124 CurlUri
const aUri( *it
);
1125 m_aRedirectURIs
.clear();
1126 setURL ( aUri
.GetURI() );
1132 bool DAVResourceAccess::handleException(DAVException
const& e
, int const errorCount
)
1134 switch ( e
.getError() )
1136 case DAVException::DAV_HTTP_REDIRECT
:
1137 if ( !detectRedirectCycle( e
.getData() ) )
1139 // set new URL and path.
1140 setURL( e
.getData() );
1145 // i#67048 copy & paste images doesn't display. This bug refers
1146 // to an old OOo problem about getting resources from sites with a bad connection.
1147 // If we have a bad connection try again. Up to three times.
1148 case DAVException::DAV_HTTP_ERROR
:
1149 // retry up to three times, if not a client-side error (4xx error codes)
1150 if ( e
.getStatus() < SC_BAD_REQUEST
&& errorCount
< 3 )
1152 // check the server side errors
1153 switch( e
.getStatus() )
1155 // the HTTP server side response status codes that can be retried
1156 // [Serf TODO? i#119036] case SC_REQUEST_ENTITY_TOO_LARGE:
1157 case SC_BAD_GATEWAY
: // retry, can be an excessive load
1158 case SC_GATEWAY_TIMEOUT
: // retry, may be we get lucky
1159 case SC_SERVICE_UNAVAILABLE
: // retry, the service may become available
1160 case SC_INSUFFICIENT_STORAGE
: // space may be freed, retry
1162 if ( errorCount
< 3 )
1168 // all the other HTTP server response status codes are NOT retry
1173 // if connection has said retry then retry!
1174 case DAVException::DAV_HTTP_RETRY
:
1178 return false; // Abort
1182 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */