Kaydet (Commit) 522de035 authored tarafından Giuseppe Castagno's avatar Giuseppe Castagno Kaydeden (comit) Christian Lohmaier

tdf#95792: fix saving file the first time on some WebDAV servers.

Some WebDAV servers don't implement section 7.3 of RFC4918:
<http://tools.ietf.org/html/rfc4918#section-7.3>

This lack of implementation breaks 'Save As...' functionality
when the target is a WebDAV server, by not locking the URL
('reserve the name for use', in RFC4918 parlance).

The server not implementing this usually answers with one of
'405 Method Not Allowed', '501 Not Implemented' or
'412 Precondition Failed' http error codes.

The fix should manage this lack of implementation.

Change-Id: Ie4689a076aafa365106d02b3ea16459a28fcde65
Reviewed-on: https://gerrit.libreoffice.org/20600Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarStephan Bergmann <sbergman@redhat.com>
(cherry picked from commit 4c82edfb)
Reviewed-on: https://gerrit.libreoffice.org/20722Reviewed-by: 's avatarChristian Lohmaier <lohmaier+LibreOffice@googlemail.com>
Tested-by: 's avatarChristian Lohmaier <lohmaier+LibreOffice@googlemail.com>
üst c3d24d64
...@@ -2083,11 +2083,37 @@ void SfxMedium::Transfer_Impl() ...@@ -2083,11 +2083,37 @@ void SfxMedium::Transfer_Impl()
sComment = pComments->GetValue( ); sComment = pComments->GetValue( );
} }
OUString sResultURL; OUString sResultURL;
if (!aTransferContent.transferContent( aSourceContent, eOperation, bool isTransferOK = aTransferContent.transferContent(
aFileName, nNameClash, aMimeType, bMajor, sComment, &sResultURL, sObjectId)) aSourceContent, eOperation,
aFileName, nNameClash, aMimeType, bMajor, sComment,
&sResultURL, sObjectId );
if ( !isTransferOK )
pImp->m_eError = ERRCODE_IO_GENERAL; pImp->m_eError = ERRCODE_IO_GENERAL;
else if ( !sResultURL.isEmpty( ) ) // Likely to happen only for checkin else if ( !sResultURL.isEmpty( ) ) // Likely to happen only for checkin
SwitchDocumentToFile( sResultURL ); SwitchDocumentToFile( sResultURL );
try
{
if ( GetURLObject().isAnyKnownWebDAVScheme() &&
isTransferOK &&
eOperation == ::ucbhelper::InsertOperation_COPY )
{
// tdf#95272 try to re-issue a lock command when a new file is created.
// This may be needed because some WebDAV servers fail to implement the
// 'LOCK on unallocated reference', see issue comment:
// <https://bugs.documentfoundation.org/show_bug.cgi?id=95792#c8>
// and specification at:
// <http://tools.ietf.org/html/rfc4918#section-7.3>
// If the WebDAV resource is already locked by this LO instance, nothing will
// happen, e.g. the LOCK method will not be sent to the server.
::ucbhelper::Content aLockContent = ::ucbhelper::Content( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xComEnv, comphelper::getProcessComponentContext() );
aLockContent.lock();
}
}
catch ( css::uno::Exception & e )
{
SAL_WARN( "sfx.doc", "LOCK not working while re-issuing it. Exception message: " << e.Message );
}
} }
catch ( const css::ucb::CommandAbortedException& ) catch ( const css::ucb::CommandAbortedException& )
{ {
......
...@@ -596,7 +596,7 @@ NeonSession::NeonSession( const rtl::Reference< DAVSessionFactory > & rSessionFa ...@@ -596,7 +596,7 @@ NeonSession::NeonSession( const rtl::Reference< DAVSessionFactory > & rSessionFa
m_aScheme = theUri.GetScheme(); m_aScheme = theUri.GetScheme();
m_aHostName = theUri.GetHost(); m_aHostName = theUri.GetHost();
m_nPort = theUri.GetPort(); m_nPort = theUri.GetPort();
SAL_INFO( "ucb.ucp.webdav", "NeonSession ctor - URL < " << inUri << ">" ); SAL_INFO( "ucb.ucp.webdav", "NeonSession ctor - URL <" << inUri << ">" );
} }
NeonSession::~NeonSession( ) NeonSession::~NeonSession( )
......
...@@ -2872,16 +2872,16 @@ Content::ResourceType Content::resourceTypeForLocks( ...@@ -2872,16 +2872,16 @@ Content::ResourceType Content::resourceTypeForLocks(
<< m_xIdentifier->getContentIdentifier() << "> was not found. "); << m_xIdentifier->getContentIdentifier() << "> was not found. ");
eResourceTypeForLocks = NOT_FOUND; eResourceTypeForLocks = NOT_FOUND;
break; break;
// some servers returns this, instead // some servers returns SC_FORBIDDEN, instead
// TODO: probably remove it, when OPTIONS implemented // 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 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 403 (Forbidden) status code indicates that the server understood
// the request but refuses to authorize it // the request but refuses to authorize it
case SC_FORBIDDEN: case SC_FORBIDDEN:
// this returned errors are part of base http 1.1 RFCs // Errors SC_NOT_IMPLEMENTED and SC_METHOD_NOT_ALLOWED are
// see: // part of base http 1.1 RFCs
case SC_NOT_IMPLEMENTED: // http://tools.ietf.org/html/rfc7231#section-6.6.2 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 case SC_METHOD_NOT_ALLOWED: // <http://tools.ietf.org/html/rfc7231#section-6.5.5>
// they all mean the resource is NON_DAV // 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: <" 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() ); << m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() );
...@@ -2986,7 +2986,7 @@ void Content::lock( ...@@ -2986,7 +2986,7 @@ void Content::lock(
{ {
SAL_WARN( "ucb.ucp.webdav", "lock() DAVException Authentication error - URL: <" SAL_WARN( "ucb.ucp.webdav", "lock() DAVException Authentication error - URL: <"
<< m_xIdentifier->getContentIdentifier() << ">" ); << m_xIdentifier->getContentIdentifier() << ">" );
// this could mean: // DAVException::DAV_HTTP_AUTH exception can mean:
// - interaction handler for credential management not present (happens, depending // - interaction handler for credential management not present (happens, depending
// on the LO framework processing) // on the LO framework processing)
// - the remote site is a WebDAV with special configuration: read/only for read operations // - the remote site is a WebDAV with special configuration: read/only for read operations
...@@ -3008,20 +3008,28 @@ void Content::lock( ...@@ -3008,20 +3008,28 @@ void Content::lock(
//grab the error code //grab the error code
switch( e.getStatus() ) switch( e.getStatus() )
{ {
// this returned error is part of base http 1.1 RFCs // The 'case SC_PRECONDITION_FAILED' just below tries to solve a problem
case SC_NOT_IMPLEMENTED: // in SharePoint when locking the resource on first creation fails due to this:
case SC_METHOD_NOT_ALLOWED: // <https://msdn.microsoft.com/en-us/library/jj575265%28v=office.12%29.aspx#id15>
SAL_WARN( "ucb.ucp.webdav", "lock() DAVException (SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED) - URL: <" // (retrieved on 2015-08-14)
case SC_PRECONDITION_FAILED: // <http://tools.ietf.org/html/rfc7232#section-4.2>
// 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>
SAL_WARN( "ucb.ucp.webdav", "lock() DAVException (SC_PRECONDITION_FAILED, SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED) - URL: <"
<< m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() ); << m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() );
// act as nothing happened // act as nothing happened
// that's because when a resource is first created // that's because when a resource is first created
// the lock is sent before the put, so the resource // the lock is sent before the put, so the resource
// is actually created by LOCK, locking it before // is actually created by LOCK, locking it before
// doing the first PUT, but if LOCK is not supported // the first PUT, but if LOCK is not supported
// (simple web or DAV with lock disabled) we end with one of these two http // (simple web or DAV with lock disabled) we end with one of these http
// errors // errors.
// details to LOCK on an unmapped (i.e. non existent) resource are in: // These same errors may be reported when the LOCK on an unmapped
// http://tools.ietf.org/html/rfc4918#section-7.3 // (i.e. non existent) resource is not implemented.
// Detailed specification in:
// <http://tools.ietf.org/html/rfc4918#section-7.3>
return; return;
break; break;
default: default:
...@@ -3084,9 +3092,10 @@ void Content::unlock( ...@@ -3084,9 +3092,10 @@ void Content::unlock(
//grab the error code //grab the error code
switch( e.getStatus() ) switch( e.getStatus() )
{ {
// this returned error is part of base http 1.1 RFCs // Errors SC_NOT_IMPLEMENTED and SC_METHOD_NOT_ALLOWED are
case SC_NOT_IMPLEMENTED: // part of base http 1.1 RFCs
case SC_METHOD_NOT_ALLOWED: 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>
SAL_WARN( "ucb.ucp.webdav", "unlock() DAVException (SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED) - URL: <" SAL_WARN( "ucb.ucp.webdav", "unlock() DAVException (SC_NOT_IMPLEMENTED or SC_METHOD_NOT_ALLOWED) - URL: <"
<< m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() ); << m_xIdentifier->getContentIdentifier() << ">, DAV error: " << e.getError() << ", HTTP error: " << e.getStatus() );
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment