ucb/source/ucp/webdav-curl/webdavcontent.cxx |  200 ++++++++++++++++-----------
 ucb/source/ucp/webdav-curl/webdavcontent.hxx |    6 
 2 files changed, 128 insertions(+), 78 deletions(-)

New commits:
commit cb0681be80bd4423475149e05eaff180887936c8
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Oct 8 19:30:59 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Nov 1 18:35:33 2021 +0100

    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.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

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

Reply via email to