From 16df731a30917a426df81d751a0bfd0ae5fcdd45 Mon Sep 17 00:00:00 2001 From: Giuseppe Castagno Date: Mon, 12 Sep 2016 20:59:09 +0200 Subject: tdf#102499 (5): Deal with HTTP unofficial response status codes A reference can be found here: (retrieved 2016-09-13). Changes done: Add set of 'HEAD method not available' before using fall back GET method. Add new method in OPTIONS cache. Add response status code if fall-back GET didn't succeeded. Add copy-assignement operator to DAVOptions. Fix behaviour of GET fall back when HEAD missing. Change-Id: I6aad0e22bb444abf37b90186588f64f79b03cc3d Reviewed-on: https://gerrit.libreoffice.org/29680 Tested-by: Jenkins Reviewed-by: Giuseppe Castagno --- ucb/source/ucp/webdav-neon/DAVTypes.cxx | 77 ++++++++++++++++-- ucb/source/ucp/webdav-neon/DAVTypes.hxx | 5 ++ ucb/source/ucp/webdav-neon/NeonSession.cxx | 113 ++++++++++++++++++++++----- ucb/source/ucp/webdav-neon/webdavcontent.cxx | 100 ++++++++++++++++-------- 4 files changed, 237 insertions(+), 58 deletions(-) (limited to 'ucb') diff --git a/ucb/source/ucp/webdav-neon/DAVTypes.cxx b/ucb/source/ucp/webdav-neon/DAVTypes.cxx index 3e48752a82ab..199028924d8d 100644 --- a/ucb/source/ucp/webdav-neon/DAVTypes.cxx +++ b/ucb/source/ucp/webdav-neon/DAVTypes.cxx @@ -34,7 +34,6 @@ DAVOptions::DAVOptions() : { } - DAVOptions::DAVOptions( const DAVOptions & rOther ) : m_isClass1( rOther.m_isClass1 ), m_isClass2( rOther.m_isClass2 ), @@ -50,11 +49,25 @@ DAVOptions::DAVOptions( const DAVOptions & rOther ) : { } - DAVOptions::~DAVOptions() { } +DAVOptions & DAVOptions::operator=( const DAVOptions& rOpts ) +{ + m_isClass1 = rOpts.m_isClass1; + m_isClass2 = rOpts.m_isClass2; + m_isClass3 = rOpts.m_isClass3; + m_isLocked = rOpts.m_isLocked; + m_isHeadAllowed = rOpts.m_isHeadAllowed; + m_aAllowedMethods = rOpts.m_aAllowedMethods; + m_nStaleTime = rOpts.m_nStaleTime; + m_sURL = rOpts.m_sURL; + m_sRedirectedURL = rOpts.m_sRedirectedURL; + m_nHttpResponseStatusCode = rOpts.m_nHttpResponseStatusCode; + m_sHttpResponseStatusText = rOpts.m_sHttpResponseStatusText; + return *this; +} bool DAVOptions::operator==( const DAVOptions& rOpts ) const { @@ -79,12 +92,10 @@ DAVOptionsCache::DAVOptionsCache() { } - DAVOptionsCache::~DAVOptionsCache() { } - bool DAVOptionsCache::getDAVOptions( const OUString & rURL, DAVOptions & rDAVOptions ) { osl::MutexGuard aGuard( m_aMutex ); @@ -113,7 +124,6 @@ bool DAVOptionsCache::getDAVOptions( const OUString & rURL, DAVOptions & rDAVOpt } } - void DAVOptionsCache::removeDAVOptions( const OUString & rURL ) { osl::MutexGuard aGuard( m_aMutex ); @@ -128,7 +138,6 @@ void DAVOptionsCache::removeDAVOptions( const OUString & rURL ) } } - void DAVOptionsCache::addDAVOptions( DAVOptions & rDAVOptions, const sal_uInt32 nLifeTime ) { osl::MutexGuard aGuard( m_aMutex ); @@ -149,6 +158,39 @@ void DAVOptionsCache::addDAVOptions( DAVOptions & rDAVOptions, const sal_uInt32 m_aTheCache[ aEncodedUrl ] = rDAVOptions; } +void DAVOptionsCache::updateCachedOption( DAVOptions & rDAVOptions, const sal_uInt32 nLifeTime ) +{ + osl::MutexGuard aGuard( m_aMutex ); + OUString aURL( rDAVOptions.getURL() ); + + OUString aEncodedUrl( ucb_impl::urihelper::encodeURI( NeonUri::unescape( aURL ) ) ); + normalizeURLLastChar( aEncodedUrl ); + rDAVOptions.setURL( aEncodedUrl ); + +// unchanged, it may be used to access a server + OUString aRedirURL( rDAVOptions.getRedirectedURL() ); + rDAVOptions.setRedirectedURL( aRedirURL ); + + // check if already cached + DAVOptionsMap::iterator it; + it = m_aTheCache.find( aEncodedUrl ); + if ( it != m_aTheCache.end() ) + { + DAVOptions &opts = (*it).second; + // exists, set new staletime, only if remaining time is higher + TimeValue t1; + osl_getSystemTime( &t1 ); + + if ( ( opts.getStaleTime() - t1.Seconds ) > nLifeTime ) + { + opts.setStaleTime( t1.Seconds + nLifeTime ); + } + // update relevant fields + opts.setHttpResponseStatusCode( rDAVOptions.getHttpResponseStatusCode() ); + opts.setHttpResponseStatusText( rDAVOptions.getHttpResponseStatusText() ); + } +} + sal_uInt16 DAVOptionsCache::getHttpResponseStatusCode( const OUString & rURL, OUString & rHttpResponseStatusText ) { osl::MutexGuard aGuard( m_aMutex ); @@ -174,6 +216,29 @@ sal_uInt16 DAVOptionsCache::getHttpResponseStatusCode( const OUString & rURL, OU return 0; } +void DAVOptionsCache::setHeadAllowed( const OUString & rURL, const bool HeadAllowed ) +{ + osl::MutexGuard aGuard( m_aMutex ); + OUString aEncodedUrl( ucb_impl::urihelper::encodeURI( NeonUri::unescape( rURL ) ) ); + normalizeURLLastChar( aEncodedUrl ); + + DAVOptionsMap::iterator it; + it = m_aTheCache.find( aEncodedUrl ); + if ( it != m_aTheCache.end() ) + { + // first check for stale + TimeValue t1; + osl_getSystemTime( &t1 ); + if( (*it).second.getStaleTime() < t1.Seconds ) + { + m_aTheCache.erase( it ); + return; + } + // check if the resource was present on server + (*it).second.setHeadAllowed( HeadAllowed ); + } +} + bool DAVOptionsCache::isHeadAllowed( const OUString & rURL ) { osl::MutexGuard aGuard( m_aMutex ); diff --git a/ucb/source/ucp/webdav-neon/DAVTypes.hxx b/ucb/source/ucp/webdav-neon/DAVTypes.hxx index 89f94a737a63..723ccb497bc0 100644 --- a/ucb/source/ucp/webdav-neon/DAVTypes.hxx +++ b/ucb/source/ucp/webdav-neon/DAVTypes.hxx @@ -152,6 +152,7 @@ namespace webdav_ucp m_sHttpResponseStatusText.clear(); }; + DAVOptions & operator=( const DAVOptions& rOpts ); bool operator==( const DAVOptions& rOpts ) const; }; @@ -174,6 +175,8 @@ namespace webdav_ucp void removeDAVOptions( const OUString & rURL ); void addDAVOptions( DAVOptions & rDAVOptions, const sal_uInt32 nLifeTime ); + void updateCachedOption( DAVOptions & rDAVOptions, const sal_uInt32 nLifeTime ); + /** return the cached value of HTTP response status code If the cached value is found stale, it is removed. @@ -190,6 +193,8 @@ namespace webdav_ucp bool isHeadAllowed( const OUString & rURL ); + void setHeadAllowed( const OUString & rURL, bool HeadAllowed = true ); + private: /// remove the last '/' in aUrl, if it exists diff --git a/ucb/source/ucp/webdav-neon/NeonSession.cxx b/ucb/source/ucp/webdav-neon/NeonSession.cxx index 99835a5c8ebf..d614a79d3930 100644 --- a/ucb/source/ucp/webdav-neon/NeonSession.cxx +++ b/ucb/source/ucp/webdav-neon/NeonSession.cxx @@ -1841,33 +1841,106 @@ void NeonSession::HandleError( int nError, sal_uInt16 code = makeStatusCode( aText ); SAL_WARN( "ucb.ucp.webdav", "Neon returned NE_ERROR, http response status code was: " << code << " '" << aText << "'" ); - if ( code == SC_LOCKED ) + if ( SC_BAD_REQUEST <= code && code < SC_INTERNAL_SERVER_ERROR ) { - if ( m_aNeonLockStore.findByUri( - makeAbsoluteURL( inPath ) ) == nullptr ) + // error codes in the range 4xx + switch ( code ) { - // locked by 3rd party - throw DAVException( DAVException::DAV_LOCKED ); - } - else - { - // locked by ourself - throw DAVException( DAVException::DAV_LOCKED_SELF ); + case SC_LOCKED: + { + if ( m_aNeonLockStore.findByUri( + makeAbsoluteURL( inPath ) ) == nullptr ) + { + // locked by 3rd party + throw DAVException( DAVException::DAV_LOCKED ); + } + else + { + // locked by ourself + throw DAVException( DAVException::DAV_LOCKED_SELF ); + } + } + break; + case SC_PRECONDITION_FAILED: + case SC_BAD_REQUEST: + { + // Special handling for 400 and 412 status codes, which may indicate + // that a lock previously obtained by us has been released meanwhile + // by the server. Unfortunately, RFC is not clear at this point, + // thus server implementations behave different... + if ( removeExpiredLocktoken( makeAbsoluteURL( inPath ), rEnv ) ) + throw DAVException( DAVException::DAV_LOCK_EXPIRED ); + } + break; + case SC_REQUEST_TIMEOUT: + { + throw DAVException( DAVException::DAV_HTTP_TIMEOUT, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + } + break; + case SC_UNAUTHORIZED: // User authentication failed on server + { + throw DAVException( DAVException::DAV_HTTP_AUTH, + NeonUri::makeConnectionEndPointString( + m_aHostName, m_nPort ) ); + } + break; + case SC_GONE: + case SC_LENGTH_REQUIRED: + case SC_REQUEST_ENTITY_TOO_LARGE: + case SC_REQUEST_URI_TOO_LONG: + case SC_UNSUPPORTED_MEDIA_TYPE: + case SC_REQUESTED_RANGE_NOT_SATISFIABLE: + case SC_EXPECTATION_FAILED: + case SC_UNPROCESSABLE_ENTITY: + case SC_FAILED_DEPENDENCY: + case SC_CONFLICT: + case SC_NOT_ACCEPTABLE: + case SC_PAYMENT_REQUIRED: + case SC_PROXY_AUTHENTICATION_REQUIRED: + default: + // set 400 error, if not one of others + code = SC_BAD_REQUEST; + SAL_FALLTHROUGH; + case SC_FORBIDDEN: + case SC_NOT_FOUND: + case SC_METHOD_NOT_ALLOWED: + throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code ); + break; } } - - // Special handling for 400 and 412 status codes, which may indicate - // that a lock previously obtained by us has been released meanwhile - // by the server. Unfortunately, RFC is not clear at this point, - // thus server implementations behave different... - else if ( code == SC_BAD_REQUEST || code == SC_PRECONDITION_FAILED ) + else if ( SC_INTERNAL_SERVER_ERROR <= code ) { - if ( removeExpiredLocktoken( makeAbsoluteURL( inPath ), rEnv ) ) - throw DAVException( DAVException::DAV_LOCK_EXPIRED ); + // deal with HTTP response status codes higher then 500 + // error codes in the range 5xx, server errors + // but there exists unofficial code in the range 1000 and up + // for example see: + // (retrieved 2016-10-05) + switch ( code ) + { + // the error codes case before the default case are not actively + // managed by LO + case SC_BAD_GATEWAY: + case SC_SERVICE_UNAVAILABLE: + case SC_GATEWAY_TIMEOUT: + case SC_HTTP_VERSION_NOT_SUPPORTED: + case SC_INSUFFICIENT_STORAGE: + default: + // set 500 error, if not one of others + // expand the error code + code = SC_INTERNAL_SERVER_ERROR; + SAL_FALLTHROUGH; + case SC_INTERNAL_SERVER_ERROR: + case SC_NOT_IMPLEMENTED: + throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code ); + break; + } } - - throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code ); + else + throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code ); } + break; case NE_LOOKUP: // Name lookup failed. SAL_WARN( "ucb.ucp.webdav", "Name lookup failed" ); throw DAVException( DAVException::DAV_HTTP_LOOKUP, diff --git a/ucb/source/ucp/webdav-neon/webdavcontent.cxx b/ucb/source/ucp/webdav-neon/webdavcontent.cxx index 7cf9ee1399a4..1937c73c1ca8 100644 --- a/ucb/source/ucp/webdav-neon/webdavcontent.cxx +++ b/ucb/source/ucp/webdav-neon/webdavcontent.cxx @@ -1590,8 +1590,13 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( // PROPPATCH can change them removeCachedPropertyNames( aTargetURL ); // test if HEAD allowed, if not, throw, will be catched immediately - if ( !aDAVOptions.isHeadAllowed() ) + // SC_GONE used internally by us, see comment below + // in the catch scope + if ( aDAVOptions.getHttpResponseStatusCode() != SC_GONE && + !aDAVOptions.isHeadAllowed() ) + { throw DAVException( DAVException::DAV_HTTP_ERROR, "405 Not Implemented", 405 ); + } // if HEAD is enabled on this site // check if there is a relevant HTTP response status code cached if ( aDAVOptions.getHttpResponseStatusCode() != SC_NONE ) @@ -1645,6 +1650,7 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( aLastException.getStatus() == SC_NOT_FOUND ) { SAL_WARN( "ucb.ucp.webdav", "HEAD probably not implemented: fall back to a partial GET" ); + aStaticDAVOptionsCache.setHeadAllowed( aTargetURL, false ); lcl_sendPartialGETRequest( bError, aLastException, aMissingProps, @@ -1658,10 +1664,27 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( if ( bError ) { + DAVOptions aDAVOptionsException; + + aDAVOptionsException.setURL( aTargetURL ); + // check if the error was SC_NOT_FOUND, meaning that the + // GET fall back didn't succeeded and the element is really missing + // we will consider the resource SC_GONE (410) for some time + // we use SC_GONE because has the same meaning of SC_NOT_FOUND (404) + // see: + // (retrieved 2016-10-09) + // apparently it's not used to mark the missing HEAD method (so far...) + sal_uInt16 ResponseStatusCode = + ( aLastException.getStatus() == SC_NOT_FOUND ) ? + SC_GONE : + aLastException.getStatus(); + aDAVOptionsException.setHttpResponseStatusCode( ResponseStatusCode ); + aDAVOptionsException.setHttpResponseStatusText( aLastException.getData() ); + aStaticDAVOptionsCache.updateCachedOption( aDAVOptionsException, + m_nOptsCacheLifeNotFound ); + if ( !shouldAccessNetworkAfterException( aLastException ) ) { - // remove the cached OPTIONS and errors - aStaticDAVOptionsCache.removeDAVOptions( aTargetURL ); cancelCommandExecution( aLastException, xEnv ); // unreachable } @@ -2348,6 +2371,7 @@ uno::Any Content::open( } catch ( DAVException const & e ) { + //TODO cache the http error if not yet cached cancelCommandExecution( e, xEnv ); // Unreachable } @@ -3729,6 +3753,7 @@ uno::Any Content::MapDAVException( const DAVException & e, bool bWrite ) bool Content::shouldAccessNetworkAfterException( const DAVException & e ) { if ( ( e.getStatus() == SC_NOT_FOUND ) || + ( e.getStatus() == SC_GONE ) || ( e.getError() == DAVException::DAV_HTTP_TIMEOUT ) || ( e.getError() == DAVException::DAV_HTTP_LOOKUP ) || ( e.getError() == DAVException::DAV_HTTP_CONNECT ) || @@ -3918,7 +3943,8 @@ Content::ResourceType Content::getResourceType( { rResAccess->resetUri(); - if ( aDAVOptions.getHttpResponseStatusCode() != SC_NOT_FOUND ) + if ( aDAVOptions.getHttpResponseStatusCode() != SC_NOT_FOUND && + aDAVOptions.getHttpResponseStatusCode() != SC_GONE ) // the cached OPTIONS can have SC_GONE { eResourceType = NON_DAV; } @@ -3926,8 +3952,7 @@ Content::ResourceType Content::getResourceType( { //resource doesn't exist if ( networkAccessAllowed != nullptr ) - *networkAccessAllowed = false; - } + *networkAccessAllowed = false; } } } @@ -3971,22 +3996,23 @@ void Content::getResourceOptions( { OUString aRedirURL; OUString aTargetURL = rResAccess->getURL(); + DAVOptions aDAVOptions; // first check if in cache, if not, then send method to server - if ( !aStaticDAVOptionsCache.getDAVOptions( aTargetURL, rDAVOptions ) ) + if ( !aStaticDAVOptionsCache.getDAVOptions( aTargetURL, aDAVOptions ) ) { try { - rResAccess->OPTIONS( rDAVOptions, xEnv ); + rResAccess->OPTIONS( aDAVOptions, xEnv ); // IMPORTANT:the correctly implemented server will answer without errors, even if the resource is not present - sal_uInt32 nLifeTime = ( rDAVOptions.isClass1() || - rDAVOptions.isClass2() || - rDAVOptions.isClass3() ) ? + sal_uInt32 nLifeTime = ( aDAVOptions.isClass1() || + aDAVOptions.isClass2() || + aDAVOptions.isClass3() ) ? m_nOptsCacheLifeDAV : // a WebDAV site m_nOptsCacheLifeImplWeb; // a site implementing OPTIONS but // it's not DAV // if resource is locked, will use a // different lifetime - if( rDAVOptions.isLocked() ) + if( aDAVOptions.isLocked() ) nLifeTime = m_nOptsCacheLifeDAVLocked; // check if redirected @@ -3996,9 +4022,9 @@ void Content::getResourceOptions( aRedirURL.clear(); } // cache this URL's option - rDAVOptions.setURL( aTargetURL ); - rDAVOptions.setRedirectedURL( aRedirURL ); - aStaticDAVOptionsCache.addDAVOptions( rDAVOptions, + aDAVOptions.setURL( aTargetURL ); + aDAVOptions.setRedirectedURL( aRedirURL ); + aStaticDAVOptionsCache.addDAVOptions( aDAVOptions, nLifeTime ); } catch ( DAVException const & e ) @@ -4007,8 +4033,8 @@ void Content::getResourceOptions( aStaticDAVOptionsCache.removeDAVOptions( aTargetURL ); rResAccess->resetUri(); - rDAVOptions.setURL( aTargetURL ); - rDAVOptions.setRedirectedURL( aRedirURL ); + aDAVOptions.setURL( aTargetURL ); + aDAVOptions.setRedirectedURL( aRedirURL ); switch( e.getError() ) { case DAVException::DAV_HTTP_TIMEOUT: @@ -4041,16 +4067,20 @@ void Content::getResourceOptions( { SAL_WARN( "ucb.ucp.webdav","OPTIONS - SC_FORBIDDEN for URL <" << m_xIdentifier->getContentIdentifier() << ">" ); // cache it, so OPTIONS won't be called again, this URL does not support it - aStaticDAVOptionsCache.addDAVOptions( rDAVOptions, + aStaticDAVOptionsCache.addDAVOptions( aDAVOptions, m_nOptsCacheLifeNotImpl ); } break; case SC_BAD_REQUEST: + case SC_INTERNAL_SERVER_ERROR: { - SAL_WARN( "ucb.ucp.webdav","OPTIONS - SC_BAD_REQUEST for URL <" << m_xIdentifier->getContentIdentifier() << ">" ); - // cache it, so OPTIONS won't be called again, this URL does not support it - aStaticDAVOptionsCache.addDAVOptions( rDAVOptions, - m_nOptsCacheLifeNotImpl ); + SAL_WARN( "ucb.ucp.webdav","OPTIONS - SC_BAD_REQUEST or SC_INTERNAL_SERVER_ERROR for URL <" << m_xIdentifier->getContentIdentifier() << ">, HTTP error: "<< e.getStatus() + << ", '" << e.getData() << "'" ); + // cache it, so OPTIONS won't be called again, this URL detect some problem while answering the method + aDAVOptions.setHttpResponseStatusCode( e.getStatus() ); + aDAVOptions.setHttpResponseStatusText( e.getData() ); + aStaticDAVOptionsCache.addDAVOptions( aDAVOptions, + m_nOptsCacheLifeNotFound ); } break; case SC_NOT_IMPLEMENTED: @@ -4058,9 +4088,10 @@ void Content::getResourceOptions( { // OPTIONS method must be implemented in DAV // resource is NON_DAV, or not advertising it - SAL_WARN( "ucb.ucp.webdav","OPTIONS - SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED for URL <" << m_xIdentifier->getContentIdentifier() << ">" ); + SAL_WARN( "ucb.ucp.webdav","OPTIONS - SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED for URL <" << m_xIdentifier->getContentIdentifier() << ">, HTTP error: "<< e.getStatus() + << ", '" << e.getData() << "'" ); // cache it, so OPTIONS won't be called again, this URL does not support it - aStaticDAVOptionsCache.addDAVOptions( rDAVOptions, + aStaticDAVOptionsCache.addDAVOptions( aDAVOptions, m_nOptsCacheLifeNotImpl ); } break; @@ -4070,22 +4101,26 @@ void Content::getResourceOptions( // instead of SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED. // So check if this is an available resource, or a real 'Not Found' event. sal_uInt32 nLifeTime = m_nOptsCacheLifeNotFound; - if( isResourceAvailable( xEnv, rResAccess, rDAVOptions ) ) + if( isResourceAvailable( xEnv, rResAccess, aDAVOptions ) ) { + SAL_WARN( "ucb.ucp.webdav", "OPTIONS - Got an SC_NOT_FOUND, but the URL <" << m_xIdentifier->getContentIdentifier() << "> resource exists" ); nLifeTime = m_nOptsCacheLifeNotImpl; } - aStaticDAVOptionsCache.addDAVOptions( rDAVOptions, + else + SAL_WARN( "ucb.ucp.webdav", "OPTIONS - SC_NOT_FOUND for URL <" << m_xIdentifier->getContentIdentifier() << ">" ); + + aStaticDAVOptionsCache.addDAVOptions( aDAVOptions, nLifeTime ); - SAL_WARN( "ucb.ucp.webdav", "OPTIONS - SC_NOT_FOUND for URL <" << m_xIdentifier->getContentIdentifier() << ">" ); } break; default: { - SAL_WARN( "ucb.ucp.webdav", "OPTIONS - DAV_HTTP_ERROR, for URL <" << m_xIdentifier->getContentIdentifier() << ">, HTTP error: "<< e.getStatus() ); - rDAVOptions.setHttpResponseStatusCode( e.getStatus() ); - rDAVOptions.setHttpResponseStatusText( e.getData() ); + SAL_WARN( "ucb.ucp.webdav", "OPTIONS - DAV_HTTP_ERROR, for URL <" << m_xIdentifier->getContentIdentifier() << ">, HTTP error: "<< e.getStatus() + << ", '" << e.getData() << "'" ); + aDAVOptions.setHttpResponseStatusCode( e.getStatus() ); + aDAVOptions.setHttpResponseStatusText( e.getData() ); // cache it, so OPTIONS won't be called again, this URL does not support it - aStaticDAVOptionsCache.addDAVOptions( rDAVOptions, + aStaticDAVOptionsCache.addDAVOptions( aDAVOptions, m_nOptsCacheLifeNotImpl ); } break; @@ -4100,13 +4135,14 @@ void Content::getResourceOptions( { SAL_WARN( "ucb.ucp.webdav","OPTIONS - General DAVException (or max DAV_HTTP_REDIRECT reached) for URL <" << m_xIdentifier->getContentIdentifier() << ">, DAV ExceptionCode: " << e.getError() << ", HTTP error: "<< e.getStatus() ); - aStaticDAVOptionsCache.addDAVOptions( rDAVOptions, + aStaticDAVOptionsCache.addDAVOptions( aDAVOptions, m_nOptsCacheLifeNotImpl ); } break; } } } + rDAVOptions = aDAVOptions; } -- cgit