webdav: Lock files when opening them.

The implementation is not perfect but good enough as a start.

Change-Id: I6f006ae7a16ee73de20448e1228d9acfd69becb4
This commit is contained in:
Matúš Kukan
2014-03-20 09:40:06 +01:00
parent 9f586e2fbe
commit 6e0cc0cd40
7 changed files with 249 additions and 81 deletions

View File

@@ -84,6 +84,7 @@ $(eval $(call gb_Library_add_exception_objects,ucpdav1,\
ucb/source/ucp/webdav/SerfGetReqProcImpl \
ucb/source/ucp/webdav/SerfHeadReqProcImpl \
ucb/source/ucp/webdav/SerfInputStream \
ucb/source/ucp/webdav/SerfLockReqProcImpl \
ucb/source/ucp/webdav/SerfMkColReqProcImpl \
ucb/source/ucp/webdav/SerfMoveReqProcImpl \
ucb/source/ucp/webdav/SerfPostReqProcImpl \

View File

@@ -0,0 +1,165 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "SerfLockReqProcImpl.hxx"
#include "DAVException.hxx"
//#include "webdavresponseparser.hxx"
#include <rtl/strbuf.hxx>
namespace http_dav_ucp
{
SerfLockReqProcImpl::SerfLockReqProcImpl( const char* inPath,
const DAVRequestHeaders& inRequestHeaders,
const css::ucb::Lock & rLock )
: SerfRequestProcessorImpl( inPath, inRequestHeaders )
, m_aLock( rLock )
, m_xInputStream( new SerfInputStream() )
{
}
SerfLockReqProcImpl::~SerfLockReqProcImpl()
{
}
serf_bucket_t * SerfLockReqProcImpl::createSerfRequestBucket( serf_request_t * inSerfRequest )
{
serf_bucket_alloc_t* pSerfBucketAlloc = serf_request_get_alloc( inSerfRequest );
OStringBuffer aBody("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<lockinfo xmlns='DAV:'>\n <lockscope>");
// Set the lock scope
switch ( m_aLock.Scope )
{
case css::ucb::LockScope_EXCLUSIVE:
aBody.append("<exclusive/>");
break;
case css::ucb::LockScope_SHARED:
aBody.append("<shared/>");
break;
default:
throw DAVException( DAVException::DAV_INVALID_ARG );
}
aBody.append("</lockscope>\n <locktype><write/></locktype>\n");
// Set the lock owner
OUString aValue;
if ((m_aLock.Owner >>= aValue) && !aValue.isEmpty())
{
aBody.append(" <owner>");
aBody.append(OUStringToOString(aValue, RTL_TEXTENCODING_UTF8));
aBody.append("</owner>\n");
}
aBody.append("</lockinfo>\n");
const OString aBodyText(aBody.makeStringAndClear());
serf_bucket_t* body_bkt = serf_bucket_simple_copy_create( aBodyText.getStr(),
aBodyText.getLength(),
pSerfBucketAlloc );
// create serf request
serf_bucket_t *req_bkt = serf_request_bucket_request_create( inSerfRequest,
"LOCK",
getPathStr(),
body_bkt,
pSerfBucketAlloc );
handleChunkedEncoding(req_bkt, aBodyText.getLength());
// set request header fields
serf_bucket_t* hdrs_bkt = serf_bucket_request_get_headers( req_bkt );
// general header fields provided by caller
setRequestHeaders( hdrs_bkt );
// request specific header fields
const char * depth = 0;
switch( m_aLock.Depth )
{
case css::ucb::LockDepth_ZERO:
depth = "0";
break;
case css::ucb::LockDepth_ONE:
depth = "1";
break;
case css::ucb::LockDepth_INFINITY:
depth = "infinity";
break;
default:
throw DAVException( DAVException::DAV_INVALID_ARG );
}
serf_bucket_headers_set( hdrs_bkt, "Depth", depth );
serf_bucket_headers_set( hdrs_bkt, "Content-Type", "application/xml" );
// Set the lock timeout
if (m_aLock.Timeout == -1)
serf_bucket_headers_set( hdrs_bkt, "Timeout", "Infinite" );
else if (m_aLock.Timeout > 0)
{
const OString aTimeValue("Second-" + OString::number(m_aLock.Timeout));
serf_bucket_headers_set( hdrs_bkt, "Timeout", aTimeValue.getStr() );
}
osl_getSystemTime( &m_aStartCall );
return req_bkt;
}
void SerfLockReqProcImpl::processChunkOfResponseData( const char* data,
apr_size_t len )
{
if ( m_xInputStream.is() )
{
m_xInputStream->AddToStream( data, len );
}
}
void SerfLockReqProcImpl::handleEndOfResponseData( serf_bucket_t * /*inSerfResponseBucket*/ )
{
//const std::vector< DAVResourceInfo > rResInfo( parseWebDAVPropNameResponse( m_xInputStream.get() ) );
/*
if ( theRetVal == NE_OK )
{
m_aSerfLockStore.addLock( theLock,
this,
lastChanceToSendRefreshRequest(
startCall, theLock->timeout ) );
uno::Sequence< OUString > aTokens( 1 );
aTokens[ 0 ] = OUString::createFromAscii( theLock->token );
m_xLock.LockTokens = aTokens;
SAL_INFO("ucb.ucp.webdav", "SerfSession::LOCK: created lock for "
<< makeAbsoluteURL( inPath ) << ". token: " << theLock->token );
}
else
{
ne_lock_destroy( theLock );
SAL_INFO("ucb.ucp.webdav", "SerfSession::LOCK: obtaining lock for "
<< makeAbsoluteURL( inPath ) << " failed!");
}
*/
}
} // namespace http_dav_ucp
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_SERFLOCKREQPROCIMPL_HXX
#define INCLUDED_SERFLOCKREQPROCIMPL_HXX
#include "SerfRequestProcessorImpl.hxx"
#include "SerfInputStream.hxx"
#include <com/sun/star/ucb/Lock.hpp>
#include <osl/time.h>
namespace http_dav_ucp
{
class SerfLockReqProcImpl : public SerfRequestProcessorImpl
{
public:
SerfLockReqProcImpl( const char* inPath,
const DAVRequestHeaders& inRequestHeaders,
const css::ucb::Lock & rLock );
virtual ~SerfLockReqProcImpl() SAL_OVERRIDE;
virtual
serf_bucket_t * createSerfRequestBucket( serf_request_t * inSerfRequest ) SAL_OVERRIDE;
private:
virtual
void processChunkOfResponseData( const char* data, apr_size_t len ) SAL_OVERRIDE;
virtual
void handleEndOfResponseData( serf_bucket_t * inSerfResponseBucket ) SAL_OVERRIDE;
css::ucb::Lock m_aLock;
TimeValue m_aStartCall;
css::uno::Reference< SerfInputStream > m_xInputStream;
};
} // namespace http_dav_ucp
#endif // INCLUDED_SERFLOCKREQPROCIMPL_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -30,6 +30,7 @@
#include "SerfMkColReqProcImpl.hxx"
#include "SerfCopyReqProcImpl.hxx"
#include "SerfMoveReqProcImpl.hxx"
#include "SerfLockReqProcImpl.hxx"
#include <apr_strings.h>
@@ -308,6 +309,16 @@ bool SerfRequestProcessor::processMove( const OUString & inDestinationPath,
return outSerfStatus == APR_SUCCESS;
}
bool SerfRequestProcessor::processLock( const css::ucb::Lock & rLock )
{
mpProcImpl = new SerfLockReqProcImpl( mPathStr,
mrSerfSession.getRequestEnvironment().m_aRequestHeaders,
rLock );
return runProcessor() == APR_SUCCESS;
}
apr_status_t SerfRequestProcessor::runProcessor()
{
prepareProcessor();

View File

@@ -32,6 +32,7 @@
#include "SerfInputStream.hxx"
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/ucb/Lock.hpp>
namespace http_dav_ucp
{
@@ -124,6 +125,9 @@ public:
const bool inOverwrite,
apr_status_t& outSerfStatus );
//LOCK
bool processLock( const css::ucb::Lock & rLock );
apr_status_t provideSerfCredentials( char ** outUsername,
char ** outPassword,
serf_request_t * inRequest,

View File

@@ -1008,7 +1008,7 @@ namespace
// LOCK (set new lock)
void SerfSession::LOCK( const OUString & inPath,
ucb::Lock & /*rLock*/,
ucb::Lock & rLock,
const DAVRequestEnvironment & rEnv )
throw ( DAVException )
{
@@ -1017,87 +1017,9 @@ void SerfSession::LOCK( const OUString & inPath,
Init( rEnv );
boost::shared_ptr<SerfRequestProcessor> aReqProc( createReqProc( inPath ) );
aReqProc->processLock( rLock );
HandleError( aReqProc );
/* Create a depth zero, exclusive write lock, with default timeout
* (allowing a server to pick a default). token, owner and uri are
* unset. */
/*
SerfLock * theLock = ne_lock_create();
// Set the lock uri
ne_uri aUri;
ne_uri_parse( OUStringToOString( makeAbsoluteURL( inPath ),
RTL_TEXTENCODING_UTF8 ).getStr(),
&aUri );
theLock->uri = aUri;
// Set the lock depth
switch( rLock.Depth )
{
case ucb::LockDepth_ZERO:
theLock->depth = NE_DEPTH_ZERO;
break;
case ucb::LockDepth_ONE:
theLock->depth = NE_DEPTH_ONE;
break;
case ucb::LockDepth_INFINITY:
theLock->depth = NE_DEPTH_INFINITE;
break;
default:
throw DAVException( DAVException::DAV_INVALID_ARG );
}
// Set the lock scope
switch ( rLock.Scope )
{
case ucb::LockScope_EXCLUSIVE:
theLock->scope = ne_lockscope_exclusive;
break;
case ucb::LockScope_SHARED:
theLock->scope = ne_lockscope_shared;
break;
default:
throw DAVException( DAVException::DAV_INVALID_ARG );
}
// Set the lock timeout
theLock->timeout = (long)rLock.Timeout;
// Set the lock owner
OUString aValue;
rLock.Owner >>= aValue;
theLock->owner =
ne_strdup( OUStringToOString( aValue,
RTL_TEXTENCODING_UTF8 ).getStr() );
TimeValue startCall;
osl_getSystemTime( &startCall );
int theRetVal = ne_lock( m_pHttpSession, theLock );
if ( theRetVal == NE_OK )
{
m_aSerfLockStore.addLock( theLock,
this,
lastChanceToSendRefreshRequest(
startCall, theLock->timeout ) );
uno::Sequence< OUString > aTokens( 1 );
aTokens[ 0 ] = OUString::createFromAscii( theLock->token );
rLock.LockTokens = aTokens;
SAL_INFO("ucb.ucp.webdav", "SerfSession::LOCK: created lock for "
<< makeAbsoluteURL( inPath ) << ". token: " << theLock->token );
}
else
{
ne_lock_destroy( theLock );
SAL_INFO("ucb.ucp.webdav", "SerfSession::LOCK: obtaining lock for "
<< makeAbsoluteURL( inPath ) << " failed!");
}
HandleError( theRetVal, inPath, rEnv );
*/
}

View File

@@ -590,6 +590,11 @@ uno::Any SAL_CALL Content::execute(
}
aRet = open( aOpenCommand, Environment );
if ( (aOpenCommand.Mode == ucb::OpenMode::DOCUMENT ||
aOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE) &&
supportsExclusiveWriteLock( Environment ) )
lock( Environment );
}
else if ( aCommand.Name == "insert" )
{