diff options
-rw-r--r-- | ucb/source/ucp/webdav-neon/DAVTypes.cxx | 29 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-neon/DAVTypes.hxx | 8 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-neon/webdavcontent.cxx | 56 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-neon/webdavcontent.hxx | 3 |
4 files changed, 88 insertions, 8 deletions
diff --git a/ucb/source/ucp/webdav-neon/DAVTypes.cxx b/ucb/source/ucp/webdav-neon/DAVTypes.cxx index af1079ca66e6..875699418f2c 100644 --- a/ucb/source/ucp/webdav-neon/DAVTypes.cxx +++ b/ucb/source/ucp/webdav-neon/DAVTypes.cxx @@ -24,6 +24,7 @@ DAVOptions::DAVOptions() : m_isClass1( false ), m_isClass2( false ), m_isClass3( false ), + m_isHeadAllowed( true ), m_isLocked( false ), m_aAllowedMethods(), m_nStaleTime( 0 ), @@ -38,6 +39,7 @@ DAVOptions::DAVOptions( const DAVOptions & rOther ) : m_isClass1( rOther.m_isClass1 ), m_isClass2( rOther.m_isClass2 ), m_isClass3( rOther.m_isClass3 ), + m_isHeadAllowed( rOther.m_isHeadAllowed ), m_isLocked( rOther.m_isLocked ), m_aAllowedMethods( rOther.m_aAllowedMethods ), m_nStaleTime( rOther.m_nStaleTime ), @@ -173,5 +175,32 @@ bool DAVOptionsCache::isResourceFound( const OUString & rURL ) return true; } +bool DAVOptionsCache::isHeadAllowed( const OUString & rURL ) +{ + 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 true; // to force again OPTIONS method + } + + // check if the resource was present on server + return (*it).second.isHeadAllowed(); + } + // this value is needed because some web server don't implement + // OPTIONS method, so the resource is considered found, + // until detected otherwise + return true; +} /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/ucb/source/ucp/webdav-neon/DAVTypes.hxx b/ucb/source/ucp/webdav-neon/DAVTypes.hxx index 53bc7390d77c..037e68fec8fe 100644 --- a/ucb/source/ucp/webdav-neon/DAVTypes.hxx +++ b/ucb/source/ucp/webdav-neon/DAVTypes.hxx @@ -81,6 +81,8 @@ namespace webdav_ucp bool m_isClass1; bool m_isClass2; bool m_isClass3; + // for server that do not implement it + bool m_isHeadAllowed; // Internally used to maintain locked stated of the resource, only // if it's a Class 2 resource bool m_isLocked; @@ -111,6 +113,9 @@ namespace webdav_ucp bool isClass3() { return m_isClass3; }; void setClass3( bool Class3 = true ) { m_isClass3 = Class3; }; + bool isHeadAllowed() { return m_isHeadAllowed; }; + void setHeadAllowed( bool HeadAllowed = true ) { m_isHeadAllowed = HeadAllowed; }; + sal_uInt32 getStaleTime() const { return m_nStaleTime ; }; void setStaleTime( const sal_uInt32 nStaleTime ) { m_nStaleTime = nStaleTime; }; @@ -133,6 +138,7 @@ namespace webdav_ucp m_isClass1 = false; m_isClass2 = false; m_isClass3 = false; + m_isHeadAllowed = true; m_isLocked = false; m_aAllowedMethods.clear(); m_nStaleTime = 0; @@ -177,6 +183,8 @@ namespace webdav_ucp */ bool isResourceFound( const OUString & rURL ); + bool isHeadAllowed( const OUString & rURL ); + private: /// remove the last '/' in aUrl, if it exists diff --git a/ucb/source/ucp/webdav-neon/webdavcontent.cxx b/ucb/source/ucp/webdav-neon/webdavcontent.cxx index be3258294a51..a5d640677b96 100644 --- a/ucb/source/ucp/webdav-neon/webdavcontent.cxx +++ b/ucb/source/ucp/webdav-neon/webdavcontent.cxx @@ -1589,6 +1589,10 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( // clean cached value of PROPFIND property names // PROPPATCH can change them removeCachedPropertyNames( xResAccess->getURL() ); + // test if HEAD allowed, if not, throw, will be catched immediately + if ( !aStaticDAVOptionsCache.isHeadAllowed( xResAccess->getURL() ) ) + throw DAVException( DAVException::DAV_HTTP_ERROR, "405 Not Implemented" ); + xResAccess->HEAD( aHeaderNames, resource, xEnv ); m_bDidGetOrHead = true; @@ -4075,7 +4079,7 @@ 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 ) ) + if( isResourceAvailable( xEnv, rResAccess, rDAVOptions ) ) { nLifeTime = m_nOptsCacheLifeNotImpl; rDAVOptions.setResourceFound(); // means it exists, but it's not DAV @@ -4134,17 +4138,54 @@ void Content::getResourceOptions( //static bool Content::isResourceAvailable( const css::uno::Reference< css::ucb::XCommandEnvironment >& xEnv, - const std::unique_ptr< DAVResourceAccess > & rResAccess ) + const std::unique_ptr< DAVResourceAccess > & rResAccess, + DAVOptions& rDAVOptions ) { + std::vector< rtl::OUString > aHeaderNames; + DAVResource aResource; + try { - // To check for the physical URL resource availability, using a simple HEAD command - // if HEAD is successfull, set element found. - std::vector< OUString > aHeaderNames; - DAVResource resource; - rResAccess->HEAD( aHeaderNames, resource, xEnv ); + // To check for the physical URL resource availability, first + // try using a simple HEAD command + // if HEAD is successfull, set element found, + rResAccess->HEAD( aHeaderNames, aResource, xEnv ); return true; } + catch ( DAVException const & e ) + { + if ( e.getStatus() == SC_NOT_IMPLEMENTED || + e.getStatus() == SC_METHOD_NOT_ALLOWED || + e.getStatus() == SC_NOT_FOUND ) + { + SAL_WARN( "ucb.ucp.webdav", "HEAD not implemented: fall back to a partial GET" ); + // set in cached OPTIONS "HEAD not implemented" + // so it won't be used again on this resource + rDAVOptions.setHeadAllowed( false ); + try + { + // do a GET with a payload of 0, the server does not + // support HEAD (or has HEAD disabled) + DAVRequestHeaders aPartialGet; + aPartialGet.push_back( + DAVRequestHeader( + OUString( "Range" ), + OUString( "bytes=0-0" ))); + + rResAccess->GET( aPartialGet, + aHeaderNames, + aResource, + xEnv ); + return true; + } + catch (...) + { + return false; + } + } + else + return false; + } catch ( ... ) { // some error... so set as not found @@ -4152,6 +4193,7 @@ bool Content::isResourceAvailable( const css::uno::Reference< css::ucb::XCommand // in rResAccess function method. return false; } + return false; } diff --git a/ucb/source/ucp/webdav-neon/webdavcontent.hxx b/ucb/source/ucp/webdav-neon/webdavcontent.hxx index 1adf196cade7..8ee5ace2322b 100644 --- a/ucb/source/ucp/webdav-neon/webdavcontent.hxx +++ b/ucb/source/ucp/webdav-neon/webdavcontent.hxx @@ -329,7 +329,8 @@ public: throw ( css::uno::Exception, std::exception ); static bool isResourceAvailable( const css::uno::Reference< css::ucb::XCommandEnvironment >& xEnv, - const std::unique_ptr< DAVResourceAccess > & rResAccess); + const std::unique_ptr< DAVResourceAccess > & rResAccess, + DAVOptions& rDAVOptions ); static void removeCachedPropertyNames( const OUString & rURL ); }; |