diff options
author | Giuseppe Castagno <giuseppe.castagno@acca-esse.eu> | 2016-01-10 16:46:19 +0100 |
---|---|---|
committer | Giuseppe Castagno <giuseppe.castagno@acca-esse.eu> | 2016-07-29 07:10:23 +0000 |
commit | 6ab2cabeae02b6beb3c33238773ba075f41c4bb9 (patch) | |
tree | acb730f6eb03984f7d99822cd13031a39f39178f | |
parent | 73cd9c480c681d076e837aa7ba1ea706de3f3d0e (diff) |
tdf#101094 (8) OPTIONS: Add options check in Content::resourceTypeForLocks
Change-Id: Ia1bcc1be9e61626da2d60ea679d4b6e7e114ac9f
Reviewed-on: https://gerrit.libreoffice.org/27661
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Giuseppe Castagno <giuseppe.castagno@acca-esse.eu>
-rw-r--r-- | ucb/source/ucp/webdav-neon/webdavcontent.cxx | 196 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-neon/webdavcontent.hxx | 6 |
2 files changed, 126 insertions, 76 deletions
diff --git a/ucb/source/ucp/webdav-neon/webdavcontent.cxx b/ucb/source/ucp/webdav-neon/webdavcontent.cxx index f91a50cc64ef..3c40ad856656 100644 --- a/ucb/source/ucp/webdav-neon/webdavcontent.cxx +++ b/ucb/source/ucp/webdav-neon/webdavcontent.cxx @@ -2782,7 +2782,8 @@ void Content::destroy( bool bDeletePhysical ) // returns the resource type, to be checked for locks Content::ResourceType Content::resourceTypeForLocks( - const uno::Reference< ucb::XCommandEnvironment >& Environment ) + const uno::Reference< ucb::XCommandEnvironment >& Environment, + const std::unique_ptr< DAVResourceAccess > & rResAccess) { ResourceType eResourceTypeForLocks = UNKNOWN; { @@ -2814,12 +2815,6 @@ Content::ResourceType Content::resourceTypeForLocks( if ( eResourceTypeForLocks == UNKNOWN ) { // resource type for lock/unlock operations still unknown, need to ask the server - std::unique_ptr< DAVResourceAccess > xResAccess; - - xResAccess.reset( new DAVResourceAccess( - m_xContext, - m_rSessionFactory, - rURL ) ); const OUString aScheme( rURL.copy( 0, rURL.indexOf( ':' ) ).toAsciiLowerCase() ); @@ -2830,89 +2825,125 @@ Content::ResourceType Content::resourceTypeForLocks( } else { - try + DAVOptions aDAVOptions; + getResourceOptions( Environment, aDAVOptions, rResAccess ); + if( aDAVOptions.isClass1() || + aDAVOptions.isClass2() || + aDAVOptions.isClass3() ) { - // we need only DAV:supportedlock - std::vector< DAVResource > resources; - std::vector< OUString > aPropNames; - uno::Sequence< beans::Property > aProperties( 1 ); - aProperties[ 0 ].Name = DAVProperties::SUPPORTEDLOCK; - - ContentProperties::UCBNamesToDAVNames( aProperties, aPropNames ); - xResAccess->PROPFIND( DAVZERO, aPropNames, resources, Environment ); - - // only one resource should be returned - if ( resources.size() == 1 ) + // this is at least a DAV, lock to be confirmed + // class 2 is needed for full lock support + // see + // <https://tools.ietf.org/html/rfc4918#section-18.2> + eResourceTypeForLocks = DAV_NOLOCK; + if( aDAVOptions.isClass2() ) { - // we may have received a bunch of other properties - // (some servers seems to do so) - // but we need only supported lock for this check - // all returned properties are in - // resources.properties[n].Name/.Value + // ok, possible lock, check for it + try + { + // we need only DAV:supportedlock + std::vector< DAVResource > resources; + std::vector< OUString > aPropNames; + uno::Sequence< beans::Property > aProperties( 1 ); + aProperties[ 0 ].Name = DAVProperties::SUPPORTEDLOCK; - std::vector< DAVPropertyValue >::iterator it; + ContentProperties::UCBNamesToDAVNames( aProperties, aPropNames ); + rResAccess->PROPFIND( DAVZERO, aPropNames, resources, Environment ); - for ( it = resources[0].properties.begin(); - it != resources[0].properties.end(); ++it) - { - if ( (*it).Name == DAVProperties::SUPPORTEDLOCK ) + bool wasSupportedlockFound = false; + + // only one resource should be returned + if ( resources.size() == 1 ) { - uno::Sequence< ucb::LockEntry > aSupportedLocks; - if ( (*it).Value >>= aSupportedLocks ) + // we may have received a bunch of other properties + // (some servers seems to do so) + // but we need only supported lock for this check + // all returned properties are in + // resources.properties[n].Name/.Value + + std::vector< DAVPropertyValue >::iterator it; + + for ( it = resources[0].properties.begin(); + it != resources[0].properties.end(); ++it) { - // this is at least a DAV, no lock confirmed yet - eResourceTypeForLocks = DAV_NOLOCK; - for ( sal_Int32 n = 0; n < aSupportedLocks.getLength(); ++n ) + if ( (*it).Name == DAVProperties::SUPPORTEDLOCK ) { - if ( aSupportedLocks[ n ].Scope == ucb::LockScope_EXCLUSIVE && - aSupportedLocks[ n ].Type == ucb::LockType_WRITE ) + wasSupportedlockFound = true; + uno::Sequence< ucb::LockEntry > aSupportedLocks; + if ( (*it).Value >>= aSupportedLocks ) { - // requested locking mode is supported - eResourceTypeForLocks = DAV; - SAL_INFO( "ucb.ucp.webdav", "resourceTypeForLocks - URL: <" - << m_xIdentifier->getContentIdentifier() << ">, DAV lock/unlock supported"); + for ( sal_Int32 n = 0; n < aSupportedLocks.getLength(); ++n ) + { + // TODO: if the lock type is changed from 'exclusive write' to 'shared write' + // e.g. to implement 'Calc shared file feature', the ucb::LockScope_EXCLUSIVE + // value should be checked as well, adaptation the code may be needed + if ( aSupportedLocks[ n ].Scope == ucb::LockScope_EXCLUSIVE && + aSupportedLocks[ n ].Type == ucb::LockType_WRITE ) + { + // requested locking mode is supported + eResourceTypeForLocks = DAV; + SAL_INFO( "ucb.ucp.webdav", "resourceTypeForLocks - URL: <" + << m_xIdentifier->getContentIdentifier() << ">, DAV lock/unlock supported"); + break; + } + } break; } } - break; } } + // check if this is still only a DAV_NOLOCK + // a fallback for resources that do not have DAVProperties::SUPPORTEDLOCK property + // we check for the returned OPTION if LOCK is allowed on the resource + if ( !wasSupportedlockFound && eResourceTypeForLocks == DAV_NOLOCK ) + { + SAL_INFO( "ucb.ucp.webdav", "This WebDAV server has no supportedlock property, check for allowed LOCK method in OPTIONS" ); + // ATTENTION: if the lock type is changed from 'exclusive write' to 'shared write' + // e.g. to implement 'Calc shared file feature' on WebDAV directly, and we arrive to this fallback + // and the LOCK is allowed, we should assume that only exclusive write lock is available + // this is just a reminder... + if ( aDAVOptions.isLockAllowed() ) + eResourceTypeForLocks = DAV; + } + } + catch ( DAVException const & e ) + { + rResAccess->resetUri(); + //grab the error code + switch( e.getStatus() ) + { + case SC_NOT_FOUND: + SAL_WARN( "ucb.ucp.webdav", "resourceTypeForLocks() - URL: <" + << m_xIdentifier->getContentIdentifier() << "> was not found. "); + eResourceTypeForLocks = NOT_FOUND; + break; + // some servers returns SC_FORBIDDEN, instead + // TODO: probably remove it, when OPTIONS implemented + // the meaning of SC_FORBIDDEN is, according to <http://tools.ietf.org/html/rfc7231#section-6.5.3>: + // The 403 (Forbidden) status code indicates that the server understood + // the request but refuses to authorize it + case SC_FORBIDDEN: + // Errors SC_NOT_IMPLEMENTED and SC_METHOD_NOT_ALLOWED are + // part of base http 1.1 RFCs + case SC_NOT_IMPLEMENTED: // <http://tools.ietf.org/html/rfc7231#section-6.6.2> + case SC_METHOD_NOT_ALLOWED: // <http://tools.ietf.org/html/rfc7231#section-6.5.5> + // they all mean the resource is NON_DAV + SAL_WARN( "ucb.ucp.webdav", "resourceTypeForLocks() DAVException (SC_FORBIDDEN, SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED) - URL: <" + << m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() ); + eResourceTypeForLocks = NON_DAV; + break; + default: + //fallthrough + SAL_WARN( "ucb.ucp.webdav", "resourceTypeForLocks() DAVException - URL: <" + << m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() ); + eResourceTypeForLocks = UNKNOWN; + } } } } - catch ( DAVException const & e ) - { - xResAccess->resetUri(); - //grab the error code - switch( e.getStatus() ) - { - case SC_NOT_FOUND: - SAL_WARN( "ucb.ucp.webdav", "resourceTypeForLocks() - URL: <" - << m_xIdentifier->getContentIdentifier() << "> was not found. "); - eResourceTypeForLocks = NOT_FOUND; - break; - // some servers returns SC_FORBIDDEN, instead - // TODO: probably remove it, when OPTIONS implemented - // the meaning of SC_FORBIDDEN is, according to <http://tools.ietf.org/html/rfc7231#section-6.5.3>: - // The 403 (Forbidden) status code indicates that the server understood - // the request but refuses to authorize it - case SC_FORBIDDEN: - // Errors SC_NOT_IMPLEMENTED and SC_METHOD_NOT_ALLOWED are - // part of base http 1.1 RFCs - case SC_NOT_IMPLEMENTED: // <http://tools.ietf.org/html/rfc7231#section-6.6.2> - case SC_METHOD_NOT_ALLOWED: // <http://tools.ietf.org/html/rfc7231#section-6.5.5> - // they all mean the resource is NON_DAV - SAL_WARN( "ucb.ucp.webdav", "resourceTypeForLocks() DAVException (SC_FORBIDDEN, SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED) - URL: <" - << m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() ); - eResourceTypeForLocks = NON_DAV; - break; - default: - //fallthrough - SAL_WARN( "ucb.ucp.webdav", "resourceTypeForLocks() DAVException - URL: <" - << m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() ); - eResourceTypeForLocks = UNKNOWN; - } - } + else + eResourceTypeForLocks = NON_DAV; + } } osl::MutexGuard g(m_aMutex); @@ -2932,6 +2963,21 @@ Content::ResourceType Content::resourceTypeForLocks( return m_eResourceTypeForLocks; } +Content::ResourceType Content::resourceTypeForLocks( + const uno::Reference< ucb::XCommandEnvironment >& Environment ) +{ + std::unique_ptr< DAVResourceAccess > xResAccess; + { + osl::MutexGuard aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + Content::ResourceType ret = resourceTypeForLocks( Environment, xResAccess ); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + return ret; +} void Content::lock( const uno::Reference< ucb::XCommandEnvironment >& Environment ) @@ -2986,7 +3032,7 @@ void Content::lock( // this exception is mapped directly to the ucb correct one, without // going into the cancelCommandExecution() user interaction // this exception should be managed by the issuer of 'lock' command - switch(e.getError()) + switch( e.getError() ) { case DAVException::DAV_LOCKED: { diff --git a/ucb/source/ucp/webdav-neon/webdavcontent.hxx b/ucb/source/ucp/webdav-neon/webdavcontent.hxx index 016f93cb3bf4..a6cb37805a43 100644 --- a/ucb/source/ucp/webdav-neon/webdavcontent.hxx +++ b/ucb/source/ucp/webdav-neon/webdavcontent.hxx @@ -184,7 +184,11 @@ private: static bool shouldAccessNetworkAfterException( const DAVException & e ); ResourceType resourceTypeForLocks( - const css::uno::Reference< css::ucb::XCommandEnvironment >& Environment ); + const css::uno::Reference< css::ucb::XCommandEnvironment >& rEnvironment, + const std::unique_ptr< DAVResourceAccess > & rResAccess ); + + ResourceType resourceTypeForLocks( + const css::uno::Reference< css::ucb::XCommandEnvironment >& rEnvironment ); void addProperty( const css::ucb::PropertyCommandArgument &aCmdArg, const css::uno::Reference< css::ucb::XCommandEnvironment >& Environment ) |