diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2021-10-08 19:30:59 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2021-11-01 18:35:33 +0100 |
commit | cb0681be80bd4423475149e05eaff180887936c8 (patch) | |
tree | 38606ff3646f1a76a0a4f9c5449ee8bb947372c1 /ucb | |
parent | 8ce2732f0a867807a9d0e70ec0966e7779d13412 (diff) |
ucb: webdav-curl: tdf#101094 (8) OPTIONS: Add options check in Content::resourceTypeForLocks
[ port of commit 6ab2cabeae02b6beb3c33238773ba075f41c4bb9 ]
Change-Id: I10f928fb5484738553769f54353ca7637e0780ce
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123290
Tested-by: Michael Stahl <michael.stahl@allotropia.de>
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'ucb')
-rw-r--r-- | ucb/source/ucp/webdav-curl/webdavcontent.cxx | 200 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/webdavcontent.hxx | 6 |
2 files changed, 128 insertions, 78 deletions
diff --git a/ucb/source/ucp/webdav-curl/webdavcontent.cxx b/ucb/source/ucp/webdav-curl/webdavcontent.cxx index 96ac6dde122a..706f3a0fb25a 100644 --- a/ucb/source/ucp/webdav-curl/webdavcontent.cxx +++ b/ucb/source/ucp/webdav-curl/webdavcontent.cxx @@ -2825,7 +2825,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; { @@ -2857,98 +2858,128 @@ 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 ) ); - { - 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); if (m_eResourceTypeForLocks == UNKNOWN) @@ -2967,6 +2998,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 ) ); + } + Content::ResourceType ret = resourceTypeForLocks( Environment, xResAccess ); + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess ) ); + } + return ret; +} void Content::lock( const uno::Reference< ucb::XCommandEnvironment >& Environment ) @@ -3020,7 +3066,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-curl/webdavcontent.hxx b/ucb/source/ucp/webdav-curl/webdavcontent.hxx index f5a74bd1f7d0..209f43516a3c 100644 --- a/ucb/source/ucp/webdav-curl/webdavcontent.hxx +++ b/ucb/source/ucp/webdav-curl/webdavcontent.hxx @@ -173,7 +173,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 ); // XPropertyContainer replacement /// @throws css::beans::PropertyExistException |