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:
@@ -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 \
|
||||
|
165
ucb/source/ucp/webdav/SerfLockReqProcImpl.cxx
Normal file
165
ucb/source/ucp/webdav/SerfLockReqProcImpl.cxx
Normal 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: */
|
60
ucb/source/ucp/webdav/SerfLockReqProcImpl.hxx
Normal file
60
ucb/source/ucp/webdav/SerfLockReqProcImpl.hxx
Normal 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: */
|
@@ -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();
|
||||
|
@@ -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,
|
||||
|
@@ -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 );
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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" )
|
||||
{
|
||||
|
Reference in New Issue
Block a user