--- officecfg/registry/data/org/openoffice/ucb/Configuration.xcu
+++ officecfg/registry/data/org/openoffice/ucb/Configuration.xcu
@@ -178,6 +178,28 @@
+
+
+ com.sun.star.ucb.WebDAVContentProvider
+
+
+ webdav
+
+
+
+
+
+
+
+ com.sun.star.ucb.WebDAVContentProvider
+
+
+ webdavs
+
+
+
+
+
--- sc/source/ui/docshell/docsh.cxx.old 2009-04-02 10:45:27.000000000 +0000
+++ sc/source/ui/docshell/docsh.cxx 2009-04-06 16:41:46.000000000 +0000
@@ -823,7 +823,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( S
// Alle Filter brauchen die komplette Datei am Stueck (nicht asynchron),
// darum vorher per CreateFileStream dafuer sorgen, dass die komplette
// Datei uebertragen wird.
- rMedium.GetPhysicalName(); //! CreateFileStream direkt rufen, wenn verfuegbar
+ rMedium.GetPhysicalName( sal_False ); //! CreateFileStream direkt rufen, wenn verfuegbar
SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
--- sfx2/inc/sfx2/docfile.hxx
+++ sfx2/inc/sfx2/docfile.hxx
@@ -186,7 +186,7 @@ public:
::com::sun::star::util::DateTime GetInitFileDate( sal_Bool bIgnoreOldValue );
::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent > GetContent() const;
- const String& GetPhysicalName() const;
+ const String& GetPhysicalName( sal_Bool bForceCreateTempIfRemote = sal_True ) const;
void SetTemporary( sal_Bool bTemp );
sal_Bool IsTemporary() const;
sal_Bool IsRemote();
@@ -260,6 +260,8 @@ public:
void SetCharset( ::rtl::OUString );
::rtl::OUString GetBaseURL( bool bForSaving=false );
+ sal_Bool SupportsActiveStreaming( const rtl::OUString &rName ) const;
+
#if _SOLAR__PRIVATE
SAL_DLLPRIVATE BOOL HasStorage_Impl() const;
--- sfx2/source/doc/docfile.cxx
+++ sfx2/source/doc/docfile.cxx
@@ -533,7 +533,7 @@
//------------------------------------------------------------------
sal_Bool SfxMedium::DocNeedsFileDateCheck()
{
- return ( !IsReadOnly() && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
+ return ( !IsReadOnly() && SupportsActiveStreaming( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
}
//------------------------------------------------------------------
@@ -749,10 +749,13 @@
}
//------------------------------------------------------------------
-const String& SfxMedium::GetPhysicalName() const
+const String& SfxMedium::GetPhysicalName( sal_Bool bForceCreateTempIfRemote ) const
{
if ( !aName.Len() && aLogicName.Len() )
- (( SfxMedium*)this)->CreateFileStream();
+ {
+ if ( bForceCreateTempIfRemote || !SupportsActiveStreaming( aLogicName ) )
+ (( SfxMedium*)this)->CreateFileStream();
+ }
// return the name then
return aName;
@@ -928,6 +929,26 @@
return bPreview;
}
+//------------------------------------------------------------------
+sal_Bool SfxMedium::SupportsActiveStreaming( const rtl::OUString &rName ) const
+{
+ if ( ::utl::LocalFileHelper::IsLocalFile( rName ) )
+ return sal_True;
+
+ ::ucbhelper::Content aTmpContent;
+ Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
+ if ( ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aTmpContent ) )
+ {
+ Any aAny = aTmpContent.getPropertyValue(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "SupportsActiveStreaming" )) );
+
+ sal_Bool bSupportsStreaming = sal_False;
+ return ( ( aAny >>= bSupportsStreaming ) && bSupportsStreaming );
+ }
+
+ return sal_False;
+}
+
//------------------------------------------------------------------
void SfxMedium::StorageBackup_Impl()
{
@@ -924,7 +924,7 @@
sal_Bool bBasedOnOriginalFile = ( !pImp->pTempFile && !( aLogicName.Len() && pImp->m_bSalvageMode )
&& GetURLObject().GetMainURL( INetURLObject::NO_DECODE ).getLength()
- && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
+ && SupportsActiveStreaming( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
&& ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
if ( bBasedOnOriginalFile && !pImp->m_aBackupURL.getLength()
@@ -2210,7 +2326,7 @@ void SfxMedium::Transfer_Impl()
xComEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler,
Reference< ::com::sun::star::ucb::XProgressHandler >() );
- if ( ::utl::LocalFileHelper::IsLocalFile( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) || !aDest.removeSegment() )
+ if ( SupportsActiveStreaming( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) || !aDest.removeSegment() )
{
TransactedTransferForFS_Impl( aSource, aDest, xComEnv );
}
@@ -2542,7 +2658,7 @@ void SfxMedium::GetMedium_Impl()
aMedium.erase( comphelper::MediaDescriptor::PROP_READONLY() );
aMedium.addInputStream();
}
- else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
+ else if ( SupportsActiveStreaming( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
{
// use the special locking approach only for file URLs
aMedium.addInputStreamOwnLock();
@@ -3249,7 +3249,7 @@
if ( !( nStorOpenMode & STREAM_TRUNC ) )
{
if ( GetContent().is()
- && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
+ && SupportsActiveStreaming( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
&& ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
{
// if there is already such a document, we should copy it
--- sfx2/source/view/viewfrm.cxx
+++ sfx2/source/view/viewfrm.cxx
@@ -631,6 +631,11 @@ void SfxViewFrame::ExecReload_Impl( SfxR
sal_Bool bHandsOff =
( pMedium->GetURLObject().GetProtocol() == INET_PROT_FILE && !xOldObj->IsDocShared() );
+ // we must do the same for the contents that support active
+ // streaming
+ if ( !bHandsOff && pMedium && pMedium->SupportsActiveStreaming( aURL ) )
+ bHandsOff = sal_True;
+
// bestehende SfxMDIFrames f"ur dieses Doc leeren
// eigenes Format oder R/O jetzt editierbar "offnen?
SfxViewNotificatedFrameList_Impl aFrames;
--- tools/inc/tools/urlobj.hxx
+++ tools/inc/tools/urlobj.hxx
@@ -141,9 +141,14 @@ enum INetProtocol
INET_PROT_TELNET = 28,
INET_PROT_VND_SUN_STAR_EXPAND = 29,
INET_PROT_VND_SUN_STAR_TDOC = 30,
- INET_PROT_GENERIC = 31,
- INET_PROT_SMB = 32,
- INET_PROT_END = 33
+ INET_PROT_SMB = 31,
+ INET_PROT_DAV = 32,
+ INET_PROT_DAVS = 33,
+ INET_PROT_WEBDAV = 34,
+ INET_PROT_WEBDAVS = 35,
+ INET_PROT_GENERIC = 36,
+ INET_PROT_GENERIC_HIERARCHICAL = 37,
+ INET_PROT_END = 38
};
//============================================================================
--- tools/source/fsys/urlobj.cxx
+++ tools/source/fsys/urlobj.cxx
@@ -374,21 +374,21 @@ static INetURLObject::SchemeInfo const a
false },
{ "ftp", "ftp://", 21, true, true, false, true, true, true, true,
false },
- { "http", "http://", 80, true, false, false, false, true, true,
+ { "http", "http://", 80, true, true, false, true, true, true,
true, true },
{ "file", "file://", 0, true, false, false, false, true, false,
true, false },
{ "mailto", "mailto:", 0, false, false, false, false, false,
false, false, true },
- { "vnd.sun.star.webdav", "vnd.sun.star.webdav://", 80, true, false,
- false, false, true, true, true, true },
+ { "vnd.sun.star.webdav", "vnd.sun.star.webdav://", 80, true, true,
+ false, true, true, true, true, true },
{ "news", "news:", 0, false, false, false, false, false, false, false,
false },
{ "private", "private:", 0, false, false, false, false, false,
false, false, true },
{ "vnd.sun.star.help", "vnd.sun.star.help://", 0, true, false, false,
false, false, false, true, true },
- { "https", "https://", 443, true, false, false, false, true, true,
+ { "https", "https://", 443, true, true, false, true, true, true,
true, true },
{ "slot", "slot:", 0, false, false, false, false, false, false,
false, true },
@@ -432,9 +432,19 @@ static INetURLObject::SchemeInfo const a
false, false, false, false, false },
{ "vnd.sun.star.tdoc", "vnd.sun.star.tdoc:", 0, false, false, false,
false, false, false, true, false },
- { "", "", 0, false, false, false, false, false, false, false, false },
{ "smb", "smb://", 139, true, true, false, true, true, true, true,
- true } };
+ true },
+ { "dav", "dav://", 80, true, true, false, true, true, true, true,
+ true },
+ { "davs", "davs://", 443, true, true, false, true, true, true,
+ true, true },
+ { "webdav", "webdav://", 80, true, true, false, true, true, true, true,
+ true },
+ { "webdavs", "webdavs://", 443, true, true, false, true, true, true,
+ true, true },
+ { "", "", 0, false, false, false, false, false, false, false, false },
+ { "", "", 0, false, false, false, false, false, false, true, false }
+ };
// static
inline INetURLObject::SchemeInfo const &
@@ -849,7 +859,10 @@ bool INetURLObject::setAbsURIRef(rtl::OU
aSynScheme = parseScheme(&p1, pEnd, nFragmentDelimiter);
if (aSynScheme.getLength() > 0)
{
- m_eScheme = INET_PROT_GENERIC;
+ if (p1 != pEnd && *p1 == '/')
+ m_eScheme = INET_PROT_GENERIC_HIERARCHICAL;
+ else
+ m_eScheme = INET_PROT_GENERIC;
pPos = p1;
}
}
@@ -866,8 +879,9 @@ bool INetURLObject::setAbsURIRef(rtl::OU
return false;
}
- if (m_eScheme != INET_PROT_GENERIC) {
- aSynScheme = rtl::OUString::createFromAscii(getSchemeInfo().m_pScheme);
+ const char *pSchemeName = getSchemeInfo().m_pScheme;
+ if (pSchemeName[0] != '\0') {
+ aSynScheme = rtl::OUString::createFromAscii(pSchemeName);
}
m_aScheme.set(aSynAbsURIRef, aSynScheme, aSynAbsURIRef.getLength());
aSynAbsURIRef.append(sal_Unicode(':'));
@@ -2120,6 +2134,8 @@ INetURLObject::getPrefix(sal_Unicode con
PrefixInfo::INTERNAL },
{ "cid:", 0, INET_PROT_CID, PrefixInfo::OFFICIAL },
{ "data:", 0, INET_PROT_DATA, PrefixInfo::OFFICIAL },
+ { "dav:", 0, INET_PROT_DAV, PrefixInfo::OFFICIAL },
+ { "davs:", 0, INET_PROT_DAVS, PrefixInfo::OFFICIAL },
{ "db:", "staroffice.db:", INET_PROT_DB, PrefixInfo::INTERNAL },
{ "file:", 0, INET_PROT_FILE, PrefixInfo::OFFICIAL },
{ "ftp:", 0, INET_PROT_FTP, PrefixInfo::OFFICIAL },
@@ -2201,6 +2217,8 @@ INetURLObject::getPrefix(sal_Unicode con
PrefixInfo::OFFICIAL },
{ "vnd.sun.star.wfs:", 0, INET_PROT_VND_SUN_STAR_WFS,
PrefixInfo::OFFICIAL },
+ { "webdav:", 0, INET_PROT_WEBDAV, PrefixInfo::OFFICIAL },
+ { "webdavs:", 0, INET_PROT_WEBDAVS, PrefixInfo::OFFICIAL },
{ "wfs:", "vnd.sun.star.wfs:", INET_PROT_VND_SUN_STAR_WFS,
PrefixInfo::ALIAS } };
PrefixInfo const * pFirst = aMap + 1;
@@ -3004,6 +3022,10 @@ bool INetURLObject::parsePath(INetProtoc
case INET_PROT_VND_SUN_STAR_WEBDAV:
case INET_PROT_HTTPS:
case INET_PROT_SMB:
+ case INET_PROT_DAV:
+ case INET_PROT_DAVS:
+ case INET_PROT_WEBDAV:
+ case INET_PROT_WEBDAVS:
if (pPos < pEnd && *pPos != '/')
return false;
while (pPos < pEnd && *pPos != nQueryDelimiter
@@ -3422,6 +3444,7 @@ bool INetURLObject::parsePath(INetProtoc
break;
case INET_PROT_GENERIC:
+ case INET_PROT_GENERIC_HIERARCHICAL:
while (pPos < pEnd && *pPos != nFragmentDelimiter)
{
EscapeType eEscapeType;
@@ -4133,10 +4156,13 @@ bool INetURLObject::ConcatData(INetProto
{
setInvalid();
m_eScheme = eTheScheme;
- if (HasError() || m_eScheme == INET_PROT_GENERIC)
+ const char *pSchemeName = getSchemeInfo().m_pScheme;
+
+ if (HasError() || pSchemeName[0] == '\0')
return false;
+
m_aAbsURIRef.setLength(0);
- m_aAbsURIRef.appendAscii(getSchemeInfo().m_pScheme);
+ m_aAbsURIRef.appendAscii(pSchemeName);
m_aAbsURIRef.append(sal_Unicode(':'));
if (getSchemeInfo().m_bAuthority)
{
--- tools/workben/urltest.cxx
+++ tools/workben/urltest.cxx
@@ -1476,7 +1476,7 @@ main()
url = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("A-b.3:/%2f?x#y"));
urlobj = INetURLObject(url);
- bSuccess &= assertEqual(url, INET_PROT_GENERIC, urlobj.GetProtocol());
+ bSuccess &= assertEqual(url, INET_PROT_GENERIC_HIERARCHICAL, urlobj.GetProtocol());
bSuccess &= assertEqual(
url, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a-b.3:/%2F?x#y")),
rtl::OUString(urlobj.GetMainURL(INetURLObject::NO_DECODE)));
@@ -1504,7 +1504,7 @@ main()
url = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("foo:/"));
urlobj = INetURLObject(url);
- bSuccess &= assertEqual(url, INET_PROT_GENERIC, urlobj.GetProtocol());
+ bSuccess &= assertEqual(url, INET_PROT_GENERIC_HIERARCHICAL, urlobj.GetProtocol());
bSuccess &= assertEqual(
url, url,
rtl::OUString(urlobj.GetMainURL(INetURLObject::NO_DECODE)));
@@ -1542,7 +1542,7 @@ main()
url = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("A-b.3:/%2f?x#y"));
urlobj = INetURLObject(url, INET_PROT_CID);
- bSuccess &= assertEqual(url, INET_PROT_GENERIC, urlobj.GetProtocol());
+ bSuccess &= assertEqual(url, INET_PROT_GENERIC_HIERARCHICAL, urlobj.GetProtocol());
bSuccess &= assertEqual(
url, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a-b.3:/%2F?x#y")),
rtl::OUString(urlobj.GetMainURL(INetURLObject::NO_DECODE)));
@@ -1563,7 +1563,7 @@ main()
url = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("foo:/"));
urlobj = INetURLObject(url, INET_PROT_CID);
- bSuccess &= assertEqual(url, INET_PROT_GENERIC, urlobj.GetProtocol());
+ bSuccess &= assertEqual(url, INET_PROT_GENERIC_HIERARCHICAL, urlobj.GetProtocol());
bSuccess &= assertEqual(
url, url,
rtl::OUString(urlobj.GetMainURL(INetURLObject::NO_DECODE)));
--- ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
+++ ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
@@ -34,6 +34,8 @@
#include
#include "DAVAuthListener.hxx"
+#include
+
namespace webdav_ucp
{
typedef std::pair< rtl::OUString, rtl::OUString > DAVRequestHeader;
@@ -46,12 +50,12 @@ struct DAVRequestEnvironment
// rtl::Reference< DAVStatusListener > m_xStatusListener;
// rtl::Reference< DAVProgressListener > m_xStatusListener;
DAVRequestHeaders m_aRequestHeaders;
- uno::Reference< ucb::XCommandEnvironment > m_xEnv;
+ com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > m_xEnv;
-DAVRequestEnvironment( const rtl::OUString & rRequestURI,
+ DAVRequestEnvironment( const rtl::OUString & rRequestURI,
const rtl::Reference< DAVAuthListener > & xListener,
const DAVRequestHeaders & rRequestHeaders,
- const uno::Reference< ucb::XCommandEnvironment > & xEnv)
+ const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv)
: m_aRequestURI( rRequestURI ),
m_xAuthListener( xListener ),
m_aRequestHeaders( rRequestHeaders ),
--- ucb/source/ucp/webdav/DAVResourceAccess.cxx
+++ ucb/source/ucp/webdav/DAVResourceAccess.cxx
@@ -42,6 +42,9 @@
#include "DAVAuthListenerImpl.hxx"
#include "DAVResourceAccess.hxx"
+#include
+#include
+
using namespace webdav_ucp;
using namespace com::sun::star;
@@ -61,11 +64,18 @@ int DAVAuthListener_Impl::authenticate(
sal_Bool bAllowPersistentStoring,
sal_Bool bCanUseSystemCredentials )
{
+ uno::Reference< task::XInteractionHandler > xIH;
+
if ( m_xEnv.is() )
{
- uno::Reference< task::XInteractionHandler > xIH
- = m_xEnv->getInteractionHandler();
+ xIH = m_xEnv->getInteractionHandler();
+ }
+ else
+ {
+ xIH = DAVResourceAccess::createCommandEnvironment()->getInteractionHandler();
+ }
+
+ {
- if ( xIH.is() )
{
// #102871# - Supply username and password from previous try.
// Password container service depends on this!
@@ -444,15 +446,16 @@ void DAVResourceAccess::GET(
}
//=========================================================================
-uno::Reference< io::XInputStream > DAVResourceAccess::GET(
+uno::Reference< io::XStream > DAVResourceAccess::GET(
const std::vector< rtl::OUString > & rHeaderNames,
DAVResource & rResource,
- const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv,
+ sal_Bool bAllowEmpty )
throw( DAVException )
{
initialize();
- uno::Reference< io::XInputStream > xStream;
+ uno::Reference< io::XStream > xStream;
int errorCount = 0;
bool bRetry;
do
@@ -472,7 +475,8 @@ uno::Reference< io::XInputStream > DAVRe
DAVRequestEnvironment(
getRequestURI(),
new DAVAuthListener_Impl( xEnv, m_aURL ),
- aHeaders, xEnv ) );
+ aHeaders, xEnv ),
+ bAllowEmpty );
}
catch ( DAVException & e )
{
@@ -606,6 +610,45 @@ void DAVResourceAccess::PUT(
}
//=========================================================================
+void DAVResourceAccess::PUT(
+ const char * buffer, size_t size,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+throw( DAVException )
+{
+ initialize();
+
+ bool bRetry = false;
+ int errorCount = 0;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "PUT" ),
+ aHeaders );
+
+ m_xSession->PUT( getRequestURI(),
+ buffer, size,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
uno::Reference< io::XInputStream > DAVResourceAccess::POST(
const rtl::OUString & rContentType,
const rtl::OUString & rReferer,
@@ -888,22 +931,44 @@ void DAVResourceAccess::DESTROY(
//=========================================================================
void DAVResourceAccess::LOCK (
- const ucb::Lock & /*rLock*/,
- const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
+ ucb::Lock & rLock,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
throw( DAVException )
{
-// initialize();
- OSL_ENSURE( sal_False, "DAVResourceAccess::LOCK - NYI" );
+ initialize();
+
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "LOCK" ),
+ aHeaders );
+
+ m_xSession->LOCK( rLock,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
}
//=========================================================================
void DAVResourceAccess::UNLOCK (
- const ucb::Lock & /*rLock*/,
- const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
+ ucb::Lock & rLock,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
throw( DAVException )
{
-// initialize();
- OSL_ENSURE( sal_False, "DAVResourceAccess::UNLOCK - NYI" );
+ initialize();
+
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "UNLOCK" ),
+ aHeaders );
+
+ m_xSession->UNLOCK( rLock,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
}
//=========================================================================
@@ -1008,6 +1073,18 @@ void DAVResourceAccess::getUserRequestHe
}
}
+// static
+com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > DAVResourceAccess::createCommandEnvironment( void )
+{
+ uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
+ uno::Reference< task::XInteractionHandler > xInteractionHandler = uno::Reference< task::XInteractionHandler > (
+ xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), uno::UNO_QUERY );
+ ucbhelper::CommandEnvironment* pCommandEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, uno::Reference< ucb::XProgressHandler >() );
+
+ return uno::Reference< ucb::XCommandEnvironment >( static_cast< ucb::XCommandEnvironment* >( pCommandEnv ), uno::UNO_QUERY );
+}
+
+
//=========================================================================
sal_Bool DAVResourceAccess::detectRedirectCycle(
const rtl::OUString& rRedirectURL )
--- ucb/source/ucp/webdav/DAVResourceAccess.hxx
+++ ucb/source/ucp/webdav/DAVResourceAccess.hxx
@@ -134,11 +134,12 @@ public:
com::sun::star::ucb::XCommandEnvironment > & xEnv )
throw( DAVException );
- com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ com::sun::star::uno::Reference< com::sun::star::io::XStream >
GET( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
DAVResource & rResource,
const com::sun::star::uno::Reference<
- com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ com::sun::star::ucb::XCommandEnvironment > & xEnv,
+ sal_Bool bAllowEmpty = sal_False )
throw( DAVException );
void
@@ -157,6 +158,11 @@ public:
com::sun::star::ucb::XCommandEnvironment > & xEnv )
throw( DAVException );
+ void
+ PUT( const char * buffer, size_t size,
+ const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException );
+
com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
POST( const rtl::OUString & rContentType,
const rtl::OUString & rReferer,
@@ -204,13 +210,13 @@ public:
throw( DAVException );
void
- LOCK( const com::sun::star::ucb::Lock & rLock,
+ LOCK( com::sun::star::ucb::Lock & rLock,
const com::sun::star::uno::Reference<
com::sun::star::ucb::XCommandEnvironment > & xEnv )
throw( DAVException );
void
- UNLOCK( const com::sun::star::ucb::Lock & rLock,
+ UNLOCK( com::sun::star::ucb::Lock & rLock,
const com::sun::star::uno::Reference<
com::sun::star::ucb::XCommandEnvironment > & xEnv )
throw( DAVException );
@@ -223,6 +229,8 @@ public:
const rtl::OUString & rMethod,
DAVRequestHeaders & rRequestHeaders );
+ static com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > createCommandEnvironment( void );
+
private:
const rtl::OUString & getRequestURI() const;
sal_Bool detectRedirectCycle( const rtl::OUString& rRedirectURL )
--- ucb/source/ucp/webdav/DAVSession.hxx
+++ ucb/source/ucp/webdav/DAVSession.hxx
@@ -33,8 +33,11 @@
#include
#include
+#include
#include
#include
+#include
+
#include "DAVException.hxx"
#include "DAVProperties.hxx"
#include "DAVResource.hxx"
@@ -42,8 +45,6 @@
#include "DAVTypes.hxx"
#include "DAVRequestEnvironment.hxx"
-
-
namespace webdav_ucp
{
@@ -114,11 +115,12 @@ public:
const DAVRequestEnvironment & rEnv )
throw( DAVException ) = 0;
- virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ virtual com::sun::star::uno::Reference< com::sun::star::io::XStream >
GET( const ::rtl::OUString & inPath,
const std::vector< ::rtl::OUString > & inHeaderNames,
DAVResource & ioResource,
- const DAVRequestEnvironment & rEnv )
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool bAllowEmpty )
throw( DAVException ) = 0;
virtual void GET( const ::rtl::OUString & inPath,
@@ -134,6 +136,12 @@ public:
virtual void ABORT()
throw( DAVException ) = 0;
+ virtual void PUT( const ::rtl::OUString & inPath,
+ const char * buffer,
+ size_t size,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException ) = 0;
+
virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
POST( const rtl::OUString & inPath,
const rtl::OUString & rContentType,
@@ -173,16 +181,14 @@ public:
const DAVRequestEnvironment & rEnv )
throw( DAVException ) = 0;
- // Note: Uncomment the following if locking support is required
- /*
- virtual void LOCK ( const Lock & inLock,
+ virtual void LOCK ( com::sun::star::ucb::Lock & rLock,
const DAVRequestEnvironment & rEnv )
throw( DAVException ) = 0;
- virtual void UNLOCK ( const Lock & inLock,
+ virtual void UNLOCK ( com::sun::star::ucb::Lock & rLock,
const DAVRequestEnvironment & rEnv )
throw( DAVException ) = 0;
- */
+
protected:
rtl::Reference< DAVSessionFactory > m_xFactory;
--- ucb/source/ucp/webdav/NeonInputStream.cxx
+++ ucb/source/ucp/webdav/NeonInputStream.cxx
@@ -31,21 +31,28 @@
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"
#include "NeonInputStream.hxx"
+#include "DAVResourceAccess.hxx"
+
#include
+#include
+
+#include
+#include
+
+#include
using namespace cppu;
-using namespace rtl;
using namespace com::sun::star::io;
-using namespace com::sun::star::uno;
+using namespace com::sun::star;
using namespace webdav_ucp;
-
// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
-NeonInputStream::NeonInputStream( void )
-: mLen( 0 ),
- mPos( 0 )
+NeonInputStream::NeonInputStream()
+: m_nLen( 0 ),
+ m_nPos( 0 ),
+ m_bDirty( sal_False )
{
}
@@ -62,24 +69,59 @@ NeonInputStream::~NeonInputStream( void
// -------------------------------------------------------------------
void NeonInputStream::AddToStream( const char * inBuf, sal_Int32 inLen )
{
- mInputBuffer.realloc( sal::static_int_cast(mLen) + inLen );
- rtl_copyMemory( mInputBuffer.getArray() + mLen, inBuf, inLen );
- mLen += inLen;
+ OSL_ENSURE( !m_bDirty, "Cannot AddToStream() when it was already written to it." );
+
+ m_aInputBuffer.realloc( sal::static_int_cast(m_nLen) + inLen );
+ rtl_copyMemory( m_aInputBuffer.getArray() + m_nLen, inBuf, inLen );
+ m_nLen += inLen;
+}
+
+// -------------------------------------------------------------------
+// Associate a URL with this stream
+// -------------------------------------------------------------------
+void NeonInputStream::SetURL( const rtl::OUString &rURL )
+{
+ osl::MutexGuard aGuard( m_aLock );
+
+ m_aURL = rURL;
}
// -------------------------------------------------------------------
// queryInterface
// -------------------------------------------------------------------
-Any NeonInputStream::queryInterface( const Type &type )
- throw( RuntimeException )
+uno::Any NeonInputStream::queryInterface( const uno::Type &type )
+ throw( uno::RuntimeException )
{
- Any aRet = ::cppu::queryInterface( type,
- static_cast< XInputStream * >( this ),
- static_cast< XSeekable * >( this ) );
+ uno::Any aRet = ::cppu::queryInterface( type,
+ static_cast< XStream * >( this ),
+ static_cast< XInputStream * >( this ),
+ static_cast< XOutputStream * >( this ),
+ static_cast< XSeekable * >( this ),
+ static_cast< XTruncate * >( this ) );
return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type );
}
// -------------------------------------------------------------------
+// getInputStream
+// -------------------------------------------------------------------
+com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL
+NeonInputStream::getInputStream( void )
+ throw( com::sun::star::uno::RuntimeException )
+{
+ return uno::Reference< XInputStream >( this );
+}
+
+// -------------------------------------------------------------------
+// getOutputStream
+// -------------------------------------------------------------------
+com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL
+NeonInputStream::getOutputStream( void )
+ throw( com::sun::star::uno::RuntimeException )
+{
+ return uno::Reference< XOutputStream >( this );
+}
+
+// -------------------------------------------------------------------
// readBytes
// "Reads" the specified number of bytes from the stream
// -------------------------------------------------------------------
@@ -92,7 +134,7 @@ sal_Int32 SAL_CALL NeonInputStream::read
{
// Work out how much we're actually going to write
sal_Int32 theBytes2Read = nBytesToRead;
- sal_Int32 theBytesLeft = sal::static_int_cast(mLen - mPos);
+ sal_Int32 theBytesLeft = sal::static_int_cast(m_nLen - m_nPos);
if ( theBytes2Read > theBytesLeft )
theBytes2Read = theBytesLeft;
@@ -101,10 +143,10 @@ sal_Int32 SAL_CALL NeonInputStream::read
// Write the data
rtl_copyMemory(
- aData.getArray(), mInputBuffer.getConstArray() + mPos, theBytes2Read );
+ aData.getArray(), m_aInputBuffer.getConstArray() + m_nPos, theBytes2Read );
// Update our stream position for next time
- mPos += theBytes2Read;
+ m_nPos += theBytes2Read;
return theBytes2Read;
}
@@ -133,9 +175,9 @@ void SAL_CALL NeonInputStream::skipBytes
::com::sun::star::io::IOException,
::com::sun::star::uno::RuntimeException )
{
- mPos += nBytesToSkip;
- if ( mPos >= mLen )
- mPos = mLen;
+ m_nPos += nBytesToSkip;
+ if ( m_nPos >= m_nLen )
+ m_nPos = m_nLen;
}
// -------------------------------------------------------------------
@@ -147,7 +189,7 @@ sal_Int32 SAL_CALL NeonInputStream::avai
::com::sun::star::io::IOException,
::com::sun::star::uno::RuntimeException )
{
- return sal::static_int_cast(mLen - mPos);
+ return sal::static_int_cast(m_nLen - m_nPos);
}
// -------------------------------------------------------------------
@@ -168,12 +210,12 @@ void SAL_CALL NeonInputStream::seek( sal
::com::sun::star::io::IOException,
::com::sun::star::uno::RuntimeException )
{
- if ( location < 0 )
- throw ::com::sun::star::lang::IllegalArgumentException();
+ if ( location < 0 )
+ throw ::com::sun::star::lang::IllegalArgumentException();
- if ( location <= mLen )
- mPos = location;
- else
+ if ( location <= m_nLen )
+ m_nPos = location;
+ else
throw ::com::sun::star::lang::IllegalArgumentException();
}
@@ -184,7 +226,7 @@ sal_Int64 SAL_CALL NeonInputStream::getP
throw( ::com::sun::star::io::IOException,
::com::sun::star::uno::RuntimeException )
{
- return mPos;
+ return m_nPos;
}
// -------------------------------------------------------------------
@@ -194,5 +236,108 @@ sal_Int64 SAL_CALL NeonInputStream::getL
throw( ::com::sun::star::io::IOException,
::com::sun::star::uno::RuntimeException )
{
- return mLen;
+ return m_nLen;
+}
+
+// -------------------------------------------------------------------
+// writeBytes
+// -------------------------------------------------------------------
+void SAL_CALL NeonInputStream::writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData )
+ throw( com::sun::star::io::NotConnectedException,
+ com::sun::star::io::BufferSizeExceededException,
+ com::sun::star::io::IOException,
+ com::sun::star::uno::RuntimeException)
+{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: writeBytes()\n" );
+#endif
+
+ sal_Int32 nDataLen = aData.getLength();
+ OSL_ASSERT( nDataLen >= 0 );
+
+ // Anything to do?
+ if ( nDataLen == 0 )
+ return;
+
+ // Update the length of the stream & size of the buffer
+ if ( m_nLen < m_nPos + nDataLen )
+ {
+ m_nLen = m_nPos + nDataLen;
+ if ( m_aInputBuffer.getLength() < m_nLen )
+ m_aInputBuffer.realloc( sal::static_int_cast( m_nLen ) );
+ }
+
+ rtl_copyMemory( m_aInputBuffer.getArray() + m_nPos, aData.getConstArray(), nDataLen );
+ m_nPos += nDataLen;
+
+ m_bDirty = sal_True;
+}
+
+// -------------------------------------------------------------------
+// flush
+// -------------------------------------------------------------------
+void SAL_CALL NeonInputStream::flush( void )
+ throw( NotConnectedException, BufferSizeExceededException,
+ IOException, uno::RuntimeException )
+{
+ if ( m_bDirty )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: flush(), saving the changed file.\n" );
+#endif
+ // FIXME It's really hacky to create the new session
+ // But so far it seems I have no other chance...
+ uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY );
+ rtl::Reference< DAVSessionFactory > rDAVFactory( new DAVSessionFactory() );
+
+ DAVResourceAccess aResourceAccess( xFactory, rDAVFactory, m_aURL );
+
+ try {
+ aResourceAccess.PUT( reinterpret_cast( m_aInputBuffer.getConstArray() ), m_nLen,
+ DAVResourceAccess::createCommandEnvironment() );
+ }
+ catch ( DAVException & e )
+ {
+ throw ucb::CommandFailedException(
+ e.getData(),
+ uno::Reference< uno::XInterface >(),
+ uno::makeAny( e.getData() ) );
+ }
+
+ m_bDirty = sal_False;
+ }
+}
+
+// -------------------------------------------------------------------
+// closeOutput
+// -------------------------------------------------------------------
+void SAL_CALL NeonInputStream::closeOutput( void )
+ throw( com::sun::star::io::NotConnectedException,
+ com::sun::star::io::IOException,
+ com::sun::star::uno::RuntimeException )
+{
+ if ( m_bDirty )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: TODO write on closeOutput(), the stream is dirty!\n" );
+#endif
+ }
+}
+
+// -------------------------------------------------------------------
+// truncate
+// -------------------------------------------------------------------
+void SAL_CALL NeonInputStream::truncate( void )
+ throw( com::sun::star::io::IOException,
+ com::sun::star::uno::RuntimeException )
+{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: truncate()\n" );
+#endif
+
+ if ( m_nLen > 0 )
+ {
+ m_nLen = m_nPos = 0;
+ m_bDirty = sal_True;
+ }
}
--- ucb/source/ucp/webdav/NeonInputStream.hxx
+++ ucb/source/ucp/webdav/NeonInputStream.hxx
@@ -31,11 +31,19 @@
#define _NEONINPUTSTREAM_HXX_
#include
+#include
+#include
#include
#include
+
+#include
#include
+#include
#include
+#include
+#include
+#include "DAVRequestEnvironment.hxx"
namespace webdav_ucp
{
@@ -45,21 +53,33 @@ namespace webdav_ucp
// A simple XInputStream implementation provided specifically for use
// by the DAVSession::GET method.
// -------------------------------------------------------------------
-class NeonInputStream : public ::com::sun::star::io::XInputStream,
+class NeonInputStream : public ::com::sun::star::io::XStream,
+ public ::com::sun::star::io::XInputStream,
+ public ::com::sun::star::io::XOutputStream,
public ::com::sun::star::io::XSeekable,
+ public ::com::sun::star::io::XTruncate,
public ::cppu::OWeakObject
{
- private:
- com::sun::star::uno::Sequence< sal_Int8 > mInputBuffer;
- sal_Int64 mLen;
- sal_Int64 mPos;
-
- public:
- NeonInputStream( void );
- virtual ~NeonInputStream();
+private:
+ com::sun::star::uno::Sequence< sal_Int8 > m_aInputBuffer;
+ sal_Int64 m_nLen; // cannot be just m_aInputBuffer.getLength() - the buffer can be bigger
+ sal_Int64 m_nPos;
+
+ sal_Bool m_bDirty;
+
+ rtl::OUString m_aURL;
+
+ osl::Mutex m_aLock;
- // Add some data to the end of the stream
- void AddToStream( const char * inBuf, sal_Int32 inLen );
+public:
+ NeonInputStream( void );
+ virtual ~NeonInputStream();
+
+ // Add some data to the end of the stream
+ void AddToStream( const char * inBuf, sal_Int32 inLen );
+
+ // Associate a URL with this stream
+ void SetURL( const rtl::OUString &rURL );
// XInterface
virtual com::sun::star::uno::Any SAL_CALL queryInterface(
@@ -74,6 +94,12 @@ class NeonInputStream : public ::com::su
throw()
{ OWeakObject::release(); }
+ // XStream
+ virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL getInputStream( void )
+ throw( com::sun::star::uno::RuntimeException );
+
+ virtual com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > SAL_CALL getOutputStream( void )
+ throw( com::sun::star::uno::RuntimeException );
// XInputStream
virtual sal_Int32 SAL_CALL readBytes(
@@ -121,6 +147,30 @@ class NeonInputStream : public ::com::su
virtual sal_Int64 SAL_CALL getLength()
throw( ::com::sun::star::io::IOException,
::com::sun::star::uno::RuntimeException );
+
+ // XOutputStream
+ virtual void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< sal_Int8 >& aData )
+ throw( com::sun::star::io::NotConnectedException,
+ com::sun::star::io::BufferSizeExceededException,
+ com::sun::star::io::IOException,
+ com::sun::star::uno::RuntimeException);
+
+ virtual void SAL_CALL flush( void )
+ throw( com::sun::star::io::NotConnectedException,
+ com::sun::star::io::BufferSizeExceededException,
+ com::sun::star::io::IOException,
+ com::sun::star::uno::RuntimeException);
+
+
+ virtual void SAL_CALL closeOutput( void )
+ throw( com::sun::star::io::NotConnectedException,
+ com::sun::star::io::IOException,
+ com::sun::star::uno::RuntimeException );
+
+ // XTruncate
+ virtual void SAL_CALL truncate( void )
+ throw( com::sun::star::io::IOException,
+ com::sun::star::uno::RuntimeException );
};
} // namespace webdav_ucp
--- ucb/source/ucp/webdav/NeonSession.cxx
+++ ucb/source/ucp/webdav/NeonSession.cxx
@@ -65,6 +65,7 @@
#ifndef _SIMPLECERTIFICATIONVALIDATIONREQUEST_HXX_
#include "ucbhelper/simplecertificatevalidationrequest.hxx"
#endif
+#include
#include
@@ -153,6 +154,12 @@ static sal_uInt16 makeStatusCode( const
return sal_uInt16( rStatusText.copy( 0, nPos ).toInt32() );
}
+static sal_uInt16 getStatusCode( HttpSession *pSession )
+{
+ rtl::OUString aText = rtl::OUString::createFromAscii( ne_get_error( pSession ) );
+ return makeStatusCode( aText );
+}
+
// -------------------------------------------------------------------
struct NeonRequestContext
{
@@ -196,12 +203,13 @@ struct NeonRequestContext
// -------------------------------------------------------------------
#if NEON_VERSION >= 0x0250
-extern "C" int NeonSession_ResponseBlockReader(void * inUserData,
+extern "C" int
#else
-extern "C" void NeonSession_ResponseBlockReader(void * inUserData,
+extern "C" void
#endif
- const char * inBuf,
- size_t inLen )
+NeonSession_ResponseBlockReader( void * inUserData,
+ const char * inBuf,
+ size_t inLen )
{
// neon calls this function with (inLen == 0)...
if ( inLen > 0 )
@@ -226,12 +234,13 @@ extern "C" void NeonSession_ResponseBloc
// -------------------------------------------------------------------
#if NEON_VERSION >= 0x0250
-extern "C" int NeonSession_ResponseBlockWriter( void * inUserData,
+extern "C" int
#else
-extern "C" void NeonSession_ResponseBlockWriter( void * inUserData,
+extern "C" void
#endif
- const char * inBuf,
- size_t inLen )
+NeonSession_ResponseBlockWriter( void * inUserData,
+ const char * inBuf,
+ size_t inLen )
{
// neon calls this function with (inLen == 0)...
if ( inLen > 0 )
@@ -299,11 +308,10 @@ extern "C" int NeonSession_NeonAuth( voi
try
{
- NeonUri uri( theSession->getRequestEnvironment().m_aRequestURI );
- rtl::OUString aUserInfo( uri.GetUserInfo() );
+ rtl::OUString aUserInfo( theSession->getUserInfo() );
if ( aUserInfo.getLength() )
{
- sal_Int32 nPos = aUserInfo.indexOf( '@' );
+ sal_Int32 nPos = aUserInfo.indexOf( ':' );
if ( nPos == -1 )
{
theUserName = aUserInfo;
@@ -564,6 +572,8 @@ extern "C" void NeonSession_PreSendReque
}
}
+NeonLockStore * NeonSession::s_aNeonLockStore = NULL;
+
// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
@@ -581,6 +591,7 @@ NeonSession::NeonSession(
m_aScheme = theUri.GetScheme();
m_aHostName = theUri.GetHost();
m_nPort = theUri.GetPort();
+ m_aUserInfo = theUri.GetUserInfo();
// Init();
}
@@ -594,14 +605,6 @@ NeonSession::~NeonSession( )
{
ne_session_destroy( m_pHttpSession );
m_pHttpSession = 0;
- // Note: Uncomment the following if locking support is required
- /*
- if ( mNeonLockSession != NULL )
- {
- ne_lock_unregister( mNeonLockSession );
- mNeonLockSession = NULL;
- }
- */
}
delete static_cast(m_pRequestData);
@@ -629,6 +632,9 @@ void NeonSession::Init()
throw DAVException( DAVException::DAV_SESSION_CREATE,
NeonUri::makeConnectionEndPointString(
m_aHostName, m_nPort ) );
+#if OSL_DEBUG_LEVEL > 0
+ ne_debug_init( stderr, NE_DBG_LOCKS );
+#endif
// #122205# - libxml2 needs to be initialized once if used by
// multithreaded programs like OOo.
xmlInitParser();
@@ -746,14 +752,15 @@ void NeonSession::Init()
m_nProxyPort );
}
- // Note: Uncomment the following if locking support is required
- /*
- mNeonLockSession = ne_lock_register( m_pHttpSession );
+ if ( !s_aNeonLockStore )
+ s_aNeonLockStore = ne_lockstore_create();
- if ( mNeonLockSession == NULL )
+ if ( s_aNeonLockStore == NULL )
throw DAVException( DAVException::DAV_SESSION_CREATE,
- theUri::makeConnectionEndPointString() );
- */
+ NeonUri::makeConnectionEndPointString( m_aHostName, m_nPort ) );
+
+ // Register the lock store
+ ne_lockstore_register( s_aNeonLockStore, m_pHttpSession );
// Register for redirects.
ne_redirect_register( m_pHttpSession );
@@ -1088,11 +1095,12 @@ void NeonSession::GET( const rtl::OUStri
// -------------------------------------------------------------------
// GET
// -------------------------------------------------------------------
-uno::Reference< io::XInputStream >
+uno::Reference< io::XStream >
NeonSession::GET( const rtl::OUString & inPath,
const std::vector< ::rtl::OUString > & inHeaderNames,
DAVResource & ioResource,
- const DAVRequestEnvironment & rEnv )
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool bAllowEmpty )
throw ( DAVException )
{
osl::Guard< osl::Mutex > theGuard( m_aMutex );
@@ -1104,16 +1112,23 @@ NeonSession::GET( const rtl::OUString &
ioResource.uri = inPath;
ioResource.properties.clear();
- rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
- NeonRequestContext aCtx( xInputStream, inHeaderNames, ioResource );
+ rtl::Reference< NeonInputStream > xStream( new NeonInputStream );
+ NeonRequestContext aCtx( xStream, inHeaderNames, ioResource );
int theRetVal = GET( m_pHttpSession,
rtl::OUStringToOString(
inPath, RTL_TEXTENCODING_UTF8 ),
NeonSession_ResponseBlockReader,
true,
&aCtx );
- HandleError( theRetVal );
- return uno::Reference< io::XInputStream >( xInputStream.get() );
+ try {
+ HandleError( theRetVal );
+ }
+ catch ( DAVException const & e )
+ {
+ if ( !bAllowEmpty || ( e.getStatus() != SC_NOT_FOUND ) )
+ throw;
+ }
+ return uno::Reference< io::XStream >( xStream.get() );
}
// -------------------------------------------------------------------
@@ -1153,22 +1168,38 @@ void NeonSession::PUT( const rtl::OUStri
const DAVRequestEnvironment & rEnv )
throw ( DAVException )
{
+ // initialization etc. is performed in the other PUT
+
+ uno::Sequence< sal_Int8 > aDataToSend;
+ if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ PUT( inPath,
+ reinterpret_cast< const char * >( aDataToSend.getConstArray() ),
+ aDataToSend.getLength(),
+ rEnv );
+}
+
+// -------------------------------------------------------------------
+// PUT
+// -------------------------------------------------------------------
+void NeonSession::PUT( const rtl::OUString &inPath,
+ const char * buffer,
+ size_t size,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
osl::Guard< osl::Mutex > theGuard( m_aMutex );
Init();
m_aEnv = rEnv;
- uno::Sequence< sal_Int8 > aDataToSend;
- if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) )
- throw DAVException( DAVException::DAV_INVALID_ARG );
-
int theRetVal = PUT( m_pHttpSession,
rtl::OUStringToOString(
inPath, RTL_TEXTENCODING_UTF8 ),
- reinterpret_cast< const char * >(
- aDataToSend.getConstArray() ),
- aDataToSend.getLength() );
+ buffer,
+ size );
HandleError( theRetVal );
}
@@ -1344,9 +1375,7 @@ void NeonSession::DESTROY( const rtl::OU
// -------------------------------------------------------------------
// LOCK
// -------------------------------------------------------------------
-// Note: Uncomment the following if locking support is required
-/*
-void NeonSession::LOCK( const Lock & inLock,
+void NeonSession::LOCK( ucb::Lock & rLock,
const DAVRequestEnvironment & rEnv )
throw ( DAVException )
{
@@ -1356,16 +1385,13 @@ void NeonSession::LOCK( const Lock & inL
m_aEnv = rEnv;
- Lockit( inLock, true );
+ Lockit( rLock, true );
}
-*/
// -------------------------------------------------------------------
// UNLOCK
// -------------------------------------------------------------------
-// Note: Uncomment the following if locking support is required
-/*
-void NeonSession::UNLOCK( const Lock & inLock,
+void NeonSession::UNLOCK( ucb::Lock & rLock,
const DAVRequestEnvironment & rEnv )
throw ( DAVException )
{
@@ -1375,9 +1401,8 @@ void NeonSession::UNLOCK( const Lock & i
m_aEnv = rEnv;
- Lockit( inLock, false );
+ Lockit( rLock, false );
}
-*/
// -------------------------------------------------------------------
const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const
@@ -1416,7 +1441,10 @@ void NeonSession::HandleError( int nErro
case NE_ERROR: // Generic error
{
rtl::OUString aText = rtl::OUString::createFromAscii(
- ne_get_error( m_pHttpSession ) );
+ ne_get_error( m_pHttpSession ) );
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: got error '%s'\n", rtl::OUStringToOString( aText, RTL_TEXTENCODING_UTF8 ).getStr() );
+#endif
throw DAVException( DAVException::DAV_HTTP_ERROR,
aText,
makeStatusCode( aText ) );
@@ -1473,77 +1501,156 @@ void NeonSession::HandleError( int nErro
}
}
-// Note: Uncomment the following if locking support is required
-/*
-void NeonSession::Lockit( const Lock & inLock, bool inLockit )
+void NeonSession::Lockit( ucb::Lock & rLock, bool bLockit )
throw ( DAVException )
{
osl::Guard< osl::Mutex > theGuard( m_aMutex );
- // Create the neon lock
- NeonLock * theLock = new NeonLock;
- int theRetVal;
-
- // Set the lock uri
- NeonUri theUri( inLock.uri );
- theLock->uri = const_cast< char * >
- ( rtl::OUStringToOString(
- theUri.GetPath(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ if ( !s_aNeonLockStore )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
- if ( inLockit )
- {
- // Set the lock depth
- switch( inLock.depth )
- {
- case DAVZERO:
- case DAVINFINITY:
- theLock->depth = int ( inLock.depth );
- break;
- default:
- throw DAVException( DAVException::DAV_INVALID_ARG );
- break;
- }
+ ne_uri aUri;
+ ne_uri_parse( rtl::OUStringToOString( m_aEnv.m_aRequestURI, RTL_TEXTENCODING_UTF8 ).getStr(),
+ &aUri );
+
+#if NEON_VERSION < 0x0260
+#define FILLIN( field, val ) aUri.field = aUri.field? aUri.field: strdup( rtl::OUStringToOString( val, RTL_TEXTENCODING_UTF8 ).getStr() )
+ FILLIN( scheme, m_aScheme );
+ FILLIN( host, m_aHostName );
+ aUri.port = aUri.port? aUri.port: m_nPort;
+#undef FILLIN
+#endif
- // Set the lock scope
- switch ( inLock.scope )
- {
- case EXCLUSIVE:
- theLock->scope = ne_lockscope_exclusive;
- break;
- case SHARED:
- theLock->scope = ne_lockscope_shared;
- break;
- default:
- throw DAVException( DAVException::DAV_INVALID_ARG );
- break;
- }
+ // Create the neon lock
+ NeonLock * theLock = ne_lockstore_findbyuri( s_aNeonLockStore, &aUri );
+ bool bAlreadyExists = false;
+ if ( theLock )
+ bAlreadyExists = true;
+ else
+ {
+ theLock = ne_lock_create();
- // Set the lock owner
- const char * theOwner = rtl::OUStringToOString( inLock.owner,
- RTL_TEXTENCODING_UTF8 );
- theLock->owner = const_cast< char * > ( theOwner );
-
- // Set the lock timeout
- // Note: Neon ignores the timeout
- //theLock->timeout = inLock.timeout;
+ // Set the lock uri
+ theLock->uri = aUri;
- theRetVal = ne_lock( m_pHttpSession, theLock );
- }
- else
- {
+ // 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 token
- rtl::OUString theToken = inLock.locktoken.getConstArray()[ 0 ];
- theLock->token = const_cast< char * >
- ( rtl::OUStringToOString(
- theToken, RTL_TEXTENCODING_UTF8 ).getStr() );
+ // 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 );
+ break;
+ }
- theRetVal = ne_unlock( m_pHttpSession, theLock );
- }
+ // Set the lock owner
+ rtl::OUString aValue;
+ rLock.Owner >>= aValue;
- HandleError( theRetVal );
+ theLock->owner = strdup( rtl::OUStringToOString( aValue, RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ // Set the lock timeout
+ // We re-new the lock while the stream is open
+ theLock->timeout = rLock.Timeout;
+ }
+
+ if ( bLockit )
+ {
+ int nRet;
+ if ( bAlreadyExists )
+ {
+#if NEON_VERSION >= 0x0260
+ nRet = ne_lock_refresh( m_pHttpSession, theLock );
+#else
+ // workaround for a bug in neon 0.24
+ // we have to call with a bigger structure that is used internally
+ // and initialize parts of it
+
+ struct lock_ctx
+ {
+ struct ne_lock active; /* activelock */
+ char *token; /* the token we're after. */
+ int found;
+ ne_buffer *cdata;
+ };
+
+ struct lock_ctx ctx;
+
+ memset( &ctx, 0, sizeof ctx );
+ ctx.cdata = ne_buffer_create();
+
+ memcpy( &ctx, theLock, sizeof( *theLock ) );
+ nRet = ne_lock_refresh( m_pHttpSession, reinterpret_cast( &ctx ) );
+
+ ne_buffer_destroy( ctx.cdata );
+#endif
+ if ( ( nRet == NE_ERROR ) && strncmp (ne_get_error (m_pHttpSession), "No activelock ", strlen ("No activelock ")) == 0 )
+ {
+ bAlreadyExists = false;
+ ne_lockstore_remove( s_aNeonLockStore, theLock );
+ }
+ }
+ if ( !bAlreadyExists )
+ {
+ nRet = ne_lock( m_pHttpSession, theLock );
+
+ if ( nRet == NE_OK )
+ {
+ ne_lockstore_add( s_aNeonLockStore, theLock );
+
+ uno::Sequence< rtl::OUString > aTokens( 1 );
+ aTokens[0] = rtl::OUString::createFromAscii( theLock->token );
+ rLock.LockTokens = aTokens;
+
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: locked the URL, the token is: %s\n", theLock->token );
+#endif
+ }
+ }
+
+ if ( ( nRet == NE_ERROR ) && getStatusCode( m_pHttpSession ) == SC_LOCKED )
+ {
+ ucbhelper::cancelCommandExecution( ucb::IOErrorCode_LOCKING_VIOLATION,
+ uno::Sequence< uno::Any >( 0 ), // FIXME more info about the file?
+ m_aEnv.m_xEnv,
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "a locking error occured" ) ),
+ uno::Reference< ucb::XCommandProcessor >() );
+ }
+#if OSL_DEBUG_LEVEL > 0
+ else if ( nRet == NE_OK )
+ fprintf( stderr, "WebDAV: locked/refreshed lock OK\n" );
+ else
+ fprintf( stderr, "WebDAV: failed to lock the file: %s\n", ne_get_error( m_pHttpSession ) );
+#endif
+ }
+ else
+ {
+ // Set the lock token
+ if ( rLock.LockTokens.getLength() > 0 )
+ {
+ rtl::OUString theToken = rLock.LockTokens.getConstArray()[ 0 ];
+ theLock->token = strdup( rtl::OUStringToOString( theToken, RTL_TEXTENCODING_UTF8 ).getStr() );
+
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: going to unlock the URL, the token is: %s\n", theLock->token );
+#endif
+
+ ne_unlock( m_pHttpSession, theLock );
+ ne_lockstore_remove( s_aNeonLockStore, theLock );
+ // FIXME even ne_lock_destroy( theLock )?
+ }
+ }
}
-*/
// -------------------------------------------------------------------
namespace {
--- ucb/source/ucp/webdav/NeonSession.hxx
+++ ucb/source/ucp/webdav/NeonSession.hxx
@@ -57,6 +57,7 @@ class NeonSession : public DAVSession
rtl::OUString m_aScheme;
rtl::OUString m_aHostName;
rtl::OUString m_aProxyName;
+ rtl::OUString m_aUserInfo;
sal_Int32 m_nPort;
sal_Int32 m_nProxyPort;
HttpSession * m_pHttpSession;
@@ -70,8 +71,7 @@ class NeonSession : public DAVSession
// moment.
DAVRequestEnvironment m_aEnv;
- // Note: Uncomment the following if locking support is required
- // NeonLockSession * mNeonLockSession;
+ static NeonLockStore *s_aNeonLockStore;
static bool m_bGlobalsInited;
@@ -92,6 +92,8 @@ class NeonSession : public DAVSession
const DAVRequestEnvironment & getRequestEnvironment() const
{ return m_aEnv; }
+ const rtl::OUString & getUserInfo() const { return m_aUserInfo; }
+
virtual void
OPTIONS( const ::rtl::OUString & inPath,
DAVCapabilities & outCapabilities,
@@ -142,11 +144,12 @@ class NeonSession : public DAVSession
throw ( DAVException );
virtual com::sun::star::uno::Reference<
- com::sun::star::io::XInputStream >
+ com::sun::star::io::XStream >
GET( const ::rtl::OUString & inPath,
const std::vector< ::rtl::OUString > & inHeaderNames,
DAVResource & ioResource,
- const DAVRequestEnvironment & rEnv )
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool bAllowEmpty = sal_False )
throw ( DAVException );
virtual void
@@ -165,6 +168,13 @@ class NeonSession : public DAVSession
const DAVRequestEnvironment & rEnv )
throw ( DAVException );
+ virtual void
+ PUT( const ::rtl::OUString & inPath,
+ const char * buffer,
+ size_t size,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
virtual com::sun::star::uno::Reference<
com::sun::star::io::XInputStream >
POST( const rtl::OUString & inPath,
@@ -209,16 +219,13 @@ class NeonSession : public DAVSession
virtual void ABORT()
throw ( DAVException );
- // Note: Uncomment the following if locking support is required
- /*
- virtual void LOCK (const Lock & inLock,
- const DAVRequestEnvironment & rEnv )
+ virtual void LOCK ( com::sun::star::ucb::Lock & rLock,
+ const DAVRequestEnvironment & rEnv )
throw ( DAVException );
- virtual void UNLOCK (const Lock & inLock,
- const DAVRequestEnvironment & rEnv )
+ virtual void UNLOCK ( com::sun::star::ucb::Lock & rLock,
+ const DAVRequestEnvironment & rEnv )
throw ( DAVException );
- */
// helpers
const rtl::OUString & getHostName() const { return m_aHostName; }
@@ -239,9 +246,8 @@ class NeonSession : public DAVSession
const ucbhelper::InternetProxyServer & getProxySettings() const;
- // Note: Uncomment the following if locking support is required
- // void Lockit( const Lock & inLock, bool inLockit )
- // throw ( DAVException );
+ void Lockit( com::sun::star::ucb::Lock & rLock, bool bLockit )
+ throw ( DAVException );
// low level GET implementation, used by public GET implementations
static int GET( ne_session * sess,
--- ucb/source/ucp/webdav/NeonTypes.hxx
+++ ucb/source/ucp/webdav/NeonTypes.hxx
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
typedef ne_session HttpSession;
typedef ne_status HttpStatus;
@@ -43,4 +44,7 @@ typedef ne_server_capabilities Http
typedef ne_propname NeonPropName;
typedef ne_prop_result_set NeonPropFindResultSet;
+typedef ne_lock_store NeonLockStore;
+typedef struct ne_lock NeonLock;
+
#endif // _NEONTYPES_HXX_
--- ucb/source/ucp/webdav/webdavcontent.cxx
+++ ucb/source/ucp/webdav/webdavcontent.cxx
@@ -37,6 +37,7 @@
*************************************************************************/
#include
+#include
#include "osl/doublecheckedlocking.h"
#include
@@ -48,20 +49,17 @@
#include
#include
#include
+#include
#include
#include
#include "com/sun/star/ucb/AuthenticationRequest.hpp"
#include
#include
#include
-#ifndef _COM_SUN_STAR_UCB_INTERACTIVEBADTRANSFRERURLEXCEPTION_HPP_
#include
-#endif
#include
#include
-#ifndef _COM_SUN_STAR_UCB_INTERACTIVENETWORKGENBERALEXCEPTION_HPP_
#include
-#endif
#include
#include
#include
@@ -90,6 +88,8 @@
#include "NeonUri.hxx"
#include "UCBDeadPropertyValue.hxx"
+#include "NeonInputStream.hxx"
+
using namespace com::sun::star;
using namespace webdav_ucp;
@@ -345,6 +345,123 @@ void SAL_CALL CommandEnvironment_Impl::h
//=========================================================================
//=========================================================================
+// Our signal - 246 is just a random number ;-)
+#define TICKER_THREAD_USER_SIGNAL ( OSL_SIGNAL_USER_RESERVED + 246 )
+
+// -------------------------------------------------------------------
+// A thread that 'ticks' - emits the user signal every second
+// -------------------------------------------------------------------
+class TickerThread : public osl::Thread
+{
+ bool m_bFinish;
+
+public:
+
+ TickerThread() : osl::Thread(), m_bFinish( false ) {}
+
+ void finish() { m_bFinish = true; }
+
+protected:
+
+ virtual void SAL_CALL run();
+};
+
+void TickerThread::run()
+{
+ // we have to go through the loop more often to be able to finish ~quickly
+ const int nNth = 25;
+
+ int nCount = nNth;
+ while ( !m_bFinish )
+ {
+ if ( nCount-- <= 0 )
+ {
+ osl_raiseSignal( TICKER_THREAD_USER_SIGNAL, NULL );
+ nCount = nNth;
+ }
+
+ TimeValue aTV;
+ aTV.Seconds = 0;
+ aTV.Nanosec = 1000000000/nNth;
+ wait( aTV );
+ }
+}
+
+// -------------------------------------------------------------------
+// A class that takes care of creating and destroying the ticker thread
+// -------------------------------------------------------------------
+class TickerThreadController
+{
+ osl::Mutex m_aMutex;
+ int m_nCount;
+ TickerThread *m_pTickerThread;
+
+public:
+
+ TickerThreadController() : m_nCount( 0 ), m_pTickerThread( NULL ) {}
+
+ void start();
+ void stop();
+};
+
+void TickerThreadController::start()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( ( m_nCount++ == 0 ) && !m_pTickerThread )
+ {
+ m_pTickerThread = new TickerThread();
+ m_pTickerThread->create();
+ }
+}
+
+void TickerThreadController::stop()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( ( --m_nCount == 0 ) && m_pTickerThread )
+ {
+ m_pTickerThread->finish();
+ m_pTickerThread->join();
+
+ delete m_pTickerThread;
+ m_pTickerThread = NULL;
+ }
+}
+
+// -------------------------------------------------------------------
+// Signal handler
+// -------------------------------------------------------------------
+oslSignalAction Content::HandleLockingSignal( void* pData, oslSignalInfo* pSignalInfo )
+{
+ Content *pContent = static_cast< Content *>( pData );
+
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "Content::HandleLockingSignal: pContent=%p pSignalInfo=%p\n", pContent, pSignalInfo );
+#endif
+
+ if ( !pContent )
+ return osl_Signal_ActCallNextHdl;
+
+ if ( pSignalInfo &&
+ pSignalInfo->Signal == osl_Signal_User &&
+ pSignalInfo->UserSignal == TICKER_THREAD_USER_SIGNAL )
+ {
+ pContent->RefreshLock();
+ }
+ else if ( !pSignalInfo || ( pSignalInfo->Signal != osl_Signal_User ) )
+ {
+ // terminating or something
+ pContent->m_xResAccess->UNLOCK( *pContent->m_pLock, pContent->m_xLockEnv );
+ delete pContent->m_pLock;
+ pContent->m_pLock = NULL;
+ }
+
+ return osl_Signal_ActCallNextHdl;
+}
+
+static TickerThreadController sTickerThreadController;
+
//=========================================================================
// ctr for content on an existing webdav resource
Content::Content(
@@ -358,7 +475,11 @@ Content::Content(
m_pProvider( pProvider ),
m_bTransient( false ),
m_bCollection( false ),
- m_bDidGetOrHead( false )
+ m_bDidGetOrHead( false ),
+ m_bForceReadOnly( false ),
+ m_pLock( NULL ),
+ m_nToExpire( -1 ),
+ m_pSignalHandler( NULL )
{
try
{
@@ -369,6 +490,14 @@ Content::Content(
NeonUri aURI( Identifier->getContentIdentifier() );
m_aEscapedTitle = aURI.GetPathBaseName();
+
+ m_pSignalHandler = osl_addSignalHandler( HandleLockingSignal, this );
+
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "Content::Content (existing resource): this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler );
+ fprintf( stderr, " identifier=%s\n", rtl::OUStringToOString( Identifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8 ).getStr() );
+#endif
+ sTickerThreadController.start();
}
catch ( DAVException const & )
{
@@ -390,12 +518,24 @@ Content::Content(
m_pProvider( pProvider ),
m_bTransient( true ),
m_bCollection( isCollection ),
- m_bDidGetOrHead( false )
+ m_bDidGetOrHead( false ),
+ m_bForceReadOnly( false ),
+ m_pLock( NULL ),
+ m_nToExpire( -1 ),
+ m_pSignalHandler( NULL )
{
try
{
m_xResAccess.reset( new DAVResourceAccess(
rxSMgr, rSessionFactory, Identifier->getContentIdentifier() ) );
+
+ m_pSignalHandler = osl_addSignalHandler( HandleLockingSignal, this );
+
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "Content::Content (nonexistent resource): this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler );
+ fprintf( stderr, " identifier=%s\n", rtl::OUStringToOString( Identifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8 ).getStr() );
+#endif
+ sTickerThreadController.start();
}
catch ( DAVException const & )
{
@@ -409,6 +548,47 @@ Content::Content(
// virtual
Content::~Content()
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "Content::~Content: this=%p m_pSignalHandler=%p\n", this, m_pSignalHandler );
+#endif
+ sTickerThreadController.stop();
+
+ osl_removeSignalHandler( m_pSignalHandler );
+
+ if (m_pLock != NULL)
+ {
+ try {
+ m_xResAccess->UNLOCK( *m_pLock, m_xLockEnv );
+ delete m_pLock;
+ m_pLock = NULL;
+ }
+ catch ( ucb::CommandFailedException const & )
+ {
+ }
+ }
+}
+
+// -------------------------------------------------------------------
+// Lock the resource again
+// -------------------------------------------------------------------
+void Content::RefreshLock( void )
+{
+ osl::MutexGuard aGuard( m_aLock );
+
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "Content::RefreshLock(): m_nToExpire=%d m_pLock=%p\n", m_nToExpire, m_pLock);
+#endif
+
+ if ( m_nToExpire > 0 )
+ --m_nToExpire;
+
+ // Refresh the lock if it expires in less than 30 s
+ if ( m_pLock && m_nToExpire >= 0 && m_nToExpire < 30 )
+ {
+ m_xResAccess->LOCK( *m_pLock, m_xLockEnv );
+
+ m_nToExpire = m_pLock->Timeout;
+ }
}
//=========================================================================
@@ -630,6 +811,11 @@ uno::Any SAL_CALL Content::execute(
ucb::CommandAbortedException,
uno::RuntimeException )
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: Content::execute(): this=%p command=%s\n",
+ this, rtl::OUStringToOString( aCommand.Name, RTL_TEXTENCODING_UTF8 ).getStr() );
+#endif
+
uno::Any aRet;
if ( aCommand.Name.equalsAsciiL(
@@ -1000,6 +1000,11 @@
if ( !Name.getLength() )
throw lang::IllegalArgumentException();
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: Content::addProperty(): this=%p property=%s\n",
+ this, rtl::OUStringToOString( Name, RTL_TEXTENCODING_UTF8 ).getStr() );
+#endif
+
// Check property type.
if ( !UCBDeadPropertyValue::supportsType( DefaultValue.getValueType() ) )
{
@@ -1100,6 +1100,11 @@
// Try to remove property from server.
//////////////////////////////////////////////////////////////////////
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: Content::removeProperty(): this=%p property=%s\n",
+ this, rtl::OUStringToOString( Name, RTL_TEXTENCODING_UTF8 ).getStr() );
+#endif
+
try
{
std::vector< ProppatchValue > aProppatchValues;
@@ -1349,6 +1535,31 @@ uno::Reference< sdbc::XRow > Content::ge
uno::Reference< ucb::XContentIdentifier > xIdentifier;
rtl::Reference< ::ucbhelper::ContentProviderImplHelper > xProvider;
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: Content::getPropertyValues(): answering the following properties: " );
+ for ( int i = 0; i < rProperties.getLength(); ++i )
+ fprintf( stderr, " %s,",
+ rtl::OUStringToOString( rProperties[i].Name, RTL_TEXTENCODING_UTF8 ).getStr() );
+ fprintf( stderr, "\n" );
+#endif
+
+ // WebDAV supports XActiveDataStreamer
+ // We have to return TRUE on
+ // - SupportsActiveStreaming - always
+ // - IsReadOnly - if we forced read only due to failed locking
+ if ( rProperties.getLength() == 1 )
+ {
+ if ( rProperties[ 0 ].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SupportsActiveStreaming" ) ) ||
+ ( rProperties[ 0 ].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) && m_bForceReadOnly ) )
+ {
+ rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
+ = new ::ucbhelper::PropertyValueSet( m_xSMgr );
+ xRow->appendBoolean( rProperties[0], sal_True );
+
+ return uno::Reference< sdbc::XRow >( xRow.get() );
+ }
+ }
+
{
osl::Guard< osl::Mutex > aGuard( m_aMutex );
@@ -1475,8 +1686,13 @@ uno::Reference< sdbc::XRow > Content::ge
if ( !bNetworkAccessAllowed )
{
- cancelCommandExecution( e, xEnv );
- // unreachable
+ if ( e.getStatus() == SC_NOT_FOUND )
+ xProps.reset();
+ else
+ {
+ cancelCommandExecution( e, xEnv );
+ // unreachable
+ }
}
}
}
@@ -2000,6 +2000,10 @@
{
uno::Any aRet;
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: Content::open() this=%p\n", this );
+#endif
+
sal_Bool bOpenFolder = ( ( rArg.Mode == ucb::OpenMode::ALL ) ||
( rArg.Mode == ucb::OpenMode::FOLDERS ) ||
( rArg.Mode == ucb::OpenMode::DOCUMENTS ) );
@@ -2092,13 +2308,17 @@ uno::Any Content::open(
}
}
- if ( rArg.Sink.is() )
- {
- // Open document.
+ if ( !rArg.Sink.is() )
+ return aRet;
+
+ // Open document.
if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: rArg.Mode currently(?) unsupported\n" );
+#endif
// Currently(?) unsupported.
ucbhelper::cancelCommandExecution(
uno::makeAny(
@@ -2115,6 +2332,9 @@ uno::Any Content::open(
= uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY );
if ( xOut.is() )
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: rArg.Sink is XOutputStream\n" );
+#endif
// PUSH: write data
try
{
@@ -2159,6 +2379,60 @@ uno::Any Content::open(
uno::UNO_QUERY );
if ( xDataSink.is() )
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataSink\n" );
+#endif
+ // PULL: wait for client read
+ try
+ {
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+
+ // throw away previously cached headers.
+ m_xCachedProps.reset();
+ }
+ // fill inputsream sync; return if all data present
+ DAVResource aResource;
+ std::vector< rtl::OUString > aHeaders;
+ // // Obtain list containing all HTTP headers that can
+ // // be mapped to UCB properties.
+ // ContentProperties::getMappableHTTPHeaders( aHeaders );
+ uno::Reference< io::XInputStream > xIn
+ = m_xResAccess->GET( aHeaders, aResource, xEnv )->getInputStream();
+
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+
+ m_xCachedProps.reset(
+ new ContentProperties( aResource ) );
+ }
+
+ xDataSink->setInputStream( xIn );
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, xEnv );
+ // Unreachable
+ }
+ }
+ else
+ {
+ uno::Reference< io::XActiveDataStreamer > xDataStreamer
+ = uno::Reference< io::XActiveDataStreamer >( rArg.Sink,
+ uno::UNO_QUERY );
+ if ( xDataStreamer.is() && !m_bForceReadOnly )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataStreamer\n" );
+#endif
+ // prepare the lock
+ m_pLock = new ucb::Lock;
+ m_pLock->Depth = ucb::LockDepth_ZERO;
+ m_pLock->Scope = ucb::LockScope_EXCLUSIVE;
+ m_pLock->Timeout = 2*60; // 2 minutes
+
+ m_nToExpire = m_pLock->Timeout;
+
// PULL: wait for client read
try
{
@@ -2174,9 +2448,31 @@ uno::Any Content::open(
DAVResource aResource;
std::vector< rtl::OUString > aHeaders;
- uno::Reference< io::XInputStream > xIn
- = xResAccess->GET( aHeaders, aResource, xEnv );
+ try {
+ m_xResAccess->LOCK( *m_pLock, xEnv );
+ m_xLockEnv = xEnv;
+ }
+ catch ( ucb::CommandFailedException const &e )
+ {
+ // stream locked?
+ ucb::InteractiveIOException aIoException;
+ if ( ( e.Reason >>= aIoException ) && ( aIoException.Code == ucb::IOErrorCode_LOCKING_VIOLATION ) )
+ {
+ delete m_pLock;
+ m_pLock = NULL;
+ // yes => we must be read only at the next try
+ m_bForceReadOnly = sal_True;
+ }
+
+ throw;
+ }
+
+ uno::Reference< io::XStream > xStream
+ = xResAccess->GET( aHeaders, aResource, xEnv, sal_True );
m_bDidGetOrHead = true;
+
+ // pass the URL to the stream
+ static_cast< NeonInputStream* >( xStream.get() )->SetURL( m_xResAccess->getURL() );
{
osl::MutexGuard aGuard( m_aMutex );
@@ -2191,16 +2487,24 @@ uno::Any Content::open(
new DAVResourceAccess( *xResAccess.get() ) );
}
- xDataSink->setInputStream( xIn );
+ xDataStreamer->setStream( xStream );
}
catch ( DAVException const & e )
{
+ m_xResAccess->UNLOCK( *m_pLock, xEnv );
+ delete m_pLock;
+ m_pLock = NULL;
+ m_bForceReadOnly = sal_False;
+
cancelCommandExecution( e, xEnv );
// Unreachable
}
}
else
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: unsupported rArg.Sink\n" );
+#endif
// Note: aOpenCommand.Sink may contain an XStream
// implementation. Support for this type of
// sink is optional...
@@ -2228,9 +2532,16 @@ void Content::post(
const uno::Reference< ucb::XCommandEnvironment > & xEnv )
throw( uno::Exception )
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: Content::post() this=%p\n", this );
+#endif
+
uno::Reference< io::XActiveDataSink > xSink( rArg.Sink, uno::UNO_QUERY );
if ( xSink.is() )
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataSink\n" );
+#endif
try
{
std::auto_ptr< DAVResourceAccess > xResAccess;
@@ -2262,6 +2569,9 @@ void Content::post(
uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY );
if ( xResult.is() )
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: rArg.Sink is XOutputStream\n" );
+#endif
try
{
std::auto_ptr< DAVResourceAccess > xResAccess;
@@ -2291,6 +2601,9 @@ void Content::post(
}
else
{
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: rArg.Sink is XActiveDataStreamer (or something)\n" );
+#endif
ucbhelper::cancelCommandExecution(
uno::makeAny(
ucb::UnsupportedDataSinkException(
@@ -2600,6 +2600,10 @@
rtl::OUString aEscapedTitle;
std::auto_ptr< DAVResourceAccess > xResAccess;
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "WebDAV: Content::insert() this=%p\n", this );
+#endif
+
{
osl::Guard< osl::Mutex > aGuard( m_aMutex );
@@ -2643,11 +2956,23 @@ void Content::transfer(
rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
}
else if ( aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAV_URL_SCHEME ) ) )
+ {
+ sourceURI.SetScheme(
+ rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
+ }
+ else if ( aScheme.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) )
{
sourceURI.SetScheme(
rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) );
}
+ else if ( aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAVS_URL_SCHEME ) ) )
+ {
+ sourceURI.SetScheme(
+ rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) );
+ }
else
{
if ( !aScheme.equalsAsciiL(
@@ -2674,6 +2999,18 @@ void Content::transfer(
RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) )
targetURI.SetScheme(
rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
+ else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAV_URL_SCHEME ) ) )
+ targetURI.SetScheme(
+ rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
+ else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) )
+ targetURI.SetScheme(
+ rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) );
+ else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAVS_URL_SCHEME ) ) )
+ targetURI.SetScheme(
+ rtl::OUString::createFromAscii( HTTPS_URL_SCHEME ) );
// @@@ This implementation of 'transfer' only works
// if the source and target are located at same host.
--- ucb/source/ucp/webdav/webdavcontent.hxx
+++ ucb/source/ucp/webdav/webdavcontent.hxx
@@ -33,10 +33,13 @@
#include
#include
+#include
#include
#include
#include
+#include
#include
+
#include "DAVResourceAccess.hxx"
#include "PropertyMap.hxx"
@@ -91,6 +94,9 @@ class Content : public ::ucbhelper::Cont
bool m_bTransient;
bool m_bCollection;
bool m_bDidGetOrHead;
+ bool m_bForceReadOnly;
+ com::sun::star::ucb::Lock *m_pLock;
+ uno::Reference< ucb::XCommandEnvironment > m_xLockEnv;
std::vector< rtl::OUString > m_aFailedPropNames;
private:
@@ -184,6 +190,17 @@ private:
static bool shouldAccessNetworkAfterException( const DAVException & e );
+ oslSignalHandler m_pSignalHandler;
+ int m_nToExpire;
+ osl::Mutex m_aLock;
+
+ // Refresh the lock of the resource
+ void RefreshLock( void );
+
+ // Refresh the lock if necessary, or unlock the resource when
+ // OOo crashes or is terminated
+ static oslSignalAction HandleLockingSignal( void* pData, oslSignalInfo* pInfo );
+
public:
Content( const ::com::sun::star::uno::Reference<
::com::sun::star::lang::XMultiServiceFactory >& rxSMgr,
--- ucb/source/ucp/webdav/webdavcontentcaps.cxx
+++ ucb/source/ucp/webdav/webdavcontentcaps.cxx
@@ -263,6 +263,24 @@ bool ContentProvider::getProperty(
-1,
getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
beans::PropertyAttribute::BOUND ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "SupportsActiveStreaming" ) ),
+ -1,
+ getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ),
+ -1,
+ getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
}
}
--- ucb/source/ucp/webdav/webdavprovider.cxx
+++ ucb/source/ucp/webdav/webdavprovider.cxx
@@ -36,6 +36,9 @@
**************************************************************************
*************************************************************************/
+
+#include
+
#include
#include "webdavprovider.hxx"
#include "webdavcontent.hxx"
@@ -138,7 +141,11 @@ ContentProvider::queryContent(
RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) &&
!aScheme.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) &&
- !aScheme.equalsAsciiL(
+ !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAV_URL_SCHEME ) ) &&
+ !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( PLAIN_WEBDAVS_URL_SCHEME ) ) &&
+ !aScheme.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( FTP_URL_SCHEME ) ) )
throw ucb::IllegalIdentifierException();
@@ -157,32 +164,27 @@ ContentProvider::queryContent(
uno::Reference< ucb::XContentIdentifier > xCanonicId;
bool bNewId = false;
- if ( aScheme.equalsAsciiL(
- RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) )
+ struct {
+ const char *from;
+ const char *to;
+ } const *pScheme, pReplace[] = {
+ { WEBDAV_URL_SCHEME, HTTP_URL_SCHEME },
+ { DAV_URL_SCHEME, HTTP_URL_SCHEME },
+ { DAVS_URL_SCHEME, HTTPS_URL_SCHEME },
+ { PLAIN_WEBDAV_URL_SCHEME, HTTP_URL_SCHEME },
+ { PLAIN_WEBDAVS_URL_SCHEME, HTTPS_URL_SCHEME },
+ { NULL, NULL }
+ };
+ for ( pScheme = pReplace; pScheme->from ; ++pScheme )
{
- aURL = aURL.replaceAt( 0,
- WEBDAV_URL_SCHEME_LENGTH,
- rtl::OUString::createFromAscii(
- HTTP_URL_SCHEME ) );
- bNewId = true;
- }
- else if ( aScheme.equalsAsciiL(
- RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) )
- {
- aURL = aURL.replaceAt( 0,
- DAV_URL_SCHEME_LENGTH,
- rtl::OUString::createFromAscii(
- HTTP_URL_SCHEME ) );
- bNewId = true;
- }
- else if ( aScheme.equalsAsciiL(
- RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) )
- {
- aURL = aURL.replaceAt( 0,
- DAVS_URL_SCHEME_LENGTH,
- rtl::OUString::createFromAscii(
- HTTPS_URL_SCHEME ) );
- bNewId = true;
+ if ( aScheme.equalsAscii( pScheme->from ) )
+ {
+ aURL = aURL.replaceAt( 0,
+ strlen( pScheme->from ),
+ rtl::OUString::createFromAscii( pScheme->to ) );
+ bNewId = true;
+ break;
+ }
}
sal_Int32 nPos = aURL.lastIndexOf( '/' );
@@ -208,6 +208,12 @@
else
xCanonicId = Identifier;
+#if OSL_DEBUG_LEVEL > 0
+ fprintf( stderr, "ContentProvider::queryContent(): bNewId=%s, xCanonicId=%s\n",
+ bNewId ? "YES" : "NO",
+ rtl::OUStringToOString( xCanonicId->getContentIdentifier(), RTL_TEXTENCODING_UTF8 ).getStr() );
+#endif
+
osl::MutexGuard aGuard( m_aMutex );
// Check, if a content with given id already exists...
@@ -232,4 +234,3 @@ ContentProvider::queryContent(
return xContent;
}
-
--- ucb/source/ucp/webdav/webdavprovider.hxx
+++ ucb/source/ucp/webdav/webdavprovider.hxx
@@ -52,13 +52,10 @@ namespace webdav_ucp {
// contents ) according to this scheme.
#define WEBDAV_URL_SCHEME \
"vnd.sun.star.webdav"
-#define WEBDAV_URL_SCHEME_LENGTH 19
#define HTTP_URL_SCHEME "http"
-#define HTTP_URL_SCHEME_LENGTH 4
#define HTTPS_URL_SCHEME "https"
-#define HTTPS_URL_SCHEME_LENGTH 5
#define DAV_URL_SCHEME "dav"
#define DAV_URL_SCHEME_LENGTH 3
@@ -70,6 +67,12 @@ namespace webdav_ucp {
#define FTP_URL_SCHEME "ftp"
+#define DAV_URL_SCHEME "dav"
+#define DAVS_URL_SCHEME "davs"
+
+#define PLAIN_WEBDAV_URL_SCHEME "webdav"
+#define PLAIN_WEBDAVS_URL_SCHEME "webdavs"
+
#define HTTP_CONTENT_TYPE \
"application/" HTTP_URL_SCHEME "-content"
--- unotools/source/ucbhelper/ucblockbytes.cxx
+++ unotools/source/ucbhelper/ucblockbytes.cxx
@@ -964,6 +964,10 @@ static sal_Bool UCBOpenContentSync(
if( ! aScheme.equalsIgnoreAsciiCaseAscii("http") &&
! aScheme.equalsIgnoreAsciiCaseAscii("https") &&
! aScheme.equalsIgnoreAsciiCaseAscii("vnd.sun.star.webdav") &&
+ ! aScheme.equalsIgnoreAsciiCaseAscii("dav") &&
+ ! aScheme.equalsIgnoreAsciiCaseAscii("davs") &&
+ ! aScheme.equalsIgnoreAsciiCaseAscii("webdav") &&
+ ! aScheme.equalsIgnoreAsciiCaseAscii("webdavs") &&
! aScheme.equalsIgnoreAsciiCaseAscii("ftp"))
return _UCBOpenContentSync(
xLockBytes,xContent,rArg,xSink,xInteract,xProgress,xHandler);
@@ -1541,7 +1545,13 @@ ErrCode UcbLockBytes::Flush() const
Reference xOutputStream = getOutputStream_Impl();
if ( !xOutputStream.is() )
return ERRCODE_IO_CANTWRITE;
- xOutputStream->flush();
+ try {
+ xOutputStream->flush();
+ }
+ catch (...)
+ {
+ return ERRCODE_IO_CANTWRITE;
+ }
return ERRCODE_NONE;
}