summaryrefslogtreecommitdiff
path: root/ucb/source/ucp/webdav
diff options
context:
space:
mode:
Diffstat (limited to 'ucb/source/ucp/webdav')
-rw-r--r--ucb/source/ucp/webdav/ContentProperties.cxx573
-rw-r--r--ucb/source/ucp/webdav/ContentProperties.hxx197
-rw-r--r--ucb/source/ucp/webdav/DAVAuthListener.hxx52
-rw-r--r--ucb/source/ucp/webdav/DAVAuthListenerImpl.hxx77
-rw-r--r--ucb/source/ucp/webdav/DAVException.hxx166
-rw-r--r--ucb/source/ucp/webdav/DAVProperties.cxx199
-rw-r--r--ucb/source/ucp/webdav/DAVProperties.hxx62
-rw-r--r--ucb/source/ucp/webdav/DAVRequestEnvironment.hxx62
-rw-r--r--ucb/source/ucp/webdav/DAVResource.hxx67
-rw-r--r--ucb/source/ucp/webdav/DAVResourceAccess.cxx1218
-rw-r--r--ucb/source/ucp/webdav/DAVResourceAccess.hxx251
-rw-r--r--ucb/source/ucp/webdav/DAVSession.hxx219
-rw-r--r--ucb/source/ucp/webdav/DAVSessionFactory.cxx106
-rw-r--r--ucb/source/ucp/webdav/DAVSessionFactory.hxx82
-rw-r--r--ucb/source/ucp/webdav/DAVTypes.hxx85
-rw-r--r--ucb/source/ucp/webdav/DateTimeHelper.cxx270
-rw-r--r--ucb/source/ucp/webdav/DateTimeHelper.hxx63
-rw-r--r--ucb/source/ucp/webdav/LinkSequence.cxx223
-rw-r--r--ucb/source/ucp/webdav/LinkSequence.hxx51
-rw-r--r--ucb/source/ucp/webdav/LockEntrySequence.cxx244
-rw-r--r--ucb/source/ucp/webdav/LockEntrySequence.hxx48
-rw-r--r--ucb/source/ucp/webdav/LockSequence.cxx351
-rw-r--r--ucb/source/ucp/webdav/LockSequence.hxx48
-rw-r--r--ucb/source/ucp/webdav/NeonHeadRequest.cxx200
-rw-r--r--ucb/source/ucp/webdav/NeonHeadRequest.hxx53
-rw-r--r--ucb/source/ucp/webdav/NeonInputStream.cxx195
-rw-r--r--ucb/source/ucp/webdav/NeonInputStream.hxx124
-rw-r--r--ucb/source/ucp/webdav/NeonLockStore.cxx245
-rw-r--r--ucb/source/ucp/webdav/NeonLockStore.hxx102
-rw-r--r--ucb/source/ucp/webdav/NeonPropFindRequest.cxx345
-rw-r--r--ucb/source/ucp/webdav/NeonPropFindRequest.hxx62
-rw-r--r--ucb/source/ucp/webdav/NeonSession.cxx2184
-rw-r--r--ucb/source/ucp/webdav/NeonSession.hxx295
-rw-r--r--ucb/source/ucp/webdav/NeonTypes.hxx46
-rw-r--r--ucb/source/ucp/webdav/NeonUri.cxx358
-rw-r--r--ucb/source/ucp/webdav/NeonUri.hxx102
-rw-r--r--ucb/source/ucp/webdav/PropertyMap.hxx65
-rw-r--r--ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx547
-rw-r--r--ucb/source/ucp/webdav/UCBDeadPropertyValue.hxx65
-rw-r--r--ucb/source/ucp/webdav/makefile.mk168
-rw-r--r--ucb/source/ucp/webdav/ucpdav.xml109
-rw-r--r--ucb/source/ucp/webdav/ucpdav1.component34
-rw-r--r--ucb/source/ucp/webdav/webdavcontent.cxx3247
-rw-r--r--ucb/source/ucp/webdav/webdavcontent.hxx299
-rw-r--r--ucb/source/ucp/webdav/webdavcontentcaps.cxx672
-rw-r--r--ucb/source/ucp/webdav/webdavdatasupplier.cxx512
-rw-r--r--ucb/source/ucp/webdav/webdavdatasupplier.hxx82
-rw-r--r--ucb/source/ucp/webdav/webdavprovider.cxx232
-rw-r--r--ucb/source/ucp/webdav/webdavprovider.hxx124
-rw-r--r--ucb/source/ucp/webdav/webdavresultset.cxx95
-rw-r--r--ucb/source/ucp/webdav/webdavresultset.hxx59
-rw-r--r--ucb/source/ucp/webdav/webdavservices.cxx76
52 files changed, 15411 insertions, 0 deletions
diff --git a/ucb/source/ucp/webdav/ContentProperties.cxx b/ucb/source/ucp/webdav/ContentProperties.cxx
new file mode 100644
index 000000000000..2285ad28a888
--- /dev/null
+++ b/ucb/source/ucp/webdav/ContentProperties.cxx
@@ -0,0 +1,573 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+#include <osl/diagnose.h>
+#include <com/sun/star/util/DateTime.hpp>
+#include "NeonUri.hxx"
+#include "DAVResource.hxx"
+#include "DAVProperties.hxx"
+#include "DateTimeHelper.hxx"
+#include "webdavprovider.hxx"
+#include "ContentProperties.hxx"
+
+using namespace com::sun::star;
+using namespace webdav_ucp;
+
+/*
+=============================================================================
+
+ Property Mapping
+
+=============================================================================
+HTTP (entity header) WebDAV (property) UCB (property)
+=============================================================================
+
+Allow
+Content-Encoding
+Content-Language getcontentlanguage
+Content-Length getcontentlength Size
+Content-Location
+Content-MD5
+Content-Range
+Content-Type getcontenttype MediaType
+Expires
+Last-Modified getlastmodified DateModified
+ creationdate DateCreated
+ resourcetype IsFolder,IsDocument,ContentType
+ displayname
+ETag (actually getetag
+a response header )
+ lockdiscovery
+ supportedlock
+ source
+ Title (always taken from URI)
+
+=============================================================================
+
+Important: HTTP headers will not be mapped to DAV properties; only to UCB
+ properties. (Content-Length,Content-Type,Last-Modified)
+*/
+
+//=========================================================================
+//=========================================================================
+//
+// ContentProperties Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+// static member!
+uno::Any ContentProperties::m_aEmptyAny;
+
+ContentProperties::ContentProperties( const DAVResource& rResource )
+: m_xProps( new PropertyValueMap ),
+ m_bTrailingSlash( false )
+{
+ OSL_ENSURE( rResource.uri.getLength(),
+ "ContentProperties ctor - Empty resource URI!" );
+
+ // Title
+ try
+ {
+ NeonUri aURI( rResource.uri );
+ m_aEscapedTitle = aURI.GetPathBaseName();
+
+ (*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ]
+ = PropertyValue(
+ uno::makeAny( aURI.GetPathBaseNameUnescaped() ), true );
+ }
+ catch ( DAVException const & )
+ {
+ (*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ]
+ = PropertyValue(
+ uno::makeAny(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "*** unknown ***" ) ) ),
+ true );
+ }
+
+ std::vector< DAVPropertyValue >::const_iterator it
+ = rResource.properties.begin();
+ std::vector< DAVPropertyValue >::const_iterator end
+ = rResource.properties.end();
+
+ while ( it != end )
+ {
+ addProperty( (*it) );
+ ++it;
+ }
+
+ if ( rResource.uri.getStr()[ rResource.uri.getLength() - 1 ]
+ == sal_Unicode( '/' ) )
+ m_bTrailingSlash = sal_True;
+}
+
+//=========================================================================
+ContentProperties::ContentProperties(
+ const rtl::OUString & rTitle, sal_Bool bFolder )
+: m_xProps( new PropertyValueMap ),
+ m_bTrailingSlash( sal_False )
+{
+ (*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ]
+ = PropertyValue( uno::makeAny( rTitle ), true );
+ (*m_xProps)[ rtl::OUString::createFromAscii( "IsFolder" ) ]
+ = PropertyValue( uno::makeAny( bFolder ), true );
+ (*m_xProps)[ rtl::OUString::createFromAscii( "IsDocument" ) ]
+ = PropertyValue( uno::makeAny( sal_Bool( !bFolder ) ), true );
+}
+
+//=========================================================================
+ContentProperties::ContentProperties( const rtl::OUString & rTitle )
+: m_xProps( new PropertyValueMap ),
+ m_bTrailingSlash( sal_False )
+{
+ (*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ]
+ = PropertyValue( uno::makeAny( rTitle ), true );
+}
+
+//=========================================================================
+ContentProperties::ContentProperties( const ContentProperties & rOther )
+: m_aEscapedTitle( rOther.m_aEscapedTitle ),
+ m_xProps( rOther.m_xProps.get()
+ ? new PropertyValueMap( *rOther.m_xProps )
+ : new PropertyValueMap ),
+ m_bTrailingSlash( rOther.m_bTrailingSlash )
+{
+}
+
+//=========================================================================
+bool ContentProperties::contains( const rtl::OUString & rName ) const
+{
+ if ( get( rName ) )
+ return true;
+ else
+ return false;
+}
+
+//=========================================================================
+const uno::Any & ContentProperties::getValue(
+ const rtl::OUString & rName ) const
+{
+ const PropertyValue * pProp = get( rName );
+ if ( pProp )
+ return pProp->value();
+ else
+ return m_aEmptyAny;
+}
+
+//=========================================================================
+const PropertyValue * ContentProperties::get(
+ const rtl::OUString & rName ) const
+{
+ PropertyValueMap::const_iterator it = m_xProps->find( rName );
+ const PropertyValueMap::const_iterator end = m_xProps->end();
+
+ if ( it == end )
+ {
+ it = m_xProps->begin();
+ while ( it != end )
+ {
+ if ( (*it).first.equalsIgnoreAsciiCase( rName ) )
+ return &(*it).second;
+
+ ++it;
+ }
+ return 0;
+ }
+ else
+ return &(*it).second;
+}
+
+//=========================================================================
+// static
+void ContentProperties::UCBNamesToDAVNames(
+ const uno::Sequence< beans::Property > & rProps,
+ std::vector< rtl::OUString > & propertyNames,
+ bool bIncludeUnmatched /* = true */ )
+{
+ //////////////////////////////////////////////////////////////
+ // Assemble list of DAV properties to obtain from server.
+ // Append DAV properties needed to obtain requested UCB props.
+ //////////////////////////////////////////////////////////////
+
+ // DAV UCB
+ // creationdate <- DateCreated
+ // getlastmodified <- DateModified
+ // getcontenttype <- MediaType
+ // getcontentlength <- Size
+ // resourcetype <- IsFolder, IsDocument, ContentType
+ // (taken from URI) <- Title
+
+ sal_Bool bCreationDate = sal_False;
+ sal_Bool bLastModified = sal_False;
+ sal_Bool bContentType = sal_False;
+ sal_Bool bContentLength = sal_False;
+ sal_Bool bResourceType = sal_False;
+
+ sal_Int32 nCount = rProps.getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const beans::Property & rProp = rProps[ n ];
+
+ if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
+ {
+ // Title is always obtained from resource's URI.
+ continue;
+ }
+ else if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) )
+ ||
+ ( rProp.Name == DAVProperties::CREATIONDATE ) )
+ {
+ if ( !bCreationDate )
+ {
+ propertyNames.push_back( DAVProperties::CREATIONDATE );
+ bCreationDate = sal_True;
+ }
+ }
+ else if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "DateModified" ) )
+ ||
+ ( rProp.Name == DAVProperties::GETLASTMODIFIED ) )
+ {
+ if ( !bLastModified )
+ {
+ propertyNames.push_back(
+ DAVProperties::GETLASTMODIFIED );
+ bLastModified = sal_True;
+ }
+ }
+ else if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "MediaType" ) )
+ ||
+ ( rProp.Name == DAVProperties::GETCONTENTTYPE ) )
+ {
+ if ( !bContentType )
+ {
+ propertyNames.push_back(
+ DAVProperties::GETCONTENTTYPE );
+ bContentType = sal_True;
+ }
+ }
+ else if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "Size" ) )
+ ||
+ ( rProp.Name == DAVProperties::GETCONTENTLENGTH ) )
+ {
+ if ( !bContentLength )
+ {
+ propertyNames.push_back(
+ DAVProperties::GETCONTENTLENGTH );
+ bContentLength = sal_True;
+ }
+ }
+ else if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "ContentType" ) )
+ ||
+ rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) )
+ ||
+ rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) )
+ ||
+ ( rProp.Name == DAVProperties::RESOURCETYPE ) )
+ {
+ if ( !bResourceType )
+ {
+ propertyNames.push_back( DAVProperties::RESOURCETYPE );
+ bResourceType = sal_True;
+ }
+ }
+ else
+ {
+ if ( bIncludeUnmatched )
+ propertyNames.push_back( rProp.Name );
+ }
+ }
+}
+
+//=========================================================================
+// static
+void ContentProperties::UCBNamesToHTTPNames(
+ const uno::Sequence< beans::Property > & rProps,
+ std::vector< rtl::OUString > & propertyNames,
+ bool bIncludeUnmatched /* = true */ )
+{
+ //////////////////////////////////////////////////////////////
+ // Assemble list of HTTP header names to obtain from server.
+ // Append HTTP headers needed to obtain requested UCB props.
+ //////////////////////////////////////////////////////////////
+
+ // HTTP UCB
+ // Last-Modified <- DateModified
+ // Content-Type <- MediaType
+ // Content-Length <- Size
+
+ sal_Int32 nCount = rProps.getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const beans::Property & rProp = rProps[ n ];
+
+ if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
+ {
+ propertyNames.push_back(
+ rtl::OUString::createFromAscii( "Last-Modified" ) );
+ }
+ else if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
+ {
+ propertyNames.push_back(
+ rtl::OUString::createFromAscii( "Content-Type" ) );
+ }
+ else if ( rProp.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
+ {
+ propertyNames.push_back(
+ rtl::OUString::createFromAscii( "Content-Length" ) );
+ }
+ else
+ {
+ if ( bIncludeUnmatched )
+ propertyNames.push_back( rProp.Name );
+ }
+ }
+}
+
+//=========================================================================
+bool ContentProperties::containsAllNames(
+ const uno::Sequence< beans::Property >& rProps,
+ std::vector< rtl::OUString > & rNamesNotContained ) const
+{
+ rNamesNotContained.clear();
+
+ sal_Int32 nCount = rProps.getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const rtl::OUString & rName = rProps[ n ].Name;
+ if ( !contains( rName ) )
+ {
+ // Not found.
+ rNamesNotContained.push_back( rName );
+ }
+ }
+
+ return ( rNamesNotContained.size() == 0 );
+}
+
+//=========================================================================
+void ContentProperties::addProperties(
+ const std::vector< rtl::OUString > & rProps,
+ const ContentProperties & rContentProps )
+{
+ std::vector< rtl::OUString >::const_iterator it = rProps.begin();
+ std::vector< rtl::OUString >::const_iterator end = rProps.end();
+
+ while ( it != end )
+ {
+ const rtl::OUString & rName = (*it);
+
+ if ( !contains( rName ) ) // ignore duplicates
+ {
+ const PropertyValue * pProp = rContentProps.get( rName );
+ if ( pProp )
+ {
+ // Add it.
+ addProperty( rName, pProp->value(), pProp->isCaseSensitive() );
+ }
+ else
+ {
+ addProperty( rName, uno::Any(), false );
+ }
+ }
+ ++it;
+ }
+}
+
+//=========================================================================
+void ContentProperties::addProperties( const ContentProperties & rProps )
+{
+ PropertyValueMap::const_iterator it = rProps.m_xProps->begin();
+ const PropertyValueMap::const_iterator end = rProps.m_xProps->end();
+
+ while ( it != end )
+ {
+ addProperty(
+ (*it).first, (*it).second.value(), (*it).second.isCaseSensitive() );
+ ++it;
+ }
+}
+
+//=========================================================================
+void ContentProperties::addProperties(
+ const std::vector< DAVPropertyValue > & rProps )
+{
+ std::vector< DAVPropertyValue >::const_iterator it = rProps.begin();
+ std::vector< DAVPropertyValue >::const_iterator end = rProps.end();
+
+ while ( it != end )
+ {
+ addProperty( (*it) );
+ ++it;
+ }
+}
+
+//=========================================================================
+void ContentProperties::addProperty( const DAVPropertyValue & rProp )
+{
+ addProperty( rProp.Name, rProp.Value, rProp.IsCaseSensitive );
+}
+
+//=========================================================================
+void ContentProperties::addProperty( const rtl::OUString & rName,
+ const com::sun::star::uno::Any & rValue,
+ bool bIsCaseSensitive )
+{
+ if ( rName.equals( DAVProperties::CREATIONDATE ) )
+ {
+ // Map DAV:creationdate to UCP:DateCreated
+ rtl::OUString aValue;
+ rValue >>= aValue;
+ util::DateTime aDate;
+ DateTimeHelper::convert( aValue, aDate );
+
+ (*m_xProps)[ rtl::OUString::createFromAscii( "DateCreated" ) ]
+ = PropertyValue( uno::makeAny( aDate ), true );
+ }
+ // else if ( rName.equals( DAVProperties::DISPLAYNAME ) )
+ // {
+ // }
+ // else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
+ // {
+ // }
+ else if ( rName.equals( DAVProperties::GETCONTENTLENGTH ) )
+ {
+ // Map DAV:getcontentlength to UCP:Size
+ rtl::OUString aValue;
+ rValue >>= aValue;
+
+ (*m_xProps)[ rtl::OUString::createFromAscii( "Size" ) ]
+ = PropertyValue( uno::makeAny( aValue.toInt64() ), true );
+ }
+ else if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) )
+ {
+ // Do NOT map Content-Lenght entity header to DAV:getcontentlength!
+ // Only DAV resources have this property.
+
+ // Map Content-Length entity header to UCP:Size
+ rtl::OUString aValue;
+ rValue >>= aValue;
+
+ (*m_xProps)[ rtl::OUString::createFromAscii( "Size" ) ]
+ = PropertyValue( uno::makeAny( aValue.toInt64() ), true );
+ }
+ else if ( rName.equals( DAVProperties::GETCONTENTTYPE ) )
+ {
+ // Map DAV:getcontenttype to UCP:MediaType (1:1)
+ (*m_xProps)[ rtl::OUString::createFromAscii( "MediaType" ) ]
+ = PropertyValue( rValue, true );
+ }
+ else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Type" ) ) )
+ {
+ // Do NOT map Content-Type entity header to DAV:getcontenttype!
+ // Only DAV resources have this property.
+
+ // Map DAV:getcontenttype to UCP:MediaType (1:1)
+ (*m_xProps)[ rtl::OUString::createFromAscii( "MediaType" ) ]
+ = PropertyValue( rValue, true );
+ }
+ // else if ( rName.equals( DAVProperties::GETETAG ) )
+ // {
+ // }
+ else if ( rName.equals( DAVProperties::GETLASTMODIFIED ) )
+ {
+ // Map the DAV:getlastmodified entity header to UCP:DateModified
+ rtl::OUString aValue;
+ rValue >>= aValue;
+ util::DateTime aDate;
+ DateTimeHelper::convert( aValue, aDate );
+
+ (*m_xProps)[ rtl::OUString::createFromAscii( "DateModified" ) ]
+ = PropertyValue( uno::makeAny( aDate ), true );
+ }
+ else if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "Last-Modified" ) ) )
+ {
+ // Do not map Last-Modified entity header to DAV:getlastmodified!
+ // Only DAV resources have this property.
+
+ // Map the Last-Modified entity header to UCP:DateModified
+ rtl::OUString aValue;
+ rValue >>= aValue;
+ util::DateTime aDate;
+ DateTimeHelper::convert( aValue, aDate );
+
+ (*m_xProps)[ rtl::OUString::createFromAscii( "DateModified" ) ]
+ = PropertyValue( uno::makeAny( aDate ), true );
+ }
+ // else if ( rName.equals( DAVProperties::LOCKDISCOVERY ) )
+ // {
+ // }
+ else if ( rName.equals( DAVProperties::RESOURCETYPE ) )
+ {
+ rtl::OUString aValue;
+ rValue >>= aValue;
+
+ // Map DAV:resourceype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType
+ sal_Bool bFolder =
+ aValue.equalsIgnoreAsciiCaseAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "collection" ) );
+
+ (*m_xProps)[ rtl::OUString::createFromAscii( "IsFolder" ) ]
+ = PropertyValue( uno::makeAny( bFolder ), true );
+ (*m_xProps)[ rtl::OUString::createFromAscii( "IsDocument" ) ]
+ = PropertyValue( uno::makeAny( sal_Bool( !bFolder ) ), true );
+ (*m_xProps)[ rtl::OUString::createFromAscii( "ContentType" ) ]
+ = PropertyValue( uno::makeAny( bFolder
+ ? rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE )
+ : rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE ) ), true );
+ }
+ // else if ( rName.equals( DAVProperties::SOURCE ) )
+ // {
+ // }
+ // else if ( rName.equals( DAVProperties::SUPPORTEDLOCK ) )
+ // {
+ // }
+
+ // Save property.
+ (*m_xProps)[ rName ] = PropertyValue( rValue, bIsCaseSensitive );
+}
diff --git a/ucb/source/ucp/webdav/ContentProperties.hxx b/ucb/source/ucp/webdav/ContentProperties.hxx
new file mode 100644
index 000000000000..7819698bf667
--- /dev/null
+++ b/ucb/source/ucp/webdav/ContentProperties.hxx
@@ -0,0 +1,197 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WEBDAV_UCP_CONTENTPROPERTIES_HXX
+#define _WEBDAV_UCP_CONTENTPROPERTIES_HXX
+
+#include <memory>
+#include <vector>
+#include <hash_map>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+namespace com { namespace sun { namespace star { namespace beans {
+ struct Property;
+} } } }
+
+namespace webdav_ucp
+{
+
+struct DAVResource;
+
+//=========================================================================
+
+struct equalString
+{
+ bool operator()( const rtl::OUString& s1, const rtl::OUString& s2 ) const
+ {
+ return !!( s1 == s2 );
+ }
+};
+
+struct hashString
+{
+ size_t operator()( const rtl::OUString & rName ) const
+ {
+ return rName.hashCode();
+ }
+};
+
+//=========================================================================
+//
+// PropertyValueMap.
+//
+//=========================================================================
+
+class PropertyValue
+{
+private:
+ ::com::sun::star::uno::Any m_aValue;
+ bool m_bIsCaseSensitive;
+
+public:
+ PropertyValue()
+ : m_bIsCaseSensitive( true ) {}
+
+ PropertyValue( const ::com::sun::star::uno::Any & rValue,
+ bool bIsCaseSensitive )
+ : m_aValue( rValue),
+ m_bIsCaseSensitive( bIsCaseSensitive ) {}
+
+ bool isCaseSensitive() const { return m_bIsCaseSensitive; }
+ const ::com::sun::star::uno::Any & value() const { return m_aValue; }
+
+};
+
+typedef std::hash_map
+<
+ rtl::OUString,
+ PropertyValue,
+ hashString,
+ equalString
+>
+PropertyValueMap;
+
+struct DAVResource;
+
+class ContentProperties
+{
+public:
+ ContentProperties( const DAVResource& rResource );
+
+ // Mini props for transient contents.
+ ContentProperties( const rtl::OUString & rTitle, sal_Bool bFolder );
+
+ // Micro props for non-existing contents.
+ ContentProperties( const rtl::OUString & rTitle );
+
+ ContentProperties( const ContentProperties & rOther );
+
+ bool contains( const rtl::OUString & rName ) const;
+
+ const com::sun::star::uno::Any &
+ getValue( const rtl::OUString & rName ) const;
+
+ // Maps the UCB property names contained in rProps with their DAV property
+ // counterparts, if possible. All unmappable properties will be included
+ // unchanged in resulting vector unless bIncludeUnmatched is set to false.
+ // The vector filles by this method can directly be handed over to
+ // DAVResourceAccess::PROPFIND. The result from PROPFIND
+ // (vector< DAVResource >) can be used to create a ContentProperties
+ // instance which can map DAV properties back to UCB properties.
+ static void UCBNamesToDAVNames( const com::sun::star::uno::Sequence<
+ com::sun::star::beans::Property > &
+ rProps,
+ std::vector< rtl::OUString > & resources,
+ bool bIncludeUnmatched = true );
+
+ // Maps the UCB property names contained in rProps with their HTTP header
+ // counterparts, if possible. All unmappable properties will be included
+ // unchanged in resulting vector unless bIncludeUnmatched is set to false.
+ // The vector filles by this method can directly be handed over to
+ // DAVResourceAccess::HEAD. The result from HEAD (vector< DAVResource >)
+ // can be used to create a ContentProperties instance which can map header
+ // names back to UCB properties.
+ static void UCBNamesToHTTPNames( const com::sun::star::uno::Sequence<
+ com::sun::star::beans::Property > &
+ rProps,
+ std::vector< rtl::OUString > & resources,
+ bool bIncludeUnmatched = true );
+
+ // return true, if all properties contained in rProps are contained in
+ // this ContentProperties instance. Otherwiese, false will be returned.
+ // rNamesNotContained contain the missing names.
+ bool containsAllNames(
+ const com::sun::star::uno::Sequence<
+ com::sun::star::beans::Property >& rProps,
+ std::vector< rtl::OUString > & rNamesNotContained ) const;
+
+ // adds all properties described by rProps that are actually contained in
+ // rContentProps to this instance. In case of duplicates the value
+ // already contained in this will left unchanged.
+ void addProperties( const std::vector< rtl::OUString > & rProps,
+ const ContentProperties & rContentProps );
+
+ // overwrites probably existing entries.
+ void addProperties( const ContentProperties & rProps );
+
+ // overwrites probably existing entries.
+ void addProperties( const std::vector< DAVPropertyValue > & rProps );
+
+ // overwrites probably existing entry.
+ void addProperty( const rtl::OUString & rName,
+ const com::sun::star::uno::Any & rValue,
+ bool bIsCaseSensitive );
+
+ // overwrites probably existing entry.
+ void addProperty( const DAVPropertyValue & rProp );
+
+ bool isTrailingSlash() const { return m_bTrailingSlash; }
+
+ const rtl::OUString & getEscapedTitle() const { return m_aEscapedTitle; }
+
+ // Not good to expose implementation details, but this is actually an
+ // internal class.
+ const std::auto_ptr< PropertyValueMap > & getProperties() const
+ { return m_xProps; }
+
+private:
+ ::rtl::OUString m_aEscapedTitle; // escaped Title
+ std::auto_ptr< PropertyValueMap > m_xProps;
+ bool m_bTrailingSlash;
+
+ static com::sun::star::uno::Any m_aEmptyAny;
+
+ ContentProperties & operator=( const ContentProperties & ); // n.i.
+
+ const PropertyValue * get( const rtl::OUString & rName ) const;
+};
+
+}
+
+#endif /* !_WEBDAV_UCP_CONTENTPROPERTIES_HXX */
diff --git a/ucb/source/ucp/webdav/DAVAuthListener.hxx b/ucb/source/ucp/webdav/DAVAuthListener.hxx
new file mode 100644
index 000000000000..71bed1c0a14d
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVAuthListener.hxx
@@ -0,0 +1,52 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DAVAUTHLISTENER_HXX_
+#define _DAVAUTHLISTENER_HXX_
+
+#include <salhelper/simplereferenceobject.hxx>
+#include <rtl/ustring.hxx>
+
+#include <com/sun/star/uno/XReference.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+
+namespace webdav_ucp
+{
+
+class DAVAuthListener : public salhelper::SimpleReferenceObject
+{
+ public:
+ virtual int authenticate(
+ const ::rtl::OUString & inRealm,
+ const ::rtl::OUString & inHostName,
+ ::rtl::OUString & inoutUserName,
+ ::rtl::OUString & outPassWord,
+ sal_Bool bCanUseSystemCredentials ) = 0;
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVAUTHLISTENER_HXX_
diff --git a/ucb/source/ucp/webdav/DAVAuthListenerImpl.hxx b/ucb/source/ucp/webdav/DAVAuthListenerImpl.hxx
new file mode 100644
index 000000000000..c0c9968613af
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVAuthListenerImpl.hxx
@@ -0,0 +1,77 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DAVAUTHLISTENERIMPL_HXX_
+#define _DAVAUTHLISTENERIMPL_HXX_
+
+#include "DAVAuthListener.hxx"
+
+
+namespace webdav_ucp
+{
+
+//=========================================================================
+
+//=========================================================================
+//=========================================================================
+//
+// class DAVAuthListenerImpl.
+//
+//=========================================================================
+//=========================================================================
+
+
+ class DAVAuthListener_Impl : public DAVAuthListener
+ {
+ public:
+
+ DAVAuthListener_Impl(
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment>& xEnv,
+ const ::rtl::OUString & inURL )
+ : m_xEnv( xEnv ), m_aURL( inURL )
+ {
+ }
+
+ virtual int authenticate( const ::rtl::OUString & inRealm,
+ const ::rtl::OUString & inHostName,
+ ::rtl::OUString & inoutUserName,
+ ::rtl::OUString & outPassWord,
+ sal_Bool bCanUseSystemCredentials );
+ private:
+
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > m_xEnv;
+ const rtl::OUString m_aURL;
+
+ rtl::OUString m_aPrevPassword;
+ rtl::OUString m_aPrevUsername;
+ };
+
+}
+
+#endif
diff --git a/ucb/source/ucp/webdav/DAVException.hxx b/ucb/source/ucp/webdav/DAVException.hxx
new file mode 100644
index 000000000000..c981eb404676
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVException.hxx
@@ -0,0 +1,166 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DAVEXCEPTION_HXX_
+#define _DAVEXCEPTION_HXX_
+
+#include <rtl/ustring.hxx>
+
+namespace webdav_ucp
+{
+
+/////////////////////////////////////////////////////////////////////////////
+// HTTP/WebDAV status codes
+/////////////////////////////////////////////////////////////////////////////
+
+const sal_uInt16 SC_NONE = 0;
+
+// 1xx (Informational - no errors)
+const sal_uInt16 SC_CONTINUE = 100;
+const sal_uInt16 SC_SWITCHING_PROTOCOLS = 101;
+// DAV extensions
+const sal_uInt16 SC_PROCESSING = 102;
+
+//2xx (Successful - no errors)
+const sal_uInt16 SC_OK = 200;
+const sal_uInt16 SC_CREATED = 201;
+const sal_uInt16 SC_ACCEPTED = 202;
+const sal_uInt16 SC_NON_AUTHORITATIVE_INFORMATION = 203;
+const sal_uInt16 SC_NO_CONTENT = 204;
+const sal_uInt16 SC_RESET_CONTENT = 205;
+const sal_uInt16 SC_PARTIAL_CONTENT = 206;
+// DAV extensions
+const sal_uInt16 SC_MULTISTATUS = 207;
+
+//3xx (Redirection)
+const sal_uInt16 SC_MULTIPLE_CHOICES = 300;
+const sal_uInt16 SC_MOVED_PERMANENTLY = 301;
+const sal_uInt16 SC_MOVED_TEMPORARILY = 302;
+const sal_uInt16 SC_SEE_OTHER = 303;
+const sal_uInt16 SC_NOT_MODIFIED = 304;
+const sal_uInt16 SC_USE_PROXY = 305;
+const sal_uInt16 SC_TEMPORARY_REDIRECT = 307;
+
+//4xx (Client error)
+const sal_uInt16 SC_BAD_REQUEST = 400;
+const sal_uInt16 SC_UNAUTHORIZED = 401;
+const sal_uInt16 SC_PAYMENT_REQUIRED = 402;
+const sal_uInt16 SC_FORBIDDEN = 403;
+const sal_uInt16 SC_NOT_FOUND = 404;
+const sal_uInt16 SC_METHOD_NOT_ALLOWED = 405;
+const sal_uInt16 SC_NOT_ACCEPTABLE = 406;
+const sal_uInt16 SC_PROXY_AUTHENTICATION_REQUIRED = 407;
+const sal_uInt16 SC_REQUEST_TIMEOUT = 408;
+const sal_uInt16 SC_CONFLICT = 409;
+const sal_uInt16 SC_GONE = 410;
+const sal_uInt16 SC_LENGTH_REQUIRED = 411;
+const sal_uInt16 SC_PRECONDITION_FAILED = 412;
+const sal_uInt16 SC_REQUEST_ENTITY_TOO_LARGE = 413;
+const sal_uInt16 SC_REQUEST_URI_TOO_LONG = 414;
+const sal_uInt16 SC_UNSUPPORTED_MEDIA_TYPE = 415;
+const sal_uInt16 SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
+const sal_uInt16 SC_EXPECTATION_FAILED = 417;
+// DAV extensions
+const sal_uInt16 SC_UNPROCESSABLE_ENTITY = 422;
+const sal_uInt16 SC_LOCKED = 423;
+const sal_uInt16 SC_FAILED_DEPENDENCY = 424;
+
+//5xx (Server error)
+const sal_uInt16 SC_INTERNAL_SERVER_ERROR = 500;
+const sal_uInt16 SC_NOT_IMPLEMENTED = 501;
+const sal_uInt16 SC_BAD_GATEWAY = 502;
+const sal_uInt16 SC_SERVICE_UNAVAILABLE = 503;
+const sal_uInt16 SC_GATEWAY_TIMEOUT = 504;
+const sal_uInt16 SC_HTTP_VERSION_NOT_SUPPORTED = 505;
+// DAV extensions
+const sal_uInt16 SC_INSUFFICIENT_STORAGE = 507;
+
+/////////////////////////////////////////////////////////////////////////////
+
+class DAVException
+{
+ public:
+ enum ExceptionCode {
+ DAV_HTTP_ERROR = 0, // Generic error,
+ // mData = server error message,
+ // mStatusCode = HTTP status code
+ DAV_HTTP_LOOKUP, // Name lookup failed,
+ // mData = server[:port]
+ DAV_HTTP_AUTH, // User authentication failed on server,
+ // mData = server[:port]
+ DAV_HTTP_AUTHPROXY, // User authentication failed on proxy,
+ // mData = proxy server[:port]
+ DAV_HTTP_CONNECT, // Could not connect to server,
+ // mData = server[:port]
+ DAV_HTTP_TIMEOUT, // Connection timed out
+ // mData = server[:port]
+ DAV_HTTP_FAILED, // The precondition failed
+ // mData = server[:port]
+ DAV_HTTP_RETRY, // Retry request
+ // mData = server[:port]
+ DAV_HTTP_REDIRECT, // Request was redirected,
+ // mData = new URL
+ DAV_SESSION_CREATE, // session creation error,
+ // mData = server[:port]
+ DAV_INVALID_ARG, // invalid argument
+
+ DAV_LOCK_EXPIRED, // DAV lock expired
+
+ DAV_NOT_LOCKED, // not locked
+
+ DAV_LOCKED_SELF, // locked by this OOo session
+
+ DAV_LOCKED // locked by third party
+ };
+
+ private:
+ ExceptionCode mExceptionCode;
+ rtl::OUString mData;
+ sal_uInt16 mStatusCode;
+
+ public:
+ DAVException( ExceptionCode inExceptionCode ) :
+ mExceptionCode( inExceptionCode ), mStatusCode( SC_NONE ) {};
+ DAVException( ExceptionCode inExceptionCode,
+ const rtl::OUString & rData ) :
+ mExceptionCode( inExceptionCode ), mData( rData ),
+ mStatusCode( SC_NONE ) {};
+ DAVException( ExceptionCode inExceptionCode,
+ const rtl::OUString & rData,
+ sal_uInt16 nStatusCode ) :
+ mExceptionCode( inExceptionCode ), mData( rData ),
+ mStatusCode( nStatusCode ) {};
+ ~DAVException( ) {};
+
+ const ExceptionCode & getError() const { return mExceptionCode; }
+ const rtl::OUString & getData() const { return mData; }
+ sal_uInt16 getStatus() const { return mStatusCode; }
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVEXCEPTION_HXX_
diff --git a/ucb/source/ucp/webdav/DAVProperties.cxx b/ucb/source/ucp/webdav/DAVProperties.cxx
new file mode 100644
index 000000000000..1202fb75a59f
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVProperties.cxx
@@ -0,0 +1,199 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <string.h>
+#include "DAVProperties.hxx"
+
+using namespace webdav_ucp;
+
+const ::rtl::OUString DAVProperties::CREATIONDATE =
+ ::rtl::OUString::createFromAscii( "DAV:creationdate" );
+const ::rtl::OUString DAVProperties::DISPLAYNAME =
+ ::rtl::OUString::createFromAscii( "DAV:displayname" );
+const ::rtl::OUString DAVProperties::GETCONTENTLANGUAGE =
+ ::rtl::OUString::createFromAscii( "DAV:getcontentlanguage" );
+const ::rtl::OUString DAVProperties::GETCONTENTLENGTH =
+ ::rtl::OUString::createFromAscii( "DAV:getcontentlength" );
+const ::rtl::OUString DAVProperties::GETCONTENTTYPE =
+ ::rtl::OUString::createFromAscii( "DAV:getcontenttype" );
+const ::rtl::OUString DAVProperties::GETETAG =
+ ::rtl::OUString::createFromAscii( "DAV:getetag" );
+const ::rtl::OUString DAVProperties::GETLASTMODIFIED =
+ ::rtl::OUString::createFromAscii( "DAV:getlastmodified" );
+const ::rtl::OUString DAVProperties::LOCKDISCOVERY =
+ ::rtl::OUString::createFromAscii( "DAV:lockdiscovery" );
+const ::rtl::OUString DAVProperties::RESOURCETYPE =
+ ::rtl::OUString::createFromAscii( "DAV:resourcetype" );
+const ::rtl::OUString DAVProperties::SOURCE =
+ ::rtl::OUString::createFromAscii( "DAV:source" );
+const ::rtl::OUString DAVProperties::SUPPORTEDLOCK =
+ ::rtl::OUString::createFromAscii( "DAV:supportedlock" );
+
+const ::rtl::OUString DAVProperties::EXECUTABLE =
+ ::rtl::OUString::createFromAscii(
+ "http://apache.org/dav/props/executable" );
+
+// -------------------------------------------------------------------
+// static
+void DAVProperties::createNeonPropName( const rtl::OUString & rFullName,
+ NeonPropName & rName )
+{
+ if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "DAV:" ) ) == 0 )
+ {
+ rName.nspace = "DAV:";
+ rName.name
+ = strdup( rtl::OUStringToOString(
+ rFullName.copy( RTL_CONSTASCII_LENGTH( "DAV:" ) ),
+ RTL_TEXTENCODING_UTF8 ) );
+ }
+ else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM(
+ "http://apache.org/dav/props/" ) ) == 0 )
+ {
+ rName.nspace = "http://apache.org/dav/props/";
+ rName.name
+ = strdup( rtl::OUStringToOString(
+ rFullName.copy(
+ RTL_CONSTASCII_LENGTH(
+ "http://apache.org/dav/props/" ) ),
+ RTL_TEXTENCODING_UTF8 ) );
+ }
+ else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM(
+ "http://ucb.openoffice.org/dav/props/" ) ) == 0 )
+ {
+ rName.nspace = "http://ucb.openoffice.org/dav/props/";
+ rName.name
+ = strdup( rtl::OUStringToOString(
+ rFullName.copy(
+ RTL_CONSTASCII_LENGTH(
+ "http://ucb.openoffice.org/dav/props/" ) ),
+ RTL_TEXTENCODING_UTF8 ) );
+ }
+ else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM(
+ "<prop:" ) ) == 0 )
+ {
+ // Support for 3rd party namespaces/props
+
+ rtl::OString aFullName
+ = rtl::OUStringToOString( rFullName, RTL_TEXTENCODING_UTF8 );
+
+ // Format: <prop:the_propname xmlns:prop="the_namespace">
+
+ sal_Int32 nStart = RTL_CONSTASCII_LENGTH( "<prop:" );
+ sal_Int32 nLen = aFullName.indexOf( ' ' ) - nStart;
+ rName.name = strdup( aFullName.copy( nStart, nLen ) );
+
+ nStart = aFullName.indexOf( '=', nStart + nLen ) + 2; // after ="
+ nLen = aFullName.getLength() - RTL_CONSTASCII_LENGTH( "\">" ) - nStart;
+ rName.nspace = strdup( aFullName.copy( nStart, nLen ) );
+ }
+ else
+ {
+ // Add our namespace to our own properties.
+ rName.nspace = "http://ucb.openoffice.org/dav/props/";
+ rName.name
+ = strdup( rtl::OUStringToOString( rFullName,
+ RTL_TEXTENCODING_UTF8 ) );
+ }
+}
+
+// -------------------------------------------------------------------
+// static
+void DAVProperties::createUCBPropName( const char * nspace,
+ const char * name,
+ rtl::OUString & rFullName )
+{
+ rtl::OUString aNameSpace
+ = rtl::OStringToOUString( nspace, RTL_TEXTENCODING_UTF8 );
+ rtl::OUString aName
+ = rtl::OStringToOUString( name, RTL_TEXTENCODING_UTF8 );
+
+ if ( !aNameSpace.getLength() )
+ {
+ // Some servers send XML without proper namespaces. Assume "DAV:"
+ // in this case, if name is a well-known dav property name.
+ // Although this is not 100% correct, it solves many problems.
+
+ if ( DAVProperties::RESOURCETYPE.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::SUPPORTEDLOCK.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::LOCKDISCOVERY.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::CREATIONDATE.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::DISPLAYNAME.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::GETCONTENTLANGUAGE.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::GETCONTENTLENGTH.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::GETCONTENTTYPE.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::GETETAG.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::GETLASTMODIFIED.matchIgnoreAsciiCase( aName, 4 ) ||
+ DAVProperties::SOURCE.matchIgnoreAsciiCase( aName, 4 ) )
+ aNameSpace = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DAV:" ) );
+ }
+
+ // Note: Concatenating strings BEFORE comparing against known namespaces
+ // is important. See RFC 2815 ( 23.4.2 Meaning of Qualified Names ).
+ rFullName = aNameSpace;
+ rFullName += aName;
+
+ if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM(
+ "DAV:" ) ) == 0 )
+ {
+ // Okay, Just concat strings.
+ }
+ else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM(
+ "http://apache.org/dav/props/" ) ) == 0 )
+ {
+ // Okay, Just concat strings.
+ }
+ else if ( rFullName.compareToAscii( RTL_CONSTASCII_STRINGPARAM(
+ "http://ucb.openoffice.org/dav/props/" ) ) == 0 )
+ {
+ // Remove namespace from our own properties.
+ rFullName = rFullName.copy(
+ RTL_CONSTASCII_LENGTH(
+ "http://ucb.openoffice.org/dav/props/" ) );
+ }
+ else
+ {
+ // Create property name that encodes, namespace and name ( XML ).
+ rFullName = rtl::OUString::createFromAscii( "<prop:" );
+ rFullName += aName;
+ rFullName += rtl::OUString::createFromAscii( " xmlns:prop=\"" );
+ rFullName += aNameSpace;
+ rFullName += rtl::OUString::createFromAscii( "\">" );
+ }
+}
+
+// -------------------------------------------------------------------
+// static
+bool DAVProperties::isUCBDeadProperty( const NeonPropName & rName )
+{
+ return ( rName.nspace &&
+ ( rtl_str_compareIgnoreAsciiCase(
+ rName.nspace, "http://ucb.openoffice.org/dav/props/" )
+ == 0 ) );
+}
diff --git a/ucb/source/ucp/webdav/DAVProperties.hxx b/ucb/source/ucp/webdav/DAVProperties.hxx
new file mode 100644
index 000000000000..46effc84697c
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVProperties.hxx
@@ -0,0 +1,62 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DAVPROPERTIES_HXX_
+#define _DAVPROPERTIES_HXX_
+
+#include <rtl/ustring.hxx>
+#include "NeonTypes.hxx"
+
+namespace webdav_ucp
+{
+
+struct DAVProperties
+{
+ static const ::rtl::OUString CREATIONDATE;
+ static const ::rtl::OUString DISPLAYNAME;
+ static const ::rtl::OUString GETCONTENTLANGUAGE;
+ static const ::rtl::OUString GETCONTENTLENGTH;
+ static const ::rtl::OUString GETCONTENTTYPE;
+ static const ::rtl::OUString GETETAG;
+ static const ::rtl::OUString GETLASTMODIFIED;
+ static const ::rtl::OUString LOCKDISCOVERY;
+ static const ::rtl::OUString RESOURCETYPE;
+ static const ::rtl::OUString SOURCE;
+ static const ::rtl::OUString SUPPORTEDLOCK;
+ static const ::rtl::OUString EXECUTABLE;
+
+ static void createNeonPropName( const rtl::OUString & rFullName,
+ NeonPropName & rName );
+ static void createUCBPropName ( const char * nspace,
+ const char * name,
+ rtl::OUString & rFullName );
+
+ static bool isUCBDeadProperty( const NeonPropName & rName );
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVPROPERTIES_HXX_
diff --git a/ucb/source/ucp/webdav/DAVRequestEnvironment.hxx b/ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
new file mode 100644
index 000000000000..96e3faaff62f
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVRequestEnvironment.hxx
@@ -0,0 +1,62 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DAVREQUESTENVIRONMENT_HXX_
+#define _DAVREQUESTENVIRONMENT_HXX_
+
+#include <vector>
+#include <rtl/ref.hxx>
+#include "DAVAuthListener.hxx"
+
+namespace webdav_ucp
+{
+ typedef std::pair< rtl::OUString, rtl::OUString > DAVRequestHeader;
+ typedef std::vector< DAVRequestHeader > DAVRequestHeaders;
+
+struct DAVRequestEnvironment
+{
+ rtl::OUString m_aRequestURI;
+ rtl::Reference< DAVAuthListener > m_xAuthListener;
+// rtl::Reference< DAVStatusListener > m_xStatusListener;
+// rtl::Reference< DAVProgressListener > m_xStatusListener;
+ DAVRequestHeaders m_aRequestHeaders;
+ uno::Reference< ucb::XCommandEnvironment > m_xEnv;
+
+DAVRequestEnvironment( const rtl::OUString & rRequestURI,
+ const rtl::Reference< DAVAuthListener > & xListener,
+ const DAVRequestHeaders & rRequestHeaders,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv)
+ : m_aRequestURI( rRequestURI ),
+ m_xAuthListener( xListener ),
+ m_aRequestHeaders( rRequestHeaders ),
+ m_xEnv( xEnv ){}
+
+ DAVRequestEnvironment() {}
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVREQUESTENVIRONMENT_HXX_
diff --git a/ucb/source/ucp/webdav/DAVResource.hxx b/ucb/source/ucp/webdav/DAVResource.hxx
new file mode 100644
index 000000000000..4a14dc262443
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVResource.hxx
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DAVRESOURCE_HXX_
+#define _DAVRESOURCE_HXX_
+
+#include <vector>
+
+#include "rtl/ustring.hxx"
+#include "com/sun/star/uno/Any.hxx"
+
+namespace webdav_ucp
+{
+
+struct DAVPropertyValue
+{
+ rtl::OUString Name;
+ com::sun::star::uno::Any Value;
+ bool IsCaseSensitive;
+
+ DAVPropertyValue() : IsCaseSensitive( true ) {}
+};
+
+struct DAVResource
+{
+ ::rtl::OUString uri;
+ std::vector< DAVPropertyValue > properties;
+
+ DAVResource() {}
+ DAVResource( const ::rtl::OUString & inUri ) : uri( inUri ) {}
+};
+
+struct DAVResourceInfo
+{
+ ::rtl::OUString uri;
+ std::vector < ::rtl::OUString > properties;
+
+ DAVResourceInfo( const ::rtl::OUString & inUri ) : uri( inUri ) {}
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVRESOURCE_HXX_
diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.cxx b/ucb/source/ucp/webdav/DAVResourceAccess.cxx
new file mode 100644
index 000000000000..e4617b7b9ea7
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVResourceAccess.cxx
@@ -0,0 +1,1218 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include "osl/diagnose.h"
+
+#include "com/sun/star/task/XInteractionAbort.hpp"
+#include "com/sun/star/ucb/XWebDAVCommandEnvironment.hpp"
+
+#include "ucbhelper/simpleauthenticationrequest.hxx"
+#include "comphelper/seekableinput.hxx"
+
+#include "DAVAuthListenerImpl.hxx"
+#include "DAVResourceAccess.hxx"
+
+using namespace webdav_ucp;
+using namespace com::sun::star;
+
+//=========================================================================
+//=========================================================================
+//
+// DAVAuthListener_Impl Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+//=========================================================================
+// virtual
+int DAVAuthListener_Impl::authenticate(
+ const ::rtl::OUString & inRealm,
+ const ::rtl::OUString & inHostName,
+ ::rtl::OUString & inoutUserName,
+ ::rtl::OUString & outPassWord,
+ sal_Bool bCanUseSystemCredentials )
+{
+ if ( m_xEnv.is() )
+ {
+ uno::Reference< task::XInteractionHandler > xIH
+ = m_xEnv->getInteractionHandler();
+
+ if ( xIH.is() )
+ {
+ // #102871# - Supply username and password from previous try.
+ // Password container service depends on this!
+ if ( inoutUserName.getLength() == 0 )
+ inoutUserName = m_aPrevUsername;
+
+ if ( outPassWord.getLength() == 0 )
+ outPassWord = m_aPrevPassword;
+
+ rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
+ = new ucbhelper::SimpleAuthenticationRequest(
+ m_aURL, inHostName, inRealm, inoutUserName,
+ outPassWord, ::rtl::OUString(),
+ true /*bAllowPersistentStoring*/,
+ bCanUseSystemCredentials );
+ xIH->handle( xRequest.get() );
+
+ rtl::Reference< ucbhelper::InteractionContinuation > xSelection
+ = xRequest->getSelection();
+
+ if ( xSelection.is() )
+ {
+ // Handler handled the request.
+ uno::Reference< task::XInteractionAbort > xAbort(
+ xSelection.get(), uno::UNO_QUERY );
+ if ( !xAbort.is() )
+ {
+ const rtl::Reference<
+ ucbhelper::InteractionSupplyAuthentication > & xSupp
+ = xRequest->getAuthenticationSupplier();
+
+ sal_Bool bUseSystemCredentials = sal_False;
+
+ if ( bCanUseSystemCredentials )
+ bUseSystemCredentials
+ = xSupp->getUseSystemCredentials();
+
+ if ( bUseSystemCredentials )
+ {
+ // This is the (strange) way to tell neon to use
+ // system credentials.
+ inoutUserName = rtl::OUString();
+ outPassWord = rtl::OUString();
+ }
+ else
+ {
+ inoutUserName = xSupp->getUserName();
+ outPassWord = xSupp->getPassword();
+ }
+
+ // #102871# - Remember username and password.
+ m_aPrevUsername = inoutUserName;
+ m_aPrevPassword = outPassWord;
+
+ // go on.
+ return 0;
+ }
+ }
+ }
+ }
+ // Abort.
+ return -1;
+}
+
+//=========================================================================
+//=========================================================================
+//
+// DAVResourceAccess Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+//=========================================================================
+DAVResourceAccess::DAVResourceAccess(
+ const uno::Reference< lang::XMultiServiceFactory > & rSMgr,
+ rtl::Reference< DAVSessionFactory > const & rSessionFactory,
+ const rtl::OUString & rURL )
+: m_aURL( rURL ),
+ m_xSessionFactory( rSessionFactory ),
+ m_xSMgr( rSMgr )
+{
+}
+
+//=========================================================================
+DAVResourceAccess::DAVResourceAccess( const DAVResourceAccess & rOther )
+: m_aURL( rOther.m_aURL ),
+ m_aPath( rOther.m_aPath ),
+ m_xSession( rOther.m_xSession ),
+ m_xSessionFactory( rOther.m_xSessionFactory ),
+ m_xSMgr( rOther.m_xSMgr ),
+ m_aRedirectURIs( rOther.m_aRedirectURIs )
+{
+}
+
+//=========================================================================
+DAVResourceAccess & DAVResourceAccess::operator=(
+ const DAVResourceAccess & rOther )
+{
+ m_aURL = rOther.m_aURL;
+ m_aPath = rOther.m_aPath;
+ m_xSession = rOther.m_xSession;
+ m_xSessionFactory = rOther.m_xSessionFactory;
+ m_xSMgr = rOther.m_xSMgr;
+ m_aRedirectURIs = rOther.m_aRedirectURIs;
+
+ return *this;
+}
+
+#if 0 // currently not used, but please don't remove code
+//=========================================================================
+void DAVResourceAccess::OPTIONS(
+ DAVCapabilities & rCapabilities,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ bool bRetry;
+ int errorCount = 0;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii(
+ "OPTIONS" ),
+ aHeaders );
+
+ m_xSession->OPTIONS( getRequestURI(),
+ rCapabilities,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+#endif
+
+//=========================================================================
+void DAVResourceAccess::PROPFIND(
+ const Depth nDepth,
+ const std::vector< rtl::OUString > & rPropertyNames,
+ std::vector< DAVResource > & rResources,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii(
+ "PROPFIND" ),
+ aHeaders );
+
+ m_xSession->PROPFIND( getRequestURI(),
+ nDepth,
+ rPropertyNames,
+ rResources,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::PROPFIND(
+ const Depth nDepth,
+ std::vector< DAVResourceInfo > & rResInfo,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii(
+ "PROPFIND" ),
+ aHeaders );
+
+ m_xSession->PROPFIND( getRequestURI(),
+ nDepth,
+ rResInfo,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) ) ;
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::PROPPATCH(
+ const std::vector< ProppatchValue >& rValues,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii(
+ "PROPPATCH" ),
+ aHeaders );
+
+ m_xSession->PROPPATCH( getRequestURI(),
+ rValues,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::HEAD(
+ const std::vector< rtl::OUString > & rHeaderNames,
+ DAVResource & rResource,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "HEAD" ),
+ aHeaders );
+
+ m_xSession->HEAD( getRequestURI(),
+ rHeaderNames,
+ rResource,
+ 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::GET(
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ uno::Reference< io::XInputStream > xStream;
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "GET" ),
+ aHeaders );
+
+ xStream = m_xSession->GET( getRequestURI(),
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl(
+ xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+
+ return xStream;
+}
+
+//=========================================================================
+void DAVResourceAccess::GET(
+ uno::Reference< io::XOutputStream > & rStream,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "GET" ),
+ aHeaders );
+
+ m_xSession->GET( getRequestURI(),
+ rStream,
+ 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::GET(
+ const std::vector< rtl::OUString > & rHeaderNames,
+ DAVResource & rResource,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ uno::Reference< io::XInputStream > xStream;
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "GET" ),
+ aHeaders );
+
+ xStream = m_xSession->GET( getRequestURI(),
+ rHeaderNames,
+ rResource,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl(
+ xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+
+ return xStream;
+}
+
+//=========================================================================
+void DAVResourceAccess::GET(
+ uno::Reference< io::XOutputStream > & rStream,
+ const std::vector< rtl::OUString > & rHeaderNames,
+ DAVResource & rResource,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ bool bRetry;
+ int errorCount = 0;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "GET" ),
+ aHeaders );
+
+ m_xSession->GET( getRequestURI(),
+ rStream,
+ rHeaderNames,
+ rResource,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::abort()
+ throw( DAVException )
+{
+ // 17.11.09 (tkr): abort currently disabled caused by issue i106766
+ // initialize();
+ // m_xSession->abort();
+ OSL_TRACE( "Not implemented. -> #i106766#" );
+}
+
+//=========================================================================
+namespace {
+
+ void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
+ throw( DAVException )
+ {
+ try
+ {
+ uno::Reference< io::XSeekable > xSeekable(
+ rStream, uno::UNO_QUERY );
+ if ( xSeekable.is() )
+ {
+ xSeekable->seek( 0 );
+ return;
+ }
+ }
+ catch ( lang::IllegalArgumentException const & )
+ {
+ }
+ catch ( io::IOException const & )
+ {
+ }
+
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+ }
+
+} // namespace
+
+//=========================================================================
+void DAVResourceAccess::PUT(
+ const uno::Reference< io::XInputStream > & rStream,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ // Make stream seekable, if it not. Needed, if request must be retried.
+ uno::Reference< io::XInputStream > xSeekableStream
+ = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
+ rStream, m_xSMgr );
+
+ int errorCount = 0;
+ bool bRetry = false;
+ do
+ {
+ if ( bRetry )
+ resetInputStream( xSeekableStream );
+
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "PUT" ),
+ aHeaders );
+
+ m_xSession->PUT( getRequestURI(),
+ xSeekableStream,
+ 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,
+ const uno::Reference< io::XInputStream > & rInputStream,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw ( DAVException )
+{
+ initialize();
+
+ // Make stream seekable, if it not. Needed, if request must be retried.
+ uno::Reference< io::XInputStream > xSeekableStream
+ = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
+ rInputStream, m_xSMgr );
+
+ uno::Reference< io::XInputStream > xStream;
+ int errorCount = 0;
+ bool bRetry = false;
+ do
+ {
+ if ( bRetry )
+ {
+ resetInputStream( xSeekableStream );
+ bRetry = false;
+ }
+
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "POST" ),
+ aHeaders );
+
+ xStream = m_xSession->POST( getRequestURI(),
+ rContentType,
+ rReferer,
+ xSeekableStream,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl(
+ xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+
+ if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
+ {
+ // #i74980# - Upon POST redirect, do a GET.
+ return GET( xEnv );
+ }
+ }
+ }
+ while ( bRetry );
+
+ return xStream;
+}
+
+//=========================================================================
+void DAVResourceAccess::POST(
+ const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer,
+ const uno::Reference< io::XInputStream > & rInputStream,
+ uno::Reference< io::XOutputStream > & rOutputStream,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw ( DAVException )
+{
+ initialize();
+
+ // Make stream seekable, if it not. Needed, if request must be retried.
+ uno::Reference< io::XInputStream > xSeekableStream
+ = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
+ rInputStream, m_xSMgr );
+
+ int errorCount = 0;
+ bool bRetry = false;
+ do
+ {
+ if ( bRetry )
+ {
+ resetInputStream( xSeekableStream );
+ bRetry = false;
+ }
+
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "POST" ),
+ aHeaders );
+
+ m_xSession->POST( getRequestURI(),
+ rContentType,
+ rReferer,
+ xSeekableStream,
+ rOutputStream,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+
+ if ( e.getError() == DAVException::DAV_HTTP_REDIRECT )
+ {
+ // #i74980# - Upon POST redirect, do a GET.
+ GET( rOutputStream, xEnv );
+ return;
+ }
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::MKCOL(
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "MKCOL" ),
+ aHeaders );
+
+ m_xSession->MKCOL( getRequestURI(),
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::COPY(
+ const ::rtl::OUString & rSourcePath,
+ const ::rtl::OUString & rDestinationURI,
+ sal_Bool bOverwrite,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "COPY" ),
+ aHeaders );
+
+ m_xSession->COPY( rSourcePath,
+ rDestinationURI,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ),
+ bOverwrite );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::MOVE(
+ const ::rtl::OUString & rSourcePath,
+ const ::rtl::OUString & rDestinationURI,
+ sal_Bool bOverwrite,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "MOVE" ),
+ aHeaders );
+
+ m_xSession->MOVE( rSourcePath,
+ rDestinationURI,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ),
+ bOverwrite );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::DESTROY(
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii(
+ "DESTROY" ),
+ aHeaders );
+
+ m_xSession->DESTROY( getRequestURI(),
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+// set new lock.
+void DAVResourceAccess::LOCK(
+ ucb::Lock & inLock,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "LOCK" ),
+ aHeaders );
+
+ m_xSession->LOCK( getRequestURI(),
+ inLock,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+#if 0 // currently not used, but please don't remove code
+//=========================================================================
+// refresh existing lock.
+sal_Int64 DAVResourceAccess::LOCK(
+ sal_Int64 nTimeout,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException )
+{
+ initialize();
+
+ sal_Int64 nNewTimeout = 0;
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "LOCK" ),
+ aHeaders );
+
+ nNewTimeout = m_xSession->LOCK( getRequestURI(),
+ nTimeout,
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl(
+ xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+
+ return nNewTimeout;
+}
+#endif
+
+//=========================================================================
+void DAVResourceAccess::UNLOCK(
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException )
+{
+ initialize();
+
+ int errorCount = 0;
+ bool bRetry;
+ do
+ {
+ bRetry = false;
+ try
+ {
+ DAVRequestHeaders aHeaders;
+ getUserRequestHeaders( xEnv,
+ getRequestURI(),
+ rtl::OUString::createFromAscii( "UNLOCK" ),
+ aHeaders );
+
+ m_xSession->UNLOCK( getRequestURI(),
+ DAVRequestEnvironment(
+ getRequestURI(),
+ new DAVAuthListener_Impl( xEnv, m_aURL ),
+ aHeaders, xEnv ) );
+ }
+ catch ( DAVException & e )
+ {
+ errorCount++;
+ bRetry = handleException( e, errorCount );
+ if ( !bRetry )
+ throw;
+ }
+ }
+ while ( bRetry );
+}
+
+//=========================================================================
+void DAVResourceAccess::setURL( const rtl::OUString & rNewURL )
+ throw( DAVException )
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_aURL = rNewURL;
+ m_aPath = rtl::OUString(); // Next initialize() will create new session.
+}
+
+//=========================================================================
+// init dav session and path
+void DAVResourceAccess::initialize()
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ if ( m_aPath.getLength() == 0 )
+ {
+ NeonUri aURI( m_aURL );
+ rtl::OUString aPath( aURI.GetPath() );
+
+ /* #134089# - Check URI */
+ if ( !aPath.getLength() )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ /* #134089# - Check URI */
+ if ( !aURI.GetHost().getLength() )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL ) )
+ {
+ m_xSession.clear();
+
+ // create new webdav session
+ m_xSession
+ = m_xSessionFactory->createDAVSession( m_aURL, m_xSMgr );
+
+ if ( !m_xSession.is() )
+ return;
+ }
+
+ // Own URI is needed for redirect cycle detection.
+ m_aRedirectURIs.push_back( aURI );
+
+ // Success.
+ m_aPath = aPath;
+
+ // Not only the path has to be encoded
+ m_aURL = aURI.GetURI();
+ }
+}
+
+//=========================================================================
+const rtl::OUString & DAVResourceAccess::getRequestURI() const
+{
+ OSL_ENSURE( m_xSession.is(),
+ "DAVResourceAccess::getRequestURI - Not initialized!" );
+
+ // In case a proxy is used we have to use the absolute URI for a request.
+ if ( m_xSession->UsesProxy() )
+ return m_aURL;
+
+ return m_aPath;
+}
+
+//=========================================================================
+// static
+void DAVResourceAccess::getUserRequestHeaders(
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv,
+ const rtl::OUString & rURI,
+ const rtl::OUString & rMethod,
+ DAVRequestHeaders & rRequestHeaders )
+{
+ if ( xEnv.is() )
+ {
+ uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
+ xEnv, uno::UNO_QUERY );
+
+ if ( xDAVEnv.is() )
+ {
+ uno::Sequence< beans::NamedValue > aRequestHeaders
+ = xDAVEnv->getUserRequestHeaders( rURI, rMethod );
+
+ for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n )
+ {
+ rtl::OUString aValue;
+ sal_Bool isString = aRequestHeaders[ n ].Value >>= aValue;
+
+ if ( !isString )
+ {
+ OSL_ENSURE( isString,
+ "DAVResourceAccess::getUserRequestHeaders :"
+ "Value is not a string! Ignoring..." );
+ }
+
+ rRequestHeaders.push_back(
+ DAVRequestHeader( aRequestHeaders[ n ].Name, aValue ) );
+ }
+ }
+ }
+}
+
+//=========================================================================
+sal_Bool DAVResourceAccess::detectRedirectCycle(
+ const rtl::OUString& rRedirectURL )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ NeonUri aUri( rRedirectURL );
+
+ std::vector< NeonUri >::const_iterator it = m_aRedirectURIs.begin();
+ std::vector< NeonUri >::const_iterator end = m_aRedirectURIs.end();
+
+ while ( it != end )
+ {
+ if ( aUri == (*it) )
+ return sal_True;
+
+ it++;
+ }
+
+ return sal_False;
+}
+
+//=========================================================================
+void DAVResourceAccess::resetUri()
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ if ( m_aRedirectURIs.size() > 0 )
+ {
+ std::vector< NeonUri >::const_iterator it = m_aRedirectURIs.begin();
+
+ NeonUri aUri( (*it) );
+ m_aRedirectURIs.clear();
+ setURL ( aUri.GetURI() );
+ initialize();
+ }
+}
+
+//=========================================================================
+sal_Bool DAVResourceAccess::handleException( DAVException & e, int errorCount )
+ throw ( DAVException )
+{
+ switch ( e.getError() )
+ {
+ case DAVException::DAV_HTTP_REDIRECT:
+ if ( !detectRedirectCycle( e.getData() ) )
+ {
+ // set new URL and path.
+ setURL( e.getData() );
+ initialize();
+ return sal_True;
+ }
+ return sal_False;
+ // --> tkr #67048# copy & paste images doesn't display.
+ // if we have a bad connection try again. Up to three times.
+ case DAVException::DAV_HTTP_ERROR:
+ // retry up to three times, if not a client-side error.
+ if ( ( e.getStatus() < 400 || e.getStatus() >= 500 ) &&
+ errorCount < 3 )
+ {
+ return sal_True;
+ }
+ return sal_False;
+ // <--
+ // --> tkr: if connection has said retry then retry!
+ case DAVException::DAV_HTTP_RETRY:
+ return sal_True;
+ // <--
+ default:
+ return sal_False; // Abort
+ }
+}
diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.hxx b/ucb/source/ucp/webdav/DAVResourceAccess.hxx
new file mode 100644
index 000000000000..53a98847078b
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVResourceAccess.hxx
@@ -0,0 +1,251 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DAVRESOURCEACCESS_HXX_
+#define _DAVRESOURCEACCESS_HXX_
+
+#include <vector>
+#include <rtl/ustring.hxx>
+#include <rtl/ref.hxx>
+#include <osl/mutex.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/ucb/Lock.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include "DAVAuthListener.hxx"
+#include "DAVException.hxx"
+#include "DAVSession.hxx"
+#include "DAVResource.hxx"
+#include "DAVTypes.hxx"
+#include "NeonUri.hxx"
+
+namespace webdav_ucp
+{
+
+class DAVSessionFactory;
+
+class DAVResourceAccess
+{
+ osl::Mutex m_aMutex;
+ rtl::OUString m_aURL;
+ rtl::OUString m_aPath;
+ rtl::Reference< DAVSession > m_xSession;
+ rtl::Reference< DAVSessionFactory > m_xSessionFactory;
+ com::sun::star::uno::Reference<
+ com::sun::star::lang::XMultiServiceFactory > m_xSMgr;
+ std::vector< NeonUri > m_aRedirectURIs;
+
+public:
+ DAVResourceAccess() : m_xSessionFactory( 0 ) {}
+ DAVResourceAccess( const com::sun::star::uno::Reference<
+ com::sun::star::lang::XMultiServiceFactory > & rSMgr,
+ rtl::Reference<
+ DAVSessionFactory > const & rSessionFactory,
+ const rtl::OUString & rURL );
+ DAVResourceAccess( const DAVResourceAccess & rOther );
+
+ DAVResourceAccess & operator=( const DAVResourceAccess & rOther );
+
+ void setURL( const rtl::OUString & rNewURL )
+ throw ( DAVException );
+
+ void resetUri();
+
+ const rtl::OUString & getURL() const { return m_aURL; }
+
+ rtl::Reference< DAVSessionFactory > getSessionFactory() const
+ { return m_xSessionFactory; }
+
+ // DAV methods
+ //
+
+#if 0 // currently not used, but please don't remove code
+ void
+ OPTIONS( DAVCapabilities & rCapabilities,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+#endif
+
+ // allprop & named
+ void
+ PROPFIND( const Depth nDepth,
+ const std::vector< rtl::OUString > & rPropertyNames,
+ std::vector< DAVResource > & rResources,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ // propnames
+ void
+ PROPFIND( const Depth nDepth,
+ std::vector< DAVResourceInfo > & rResInfo,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ void
+ PROPPATCH( const std::vector< ProppatchValue > & rValues,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& xEnv )
+ throw ( DAVException );
+
+ void
+ HEAD( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
+ DAVResource & rResource,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& xEnv )
+ throw ( DAVException );
+
+ com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ GET( const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ void
+ GET( com::sun::star::uno::Reference<
+ com::sun::star::io::XOutputStream > & rStream,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ GET( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
+ DAVResource & rResource,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ void
+ GET( com::sun::star::uno::Reference<
+ com::sun::star::io::XOutputStream > & rStream,
+ const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all'
+ DAVResource & rResource,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ void
+ PUT( const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & rStream,
+ 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,
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & rInputStream,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& xEnv )
+ throw ( DAVException );
+
+ void
+ POST( const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer,
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & rInputStream,
+ com::sun::star::uno::Reference<
+ com::sun::star::io::XOutputStream > & rOutputStream,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& xEnv )
+ throw ( DAVException );
+
+ void
+ MKCOL( const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ void
+ COPY( const ::rtl::OUString & rSourcePath,
+ const ::rtl::OUString & rDestinationURI,
+ sal_Bool bOverwrite,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ void
+ MOVE( const ::rtl::OUString & rSourcePath,
+ const ::rtl::OUString & rDestinationURI,
+ sal_Bool bOverwrite,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ void
+ DESTROY( const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ // set new lock.
+ void
+ LOCK( com::sun::star::ucb::Lock & inLock,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw( DAVException );
+
+#if 0 // currently not used, but please don't remove code
+ // refresh existing lock.
+ sal_Int64
+ LOCK( sal_Int64 nTimeout,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+#endif
+
+ void
+ UNLOCK( const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw ( DAVException );
+
+ void
+ abort()
+ throw ( DAVException );
+
+ // helper
+ static void
+ getUserRequestHeaders(
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv,
+ const rtl::OUString & rURI,
+ const rtl::OUString & rMethod,
+ DAVRequestHeaders & rRequestHeaders );
+
+private:
+ const rtl::OUString & getRequestURI() const;
+ sal_Bool detectRedirectCycle( const rtl::OUString& rRedirectURL )
+ throw ( DAVException );
+ sal_Bool handleException( DAVException & e, int errorCount )
+ throw ( DAVException );
+ void initialize()
+ throw ( DAVException );
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVRESOURCEACCESS_HXX_
diff --git a/ucb/source/ucp/webdav/DAVSession.hxx b/ucb/source/ucp/webdav/DAVSession.hxx
new file mode 100644
index 000000000000..4ea24f372c12
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVSession.hxx
@@ -0,0 +1,219 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DAVSESSION_HXX_
+#define _DAVSESSION_HXX_
+
+#include <memory>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include "DAVException.hxx"
+#include "DAVProperties.hxx"
+#include "DAVResource.hxx"
+#include "DAVSessionFactory.hxx"
+#include "DAVTypes.hxx"
+#include "DAVRequestEnvironment.hxx"
+
+namespace com { namespace sun { namespace star { namespace ucb {
+ struct Lock;
+} } } }
+
+namespace webdav_ucp
+{
+
+class DAVAuthListener;
+
+class DAVSession
+{
+public:
+ inline void acquire() SAL_THROW(())
+ {
+ osl_incrementInterlockedCount( &m_nRefCount );
+ }
+
+ void release() SAL_THROW(())
+ {
+ if ( osl_decrementInterlockedCount( &m_nRefCount ) == 0 )
+ {
+ m_xFactory->releaseElement( this );
+ delete this;
+ }
+ }
+
+ virtual sal_Bool CanUse( const ::rtl::OUString & inPath ) = 0;
+
+ virtual sal_Bool UsesProxy() = 0;
+
+ // DAV methods
+ //
+
+ virtual void OPTIONS( const ::rtl::OUString & inPath,
+ DAVCapabilities & outCapabilities,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ // allprop & named
+ virtual void PROPFIND( const ::rtl::OUString & inPath,
+ const Depth inDepth,
+ const std::vector< ::rtl::OUString > & inPropertyNames,
+ std::vector< DAVResource > & ioResources,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ // propnames
+ virtual void PROPFIND( const ::rtl::OUString & inPath,
+ const Depth inDepth,
+ std::vector< DAVResourceInfo > & ioResInfo,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ virtual void PROPPATCH( const ::rtl::OUString & inPath,
+ const std::vector< ProppatchValue > & inValues,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ virtual void HEAD( const ::rtl::OUString & inPath,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ GET( const ::rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ virtual void GET( const ::rtl::OUString & inPath,
+ com::sun::star::uno::Reference<
+ com::sun::star::io::XOutputStream >& o,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ GET( const ::rtl::OUString & inPath,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ virtual void
+ GET( const ::rtl::OUString & inPath,
+ com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& o,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ virtual void PUT( const ::rtl::OUString & inPath,
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream >& s,
+ 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,
+ const rtl::OUString & rReferer,
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & inInputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException ) = 0;
+
+ virtual void POST( const rtl::OUString & inPath,
+ const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer,
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & inInputStream,
+ com::sun::star::uno::Reference<
+ com::sun::star::io::XOutputStream > & oOutputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException ) = 0;
+
+ virtual void MKCOL( const ::rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ virtual void COPY( const ::rtl::OUString & inSource,
+ const ::rtl::OUString & inDestination,
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool inOverwrite = false )
+ throw( DAVException ) = 0;
+
+ virtual void MOVE( const ::rtl::OUString & inSource,
+ const ::rtl::OUString & inDestination,
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool inOverwrite = false )
+ throw( DAVException ) = 0;
+
+ virtual void DESTROY( const ::rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException ) = 0;
+
+ // set new lock.
+ virtual void LOCK( const ::rtl::OUString & inPath,
+ com::sun::star::ucb::Lock & inLock,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException ) = 0;
+
+ // refresh existing lock.
+ virtual sal_Int64 LOCK( const ::rtl::OUString & inPath,
+ sal_Int64 nTimeout,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException ) = 0;
+
+ virtual void UNLOCK( const ::rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException ) = 0;
+
+ virtual void abort()
+ throw( DAVException ) = 0;
+
+protected:
+ rtl::Reference< DAVSessionFactory > m_xFactory;
+
+ DAVSession( rtl::Reference< DAVSessionFactory > const & rFactory )
+ : m_xFactory( rFactory ), m_nRefCount( 0 ) {}
+
+ virtual ~DAVSession() {}
+
+private:
+ DAVSessionFactory::Map::iterator m_aContainerIt;
+ oslInterlockedCount m_nRefCount;
+
+ friend class DAVSessionFactory;
+#if defined WNT && _MSC_VER < 1310
+ friend struct std::auto_ptr< DAVSession >;
+ // work around compiler bug...
+#else // WNT
+ friend class std::auto_ptr< DAVSession >;
+#endif // WNT
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVSESSION_HXX_
diff --git a/ucb/source/ucp/webdav/DAVSessionFactory.cxx b/ucb/source/ucp/webdav/DAVSessionFactory.cxx
new file mode 100644
index 000000000000..86d513f23fd6
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVSessionFactory.cxx
@@ -0,0 +1,106 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+#include "DAVSessionFactory.hxx"
+#include "NeonSession.hxx"
+#include "NeonUri.hxx"
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+using namespace webdav_ucp;
+using namespace com::sun::star;
+
+DAVSessionFactory::~DAVSessionFactory()
+{
+}
+
+rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession(
+ const ::rtl::OUString & inUri,
+ const uno::Reference< lang::XMultiServiceFactory > & rxSMgr )
+ throw( DAVException )
+{
+ m_xMSF = rxSMgr;
+
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_xProxyDecider.get() )
+ m_xProxyDecider.reset( new ucbhelper::InternetProxyDecider( rxSMgr ) );
+
+ Map::iterator aIt( m_aMap.begin() );
+ Map::iterator aEnd( m_aMap.end() );
+
+ while ( aIt != aEnd )
+ {
+ if ( (*aIt).second->CanUse( inUri ) )
+ break;
+
+ ++aIt;
+ }
+
+ if ( aIt == aEnd )
+ {
+ NeonUri aURI( inUri );
+
+ std::auto_ptr< DAVSession > xElement(
+ new NeonSession( this, inUri, *m_xProxyDecider.get() ) );
+
+ aIt = m_aMap.insert( Map::value_type( inUri, xElement.get() ) ).first;
+ aIt->second->m_aContainerIt = aIt;
+ xElement.release();
+ return aIt->second;
+ }
+ else if ( osl_incrementInterlockedCount( &aIt->second->m_nRefCount ) > 1 )
+ {
+ rtl::Reference< DAVSession > xElement( aIt->second );
+ osl_decrementInterlockedCount( &aIt->second->m_nRefCount );
+ return xElement;
+ }
+ else
+ {
+ osl_decrementInterlockedCount( &aIt->second->m_nRefCount );
+ aIt->second->m_aContainerIt = m_aMap.end();
+
+ // If URL scheme is different from http or https we definitely
+ // have to use a proxy and therefore can optimize the getProxy
+ // call a little:
+ NeonUri aURI( inUri );
+
+ aIt->second = new NeonSession( this, inUri, *m_xProxyDecider.get() );
+ aIt->second->m_aContainerIt = aIt;
+ return aIt->second;
+ }
+}
+
+void DAVSessionFactory::releaseElement( DAVSession * pElement ) SAL_THROW(())
+{
+ OSL_ASSERT( pElement );
+ osl::MutexGuard aGuard( m_aMutex );
+ if ( pElement->m_aContainerIt != m_aMap.end() )
+ m_aMap.erase( pElement->m_aContainerIt );
+}
+
diff --git a/ucb/source/ucp/webdav/DAVSessionFactory.hxx b/ucb/source/ucp/webdav/DAVSessionFactory.hxx
new file mode 100644
index 000000000000..eb1f22ace925
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVSessionFactory.hxx
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _DAVSESSIONFACTORY_HXX_
+#define _DAVSESSIONFACTORY_HXX_
+
+#ifdef min
+#undef min // GNU libstdc++ <memory> includes <limit> which defines methods called min...
+#endif
+#include <map>
+#include <memory>
+#include <osl/mutex.hxx>
+#include <salhelper/simplereferenceobject.hxx>
+#include <rtl/ref.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <ucbhelper/proxydecider.hxx>
+#include "DAVException.hxx"
+
+using namespace com::sun::star;
+
+namespace com { namespace sun { namespace star { namespace lang {
+ class XMultiServiceFactory;
+} } } }
+
+namespace webdav_ucp
+{
+
+class DAVSession;
+
+class DAVSessionFactory : public salhelper::SimpleReferenceObject
+{
+public:
+ ~DAVSessionFactory() SAL_THROW(());
+
+ rtl::Reference< DAVSession >
+ createDAVSession( const ::rtl::OUString & inUri,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >&
+ rxSMgr )
+ throw( DAVException );
+
+ ::uno::Reference< ::lang::XMultiServiceFactory > getServiceFactory() { return m_xMSF; }
+private:
+ typedef std::map< rtl::OUString, DAVSession * > Map;
+
+ Map m_aMap;
+ osl::Mutex m_aMutex;
+ std::auto_ptr< ucbhelper::InternetProxyDecider > m_xProxyDecider;
+
+ ::uno::Reference< ::lang::XMultiServiceFactory > m_xMSF;
+
+ void releaseElement( DAVSession * pElement ) SAL_THROW(());
+
+ friend class DAVSession;
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVSESSIONFACTORY_HXX_
diff --git a/ucb/source/ucp/webdav/DAVTypes.hxx b/ucb/source/ucp/webdav/DAVTypes.hxx
new file mode 100644
index 000000000000..04da2fefed0c
--- /dev/null
+++ b/ucb/source/ucp/webdav/DAVTypes.hxx
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DAVTYPES_HXX_
+#define _DAVTYPES_HXX_
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+namespace webdav_ucp
+{
+/* RFC 2518
+
+15.1 Class 1
+
+ A class 1 compliant resource MUST meet all "MUST" requirements in all
+ sections of this document.
+
+ Class 1 compliant resources MUST return, at minimum, the value "1" in
+ the DAV header on all responses to the OPTIONS method.
+
+15.2 Class 2
+
+ A class 2 compliant resource MUST meet all class 1 requirements and
+ support the LOCK method, the supportedlock property, the
+ lockdiscovery property, the Time-Out response header and the Lock-
+ Token request header. A class "2" compliant resource SHOULD also
+ support the Time-Out request header and the owner XML element.
+
+ Class 2 compliant resources MUST return, at minimum, the values "1"
+ and "2" in the DAV header on all responses to the OPTIONS method.
+*/
+
+struct DAVCapabilities
+{
+ bool class1;
+ bool class2;
+ bool executable; // supports "executable" property (introduced by mod_dav)
+
+ DAVCapabilities() : class1( false ), class2( false ), executable( false ) {}
+};
+
+enum Depth { DAVZERO = 0, DAVONE = 1, DAVINFINITY = -1 };
+
+enum ProppatchOperation { PROPSET = 0, PROPREMOVE = 1 };
+
+struct ProppatchValue
+{
+ ProppatchOperation operation;
+ rtl::OUString name;
+ com::sun::star::uno::Any value;
+
+ ProppatchValue( const ProppatchOperation o,
+ const rtl::OUString & n,
+ const com::sun::star::uno::Any & v )
+ : operation( o ), name( n ), value( v ) {}
+};
+
+} // namespace webdav_ucp
+
+#endif // _DAVTYPES_HXX_
diff --git a/ucb/source/ucp/webdav/DateTimeHelper.cxx b/ucb/source/ucp/webdav/DateTimeHelper.cxx
new file mode 100644
index 000000000000..41caac39f64b
--- /dev/null
+++ b/ucb/source/ucp/webdav/DateTimeHelper.cxx
@@ -0,0 +1,270 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <stdio.h>
+#include <osl/time.h>
+#include <com/sun/star/util/DateTime.hpp>
+#include "DateTimeHelper.hxx"
+
+using namespace com::sun::star::util;
+using namespace rtl;
+
+using namespace webdav_ucp;
+
+bool DateTimeHelper::ISO8601_To_DateTime (const OUString& s,
+ DateTime& dateTime)
+{
+ OString aDT (s.getStr(), s.getLength(), RTL_TEXTENCODING_ASCII_US);
+
+ int year, month, day, hours, minutes, off_hours, off_minutes, fix;
+ double seconds;
+
+ // 2001-01-01T12:30:00Z
+ int n = sscanf( aDT.getStr(), "%04d-%02d-%02dT%02d:%02d:%lfZ",
+ &year, &month, &day, &hours, &minutes, &seconds );
+ if ( n == 6 )
+ {
+ fix = 0;
+ }
+ else
+ {
+ // 2001-01-01T12:30:00+03:30
+ n = sscanf( aDT.getStr(), "%04d-%02d-%02dT%02d:%02d:%lf+%02d:%02d",
+ &year, &month, &day, &hours, &minutes, &seconds,
+ &off_hours, &off_minutes );
+ if ( n == 8 )
+ {
+ fix = - off_hours * 3600 - off_minutes * 60;
+ }
+ else
+ {
+ // 2001-01-01T12:30:00-03:30
+ n = sscanf( aDT.getStr(), "%04d-%02d-%02dT%02d:%02d:%lf-%02d:%02d",
+ &year, &month, &day, &hours, &minutes, &seconds,
+ &off_hours, &off_minutes );
+ if ( n == 8 )
+ {
+ fix = off_hours * 3600 + off_minutes * 60;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ // Convert to local time...
+
+ oslDateTime aDateTime;
+ aDateTime.NanoSeconds = 0;
+ aDateTime.Seconds = sal::static_int_cast< sal_uInt16 >(seconds); // 0-59
+ aDateTime.Minutes = sal::static_int_cast< sal_uInt16 >(minutes); // 0-59
+ aDateTime.Hours = sal::static_int_cast< sal_uInt16 >(hours); // 0-23
+ aDateTime.Day = sal::static_int_cast< sal_uInt16 >(day); // 1-31
+ aDateTime.DayOfWeek = 0; // 0-6, 0 = Sunday
+ aDateTime.Month = sal::static_int_cast< sal_uInt16 >(month); // 1-12
+ aDateTime.Year = sal::static_int_cast< sal_uInt16 >(year);
+
+ TimeValue aTimeValue;
+ if ( osl_getTimeValueFromDateTime( &aDateTime, &aTimeValue ) )
+ {
+ aTimeValue.Seconds += fix;
+
+ if ( osl_getLocalTimeFromSystemTime( &aTimeValue, &aTimeValue ) )
+ {
+ if ( osl_getDateTimeFromTimeValue( &aTimeValue, &aDateTime ) )
+ {
+ dateTime.Year = aDateTime.Year;
+ dateTime.Month = aDateTime.Month;
+ dateTime.Day = aDateTime.Day;
+ dateTime.Hours = aDateTime.Hours;
+ dateTime.Minutes = aDateTime.Minutes;
+ dateTime.Seconds = aDateTime.Seconds;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/*
+sal_Int32 DateTimeHelper::convertDayToInt (const OUString& day)
+{
+ if (day.compareToAscii ("Sun") == 0)
+ return 0;
+ else if (day.compareToAscii ("Mon") == 0)
+ return 1;
+ else if (day.compareToAscii ("Tue") == 0)
+ return 2;
+ else if (day.compareToAscii ("Wed") == 0)
+ return 3;
+ else if (day.compareToAscii ("Thu") == 0)
+ return 4;
+ else if (day.compareToAscii ("Fri") == 0)
+ return 5;
+ else if (day.compareToAscii ("Sat") == 0)
+ return 6;
+ else
+ return -1;
+}
+*/
+
+sal_Int32 DateTimeHelper::convertMonthToInt (const OUString& month)
+{
+ if (month.compareToAscii ("Jan") == 0)
+ return 1;
+ else if (month.compareToAscii ("Feb") == 0)
+ return 2;
+ else if (month.compareToAscii ("Mar") == 0)
+ return 3;
+ else if (month.compareToAscii ("Apr") == 0)
+ return 4;
+ else if (month.compareToAscii ("May") == 0)
+ return 5;
+ else if (month.compareToAscii ("Jun") == 0)
+ return 6;
+ else if (month.compareToAscii ("Jul") == 0)
+ return 7;
+ else if (month.compareToAscii ("Aug") == 0)
+ return 8;
+ else if (month.compareToAscii ("Sep") == 0)
+ return 9;
+ else if (month.compareToAscii ("Oct") == 0)
+ return 10;
+ else if (month.compareToAscii ("Nov") == 0)
+ return 11;
+ else if (month.compareToAscii ("Dec") == 0)
+ return 12;
+ else
+ return 0;
+}
+
+bool DateTimeHelper::RFC2068_To_DateTime (const OUString& s,
+ DateTime& dateTime)
+{
+ int year;
+ int day;
+ int hours;
+ int minutes;
+ int seconds;
+ sal_Char string_month[3 + 1];
+ sal_Char string_day[3 + 1];
+
+ sal_Int32 found = s.indexOf (',');
+ if (found != -1)
+ {
+ OString aDT (s.getStr(), s.getLength(), RTL_TEXTENCODING_ASCII_US);
+
+ // RFC 1123
+ found = sscanf (aDT.getStr(), "%3s, %2d %3s %4d %2d:%2d:%2d GMT",
+ string_day, &day, string_month, &year, &hours, &minutes, &seconds);
+ if (found != 7)
+ {
+ // RFC 1036
+ found = sscanf (aDT.getStr(), "%3s, %2d-%3s-%2d %2d:%2d:%2d GMT",
+ string_day, &day, string_month, &year, &hours, &minutes, &seconds);
+ }
+ found = (found == 7) ? 1 : 0;
+ }
+ else
+ {
+ OString aDT (s.getStr(), s.getLength(), RTL_TEXTENCODING_ASCII_US);
+
+ // ANSI C's asctime () format
+ found = sscanf (aDT.getStr(), "%3s %3s %d %2d:%2d:%2d %4d",
+ string_day, string_month,
+ &day, &hours, &minutes, &seconds, &year);
+ found = (found == 7) ? 1 : 0;
+ }
+
+ if (found)
+ {
+ found = 0;
+
+ int month = DateTimeHelper::convertMonthToInt (
+ OUString::createFromAscii (string_month));
+ if (month)
+ {
+ // Convert to local time...
+
+ oslDateTime aDateTime;
+ aDateTime.NanoSeconds = 0;
+ aDateTime.Seconds = sal::static_int_cast< sal_uInt16 >(seconds);
+ // 0-59
+ aDateTime.Minutes = sal::static_int_cast< sal_uInt16 >(minutes);
+ // 0-59
+ aDateTime.Hours = sal::static_int_cast< sal_uInt16 >(hours);
+ // 0-23
+ aDateTime.Day = sal::static_int_cast< sal_uInt16 >(day);
+ // 1-31
+ aDateTime.DayOfWeek = 0; //dayofweek; // 0-6, 0 = Sunday
+ aDateTime.Month = sal::static_int_cast< sal_uInt16 >(month);
+ // 1-12
+ aDateTime.Year = sal::static_int_cast< sal_uInt16 >(year);
+
+ TimeValue aTimeValue;
+ if ( osl_getTimeValueFromDateTime( &aDateTime,
+ &aTimeValue ) )
+ {
+ if ( osl_getLocalTimeFromSystemTime( &aTimeValue,
+ &aTimeValue ) )
+ {
+ if ( osl_getDateTimeFromTimeValue( &aTimeValue,
+ &aDateTime ) )
+ {
+ dateTime.Year = aDateTime.Year;
+ dateTime.Month = aDateTime.Month;
+ dateTime.Day = aDateTime.Day;
+ dateTime.Hours = aDateTime.Hours;
+ dateTime.Minutes = aDateTime.Minutes;
+ dateTime.Seconds = aDateTime.Seconds;
+
+ found = 1;
+ }
+ }
+ }
+ }
+ }
+
+ return (found) ? true : false;
+}
+
+bool DateTimeHelper::convert (const OUString& s, DateTime& dateTime)
+{
+ if (ISO8601_To_DateTime (s, dateTime))
+ return true;
+ else if (RFC2068_To_DateTime (s, dateTime))
+ return true;
+ else
+ return false;
+}
+
diff --git a/ucb/source/ucp/webdav/DateTimeHelper.hxx b/ucb/source/ucp/webdav/DateTimeHelper.hxx
new file mode 100644
index 000000000000..c857457d0534
--- /dev/null
+++ b/ucb/source/ucp/webdav/DateTimeHelper.hxx
@@ -0,0 +1,63 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WEBDAV_DATETIME_HELPER_HXX
+#define _WEBDAV_DATETIME_HELPER_HXX
+
+#include <sal/types.h>
+
+namespace com { namespace sun { namespace star { namespace util {
+ struct DateTime;
+} } } }
+
+namespace rtl {
+ class OUString;
+}
+
+namespace webdav_ucp
+{
+
+class DateTimeHelper
+{
+private:
+ static sal_Int32 convertMonthToInt (const ::rtl::OUString& );
+
+ static bool ISO8601_To_DateTime (const ::rtl::OUString&,
+ ::com::sun::star::util::DateTime& );
+
+ static bool RFC2068_To_DateTime (const ::rtl::OUString&,
+ ::com::sun::star::util::DateTime& );
+
+public:
+ static bool convert (const ::rtl::OUString&,
+ ::com::sun::star::util::DateTime& );
+};
+
+} // namespace webdav_ucp
+
+#endif
+
diff --git a/ucb/source/ucp/webdav/LinkSequence.cxx b/ucb/source/ucp/webdav/LinkSequence.cxx
new file mode 100644
index 000000000000..39d8d9cecc38
--- /dev/null
+++ b/ucb/source/ucp/webdav/LinkSequence.cxx
@@ -0,0 +1,223 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <string.h>
+#include <ne_xml.h>
+
+#ifndef _LINKSEQUENCE_HXX_
+#include "LinkSequence.hxx"
+#endif
+
+using namespace webdav_ucp;
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////
+
+struct LinkSequenceParseContext
+{
+ ucb::Link * pLink;
+ bool hasSource;
+ bool hasDestination;
+
+ LinkSequenceParseContext()
+ : pLink( 0 ), hasSource( false ), hasDestination( false ) {}
+ ~LinkSequenceParseContext() { delete pLink; }
+};
+
+#define STATE_TOP (1)
+
+#define STATE_LINK (STATE_TOP)
+#define STATE_DST (STATE_TOP + 1)
+#define STATE_SRC (STATE_TOP + 2)
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LinkSequence_startelement_callback(
+ void *,
+ int parent,
+ const char * /*nspace*/,
+ const char *name,
+ const char ** )
+{
+ if ( name != 0 )
+ {
+ switch ( parent )
+ {
+ case NE_XML_STATEROOT:
+ if ( strcmp( name, "link" ) == 0 )
+ return STATE_LINK;
+ break;
+
+ case STATE_LINK:
+ if ( strcmp( name, "dst" ) == 0 )
+ return STATE_DST;
+ else if ( strcmp( name, "src" ) == 0 )
+ return STATE_SRC;
+ break;
+ }
+ }
+ return NE_XML_DECLINE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LinkSequence_chardata_callback(
+ void *userdata,
+ int state,
+ const char *buf,
+ size_t len )
+{
+ LinkSequenceParseContext * pCtx
+ = static_cast< LinkSequenceParseContext * >( userdata );
+ if ( !pCtx->pLink )
+ pCtx->pLink = new ucb::Link;
+
+ switch ( state )
+ {
+ case STATE_DST:
+ pCtx->pLink->Destination
+ = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
+ pCtx->hasDestination = true;
+ break;
+
+ case STATE_SRC:
+ pCtx->pLink->Source
+ = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
+ pCtx->hasSource = true;
+ break;
+ }
+ return 0; // zero to continue, non-zero to abort parsing
+}
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LinkSequence_endelement_callback(
+ void *userdata,
+ int state,
+ const char *,
+ const char * )
+{
+ LinkSequenceParseContext * pCtx
+ = static_cast< LinkSequenceParseContext * >( userdata );
+ if ( !pCtx->pLink )
+ pCtx->pLink = new ucb::Link;
+
+ switch ( state )
+ {
+ case STATE_LINK:
+ if ( !pCtx->hasDestination || !pCtx->hasSource )
+ return 1; // abort
+ break;
+ }
+ return 0; // zero to continue, non-zero to abort parsing
+}
+
+//////////////////////////////////////////////////////////////////////////
+// static
+bool LinkSequence::createFromXML( const rtl::OString & rInData,
+ uno::Sequence< ucb::Link > & rOutData )
+{
+ const sal_Int32 TOKEN_LENGTH = 7; // </link>
+ bool success = true;
+
+ // rInData may contain multiple <link>...</link> tags.
+ sal_Int32 nCount = 0;
+ sal_Int32 nStart = 0;
+ sal_Int32 nEnd = rInData.indexOf( "</link>" );
+ while ( nEnd > -1 )
+ {
+ ne_xml_parser * parser = ne_xml_create();
+ if ( !parser )
+ {
+ success = false;
+ break;
+ }
+
+ LinkSequenceParseContext aCtx;
+ ne_xml_push_handler( parser,
+ LinkSequence_startelement_callback,
+ LinkSequence_chardata_callback,
+ LinkSequence_endelement_callback,
+ &aCtx );
+
+ ne_xml_parse( parser,
+ rInData.getStr() + nStart,
+ nEnd - nStart + TOKEN_LENGTH );
+
+#if NEON_VERSION >= 0x0250
+ success = !ne_xml_failed( parser );
+#else
+ success = !!ne_xml_valid( parser );
+#endif
+
+ ne_xml_destroy( parser );
+
+ if ( !success )
+ break;
+
+ if ( aCtx.pLink )
+ {
+ nCount++;
+ if ( nCount > rOutData.getLength() )
+ rOutData.realloc( rOutData.getLength() + 1 );
+
+ rOutData[ nCount - 1 ] = *aCtx.pLink;
+ }
+
+ nStart = nEnd + TOKEN_LENGTH;
+ nEnd = rInData.indexOf( "</link>", nStart );
+ }
+
+ return success;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// static
+bool LinkSequence::toXML( const uno::Sequence< ucb::Link > & rInData,
+ rtl::OUString & rOutData )
+{
+ // <link><src>value</src><dst>value</dst></link><link><src>....
+
+ sal_Int32 nCount = rInData.getLength();
+ if ( nCount )
+ {
+ rtl::OUString aPre( rtl::OUString::createFromAscii( "<link><src>" ) );
+ rtl::OUString aMid( rtl::OUString::createFromAscii( "</src><dst>" ) );
+ rtl::OUString aEnd( rtl::OUString::createFromAscii( "</dst></link>" ) );
+
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ rOutData += aPre;
+ rOutData += rInData[ n ].Source;
+ rOutData += aMid;
+ rOutData += rInData[ n ].Destination;
+ rOutData += aEnd;
+ }
+ return true;
+ }
+ return false;
+}
diff --git a/ucb/source/ucp/webdav/LinkSequence.hxx b/ucb/source/ucp/webdav/LinkSequence.hxx
new file mode 100644
index 000000000000..49bf883f1099
--- /dev/null
+++ b/ucb/source/ucp/webdav/LinkSequence.hxx
@@ -0,0 +1,51 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _LINKSEQUENCE_HXX_
+#define _LINKKSEQUENCE_HXX_
+
+#include <rtl/string.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/ucb/Link.hpp>
+
+namespace webdav_ucp
+{
+
+class LinkSequence
+{
+public:
+ static bool createFromXML( const rtl::OString & rInData,
+ com::sun::star::uno::Sequence<
+ com::sun::star::ucb::Link > & rOutData );
+ static bool toXML( const com::sun::star::uno::Sequence<
+ com::sun::star::ucb::Link > & rInData,
+ rtl::OUString & rOutData );
+};
+
+}
+
+#endif /* _LINKSEQUENCE_HXX_ */
diff --git a/ucb/source/ucp/webdav/LockEntrySequence.cxx b/ucb/source/ucp/webdav/LockEntrySequence.cxx
new file mode 100644
index 000000000000..762170e7e057
--- /dev/null
+++ b/ucb/source/ucp/webdav/LockEntrySequence.cxx
@@ -0,0 +1,244 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <string.h>
+#include <ne_xml.h>
+#include "LockEntrySequence.hxx"
+
+using namespace webdav_ucp;
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////
+
+struct LockEntrySequenceParseContext
+{
+ ucb::LockEntry * pEntry;
+ bool hasScope;
+ bool hasType;
+
+ LockEntrySequenceParseContext()
+ : pEntry( 0 ), hasScope( false ), hasType( false ) {}
+ ~LockEntrySequenceParseContext() { delete pEntry; }
+};
+
+#define STATE_TOP (1)
+
+#define STATE_LOCKENTRY (STATE_TOP)
+#define STATE_LOCKSCOPE (STATE_TOP + 1)
+#define STATE_EXCLUSIVE (STATE_TOP + 2)
+#define STATE_SHARED (STATE_TOP + 3)
+#define STATE_LOCKTYPE (STATE_TOP + 4)
+#define STATE_WRITE (STATE_TOP + 5)
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LockEntrySequence_startelement_callback(
+ void *,
+ int parent,
+ const char * /*nspace*/,
+ const char *name,
+ const char ** )
+{
+ if ( name != 0 )
+ {
+ switch ( parent )
+ {
+ case NE_XML_STATEROOT:
+ if ( strcmp( name, "lockentry" ) == 0 )
+ return STATE_LOCKENTRY;
+ break;
+
+ case STATE_LOCKENTRY:
+ if ( strcmp( name, "lockscope" ) == 0 )
+ return STATE_LOCKSCOPE;
+ else if ( strcmp( name, "locktype" ) == 0 )
+ return STATE_LOCKTYPE;
+
+#define IIS_BUGS_WORKAROUND
+
+#ifdef IIS_BUGS_WORKAROUND
+ /* IIS (6) returns XML violating RFC 4918
+ for DAV:supportedlock property value.
+
+ <lockentry>
+ <write></write>
+ <shared></shared>
+ </lockentry>
+ <lockentry>
+ <write></write>
+ <exclusive></exclusive>
+ </lockentry>
+
+ Bother...
+ */
+ else if ( strcmp( name, "exclusive" ) == 0 )
+ return STATE_EXCLUSIVE;
+ else if ( strcmp( name, "shared" ) == 0 )
+ return STATE_SHARED;
+ else if ( strcmp( name, "write" ) == 0 )
+ return STATE_WRITE;
+#endif
+ break;
+
+ case STATE_LOCKSCOPE:
+ if ( strcmp( name, "exclusive" ) == 0 )
+ return STATE_EXCLUSIVE;
+ else if ( strcmp( name, "shared" ) == 0 )
+ return STATE_SHARED;
+ break;
+
+ case STATE_LOCKTYPE:
+ if ( strcmp( name, "write" ) == 0 )
+ return STATE_WRITE;
+ break;
+ }
+ }
+ return NE_XML_DECLINE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LockEntrySequence_chardata_callback(
+ void *,
+ int,
+ const char *,
+ size_t )
+{
+ return 0; // zero to continue, non-zero to abort parsing
+}
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LockEntrySequence_endelement_callback(
+ void *userdata,
+ int state,
+ const char *,
+ const char * )
+{
+ LockEntrySequenceParseContext * pCtx
+ = static_cast< LockEntrySequenceParseContext * >( userdata );
+ if ( !pCtx->pEntry )
+ pCtx->pEntry = new ucb::LockEntry;
+
+ switch ( state )
+ {
+ case STATE_EXCLUSIVE:
+ pCtx->pEntry->Scope = ucb::LockScope_EXCLUSIVE;
+ pCtx->hasScope = true;
+ break;
+
+ case STATE_SHARED:
+ pCtx->pEntry->Scope = ucb::LockScope_SHARED;
+ pCtx->hasScope = true;
+ break;
+
+ case STATE_WRITE:
+ pCtx->pEntry->Type = ucb::LockType_WRITE;
+ pCtx->hasType = true;
+ break;
+
+ case STATE_LOCKSCOPE:
+ if ( !pCtx->hasScope )
+ return 1; // abort
+ break;
+
+ case STATE_LOCKTYPE:
+ if ( !pCtx->hasType )
+ return 1; // abort
+ break;
+
+ case STATE_LOCKENTRY:
+ if ( !pCtx->hasType || !pCtx->hasType )
+ return 1; // abort
+ break;
+
+ default:
+ break;
+ }
+ return 0; // zero to continue, non-zero to abort parsing
+}
+
+//////////////////////////////////////////////////////////////////////////
+// static
+bool LockEntrySequence::createFromXML( const rtl::OString & rInData,
+ uno::Sequence<
+ ucb::LockEntry > & rOutData )
+{
+ const sal_Int32 TOKEN_LENGTH = 12; // </lockentry>
+ bool success = true;
+
+ // rInData may contain multiple <lockentry>...</lockentry> tags.
+ sal_Int32 nCount = 0;
+ sal_Int32 nStart = 0;
+ sal_Int32 nEnd = rInData.indexOf( "</lockentry>" );
+ while ( nEnd > -1 )
+ {
+ ne_xml_parser * parser = ne_xml_create();
+ if ( !parser )
+ {
+ success = false;
+ break;
+ }
+
+ LockEntrySequenceParseContext aCtx;
+ ne_xml_push_handler( parser,
+ LockEntrySequence_startelement_callback,
+ LockEntrySequence_chardata_callback,
+ LockEntrySequence_endelement_callback,
+ &aCtx );
+
+ ne_xml_parse( parser,
+ rInData.getStr() + nStart,
+ nEnd - nStart + TOKEN_LENGTH );
+
+#if NEON_VERSION >= 0x0250
+ success = !ne_xml_failed( parser );
+#else
+ success = !!ne_xml_valid( parser );
+#endif
+
+ ne_xml_destroy( parser );
+
+ if ( !success )
+ break;
+
+ if ( aCtx.pEntry )
+ {
+ nCount++;
+ if ( nCount > rOutData.getLength() )
+ rOutData.realloc( rOutData.getLength() + 2 );
+
+ rOutData[ nCount - 1 ] = *aCtx.pEntry;
+ }
+
+ nStart = nEnd + TOKEN_LENGTH;
+ nEnd = rInData.indexOf( "</lockentry>", nStart );
+ }
+
+ rOutData.realloc( nCount );
+ return success;
+}
diff --git a/ucb/source/ucp/webdav/LockEntrySequence.hxx b/ucb/source/ucp/webdav/LockEntrySequence.hxx
new file mode 100644
index 000000000000..12c407100ecf
--- /dev/null
+++ b/ucb/source/ucp/webdav/LockEntrySequence.hxx
@@ -0,0 +1,48 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _LOCKENTRYSEQUENCE_HXX_
+#define _LOCKENTRYSEQUENCE_HXX_
+
+#include <rtl/string.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/ucb/LockEntry.hpp>
+
+namespace webdav_ucp
+{
+
+class LockEntrySequence
+{
+public:
+ static bool createFromXML( const rtl::OString & rInData,
+ com::sun::star::uno::Sequence<
+ com::sun::star::ucb::LockEntry > & rOutData );
+};
+
+}
+
+#endif /* _LOCKENTRYSEQUENCE_HXX_ */
diff --git a/ucb/source/ucp/webdav/LockSequence.cxx b/ucb/source/ucp/webdav/LockSequence.cxx
new file mode 100644
index 000000000000..cd5f12708d58
--- /dev/null
+++ b/ucb/source/ucp/webdav/LockSequence.cxx
@@ -0,0 +1,351 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <string.h>
+#include <ne_xml.h>
+#include "LockSequence.hxx"
+
+using namespace webdav_ucp;
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////
+
+struct LockSequenceParseContext
+{
+ ucb::Lock * pLock;
+ bool hasLockScope;
+ bool hasLockType;
+ bool hasDepth;
+ bool hasHREF;
+ bool hasTimeout;
+
+ LockSequenceParseContext()
+ : pLock( 0 ), hasLockScope( false ), hasLockType( false ),
+ hasDepth( false ), hasHREF( false ), hasTimeout( false ) {}
+
+ ~LockSequenceParseContext() { delete pLock; }
+};
+
+#define STATE_TOP (1)
+
+#define STATE_ACTIVELOCK (STATE_TOP)
+#define STATE_LOCKSCOPE (STATE_TOP + 1)
+#define STATE_LOCKTYPE (STATE_TOP + 2)
+#define STATE_DEPTH (STATE_TOP + 3)
+#define STATE_OWNER (STATE_TOP + 4)
+#define STATE_TIMEOUT (STATE_TOP + 5)
+#define STATE_LOCKTOKEN (STATE_TOP + 6)
+#define STATE_EXCLUSIVE (STATE_TOP + 7)
+#define STATE_SHARED (STATE_TOP + 8)
+#define STATE_WRITE (STATE_TOP + 9)
+#define STATE_HREF (STATE_TOP + 10)
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LockSequence_startelement_callback(
+ void *,
+ int parent,
+ const char * /*nspace*/,
+ const char *name,
+ const char ** )
+{
+ if ( name != 0 )
+ {
+ switch ( parent )
+ {
+ case NE_XML_STATEROOT:
+ if ( strcmp( name, "activelock" ) == 0 )
+ return STATE_ACTIVELOCK;
+ break;
+
+ case STATE_ACTIVELOCK:
+ if ( strcmp( name, "lockscope" ) == 0 )
+ return STATE_LOCKSCOPE;
+ else if ( strcmp( name, "locktype" ) == 0 )
+ return STATE_LOCKTYPE;
+ else if ( strcmp( name, "depth" ) == 0 )
+ return STATE_DEPTH;
+ else if ( strcmp( name, "owner" ) == 0 )
+ return STATE_OWNER;
+ else if ( strcmp( name, "timeout" ) == 0 )
+ return STATE_TIMEOUT;
+ else if ( strcmp( name, "locktoken" ) == 0 )
+ return STATE_LOCKTOKEN;
+ break;
+
+ case STATE_LOCKSCOPE:
+ if ( strcmp( name, "exclusive" ) == 0 )
+ return STATE_EXCLUSIVE;
+ else if ( strcmp( name, "shared" ) == 0 )
+ return STATE_SHARED;
+ break;
+
+ case STATE_LOCKTYPE:
+ if ( strcmp( name, "write" ) == 0 )
+ return STATE_WRITE;
+ break;
+
+ case STATE_LOCKTOKEN:
+ if ( strcmp( name, "href" ) == 0 )
+ return STATE_HREF;
+ break;
+
+ case STATE_OWNER:
+ // owner elem contains ANY. Accept anything; no state change.
+ return STATE_OWNER;
+ }
+ }
+ return NE_XML_DECLINE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LockSequence_chardata_callback(
+ void *userdata,
+ int state,
+ const char *buf,
+ size_t len )
+{
+ LockSequenceParseContext * pCtx
+ = static_cast< LockSequenceParseContext * >( userdata );
+ if ( !pCtx->pLock )
+ pCtx->pLock = new ucb::Lock;
+
+ switch ( state )
+ {
+ case STATE_DEPTH:
+ if ( rtl_str_compareIgnoreAsciiCase_WithLength(
+ buf, len, "0", 1 ) == 0 )
+ {
+ pCtx->pLock->Depth = ucb::LockDepth_ZERO;
+ pCtx->hasDepth = true;
+ }
+ else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
+ buf, len, "1", 1 ) == 0 )
+ {
+ pCtx->pLock->Depth = ucb::LockDepth_ONE;
+ pCtx->hasDepth = true;
+ }
+ else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
+ buf, len, "infinity", 8 ) == 0 )
+ {
+ pCtx->pLock->Depth = ucb::LockDepth_INFINITY;
+ pCtx->hasDepth = true;
+ }
+ else
+ OSL_ENSURE( sal_False,
+ "LockSequence_chardata_callback - Unknown depth!" );
+ break;
+
+ case STATE_OWNER:
+ {
+ // collect raw XML data... (owner contains ANY)
+ rtl::OUString aValue;
+ pCtx->pLock->Owner >>= aValue;
+ aValue += rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
+ pCtx->pLock->Owner <<= aValue;
+ break;
+ }
+
+ case STATE_TIMEOUT:
+ //
+ // RFC2518, RFC2616:
+ //
+ // TimeType = ("Second-" DAVTimeOutVal | "Infinite" | Other)
+ // DAVTimeOutVal = 1*digit
+ // Other = "Extend" field-value
+ // field-value = *( field-content | LWS )
+ // field-content = <the OCTETs making up the field-value
+ // and consisting of either *TEXT or combinations
+ // of token, separators, and quoted-string>
+
+ if ( rtl_str_compareIgnoreAsciiCase_WithLength(
+ buf, len, "Infinite", 8 ) == 0 )
+ {
+ pCtx->pLock->Timeout = sal_Int64( -1 );
+ pCtx->hasTimeout = true;
+ }
+ else if ( rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ buf, len, "Second-", 7, 7 ) == 0 )
+ {
+ pCtx->pLock->Timeout
+ = rtl::OString( buf + 7, len - 7 ).toInt64();
+ pCtx->hasTimeout = true;
+ }
+// else if ( rtl_str_shortenedCompareIgnoreCase_WithLength(
+// buf, len, "Extend", 6, 6 ) == 0 )
+// {
+// @@@
+// }
+ else
+ {
+ pCtx->pLock->Timeout = sal_Int64( -1 );
+ pCtx->hasTimeout = true;
+ OSL_ENSURE( sal_False,
+ "LockSequence_chardata_callback - Unknown timeout!" );
+ }
+ break;
+
+ case STATE_HREF:
+ {
+ // collect hrefs.
+ sal_Int32 nPos = pCtx->pLock->LockTokens.getLength();
+ pCtx->pLock->LockTokens.realloc( nPos + 1 );
+ pCtx->pLock->LockTokens[ nPos ]
+ = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
+ pCtx->hasHREF = true;
+ break;
+ }
+
+ }
+ return 0; // zero to continue, non-zero to abort parsing
+}
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int LockSequence_endelement_callback(
+ void *userdata,
+ int state,
+ const char *,
+ const char * )
+{
+ LockSequenceParseContext * pCtx
+ = static_cast< LockSequenceParseContext * >( userdata );
+ if ( !pCtx->pLock )
+ pCtx->pLock = new ucb::Lock;
+
+ switch ( state )
+ {
+ case STATE_EXCLUSIVE:
+ pCtx->pLock->Scope = ucb::LockScope_EXCLUSIVE;
+ pCtx->hasLockScope = true;
+ break;
+
+ case STATE_SHARED:
+ pCtx->pLock->Scope = ucb::LockScope_SHARED;
+ pCtx->hasLockScope = true;
+ break;
+
+ case STATE_WRITE:
+ pCtx->pLock->Type = ucb::LockType_WRITE;
+ pCtx->hasLockType = true;
+ break;
+
+ case STATE_DEPTH:
+ if ( !pCtx->hasDepth )
+ return 1; // abort
+ break;
+
+ case STATE_HREF:
+ if ( !pCtx->hasHREF )
+ return 1; // abort
+ break;
+
+ case STATE_TIMEOUT:
+ if ( !pCtx->hasTimeout )
+ return 1; // abort
+ break;
+
+ case STATE_LOCKSCOPE:
+ if ( !pCtx->hasLockScope )
+ return 1; // abort
+ break;
+
+ case STATE_LOCKTYPE:
+ if ( !pCtx->hasLockType )
+ return 1; // abort
+ break;
+
+ case STATE_ACTIVELOCK:
+ if ( !pCtx->hasLockType || !pCtx->hasLockType || !pCtx->hasDepth )
+ return 1; // abort
+ break;
+
+ default:
+ break;
+ }
+ return 0; // zero to continue, non-zero to abort parsing
+}
+
+//////////////////////////////////////////////////////////////////////////
+// static
+bool LockSequence::createFromXML( const rtl::OString & rInData,
+ uno::Sequence< ucb::Lock > & rOutData )
+{
+ const sal_Int32 TOKEN_LENGTH = 13; // </activelock>
+ bool success = true;
+
+ // rInData may contain multiple <activelock>...</activelock> tags.
+ sal_Int32 nCount = 0;
+ sal_Int32 nStart = 0;
+ sal_Int32 nEnd = rInData.indexOf( "</activelock>" );
+ while ( nEnd > -1 )
+ {
+ ne_xml_parser * parser = ne_xml_create();
+ if ( !parser )
+ {
+ success = false;
+ break;
+ }
+
+ LockSequenceParseContext aCtx;
+ ne_xml_push_handler( parser,
+ LockSequence_startelement_callback,
+ LockSequence_chardata_callback,
+ LockSequence_endelement_callback,
+ &aCtx );
+
+ ne_xml_parse( parser,
+ rInData.getStr() + nStart,
+ nEnd - nStart + TOKEN_LENGTH );
+
+#if NEON_VERSION >= 0x0250
+ success = !ne_xml_failed( parser );
+#else
+ success = !!ne_xml_valid( parser );
+#endif
+
+ ne_xml_destroy( parser );
+
+ if ( !success )
+ break;
+
+ if ( aCtx.pLock )
+ {
+ nCount++;
+ if ( nCount > rOutData.getLength() )
+ rOutData.realloc( rOutData.getLength() + 1 );
+
+ rOutData[ nCount - 1 ] = *aCtx.pLock;
+ }
+
+ nStart = nEnd + TOKEN_LENGTH;
+ nEnd = rInData.indexOf( "</activelock>", nStart );
+ }
+
+ return success;
+}
diff --git a/ucb/source/ucp/webdav/LockSequence.hxx b/ucb/source/ucp/webdav/LockSequence.hxx
new file mode 100644
index 000000000000..85d4cdee77f5
--- /dev/null
+++ b/ucb/source/ucp/webdav/LockSequence.hxx
@@ -0,0 +1,48 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _LOCKSEQUENCE_HXX_
+#define _LOCKSEQUENCE_HXX_
+
+#include <rtl/string.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/ucb/Lock.hpp>
+
+namespace webdav_ucp
+{
+
+class LockSequence
+{
+public:
+ static bool createFromXML( const rtl::OString & rInData,
+ com::sun::star::uno::Sequence<
+ com::sun::star::ucb::Lock > & rOutData );
+};
+
+}
+
+#endif /* _LOCKSEQUENCE_HXX_ */
diff --git a/ucb/source/ucp/webdav/NeonHeadRequest.cxx b/ucb/source/ucp/webdav/NeonHeadRequest.cxx
new file mode 100644
index 000000000000..2880a86a727d
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonHeadRequest.cxx
@@ -0,0 +1,200 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+#include <osl/diagnose.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include "NeonHeadRequest.hxx"
+
+using namespace webdav_ucp;
+using namespace com::sun::star;
+
+namespace {
+
+#if NEON_VERSION >= 0x0250
+void process_headers(ne_request *req,
+ DAVResource &rResource,
+ const std::vector< ::rtl::OUString > &rHeaderNames)
+{
+ void *cursor = NULL;
+ const char *name, *value;
+
+ while ((cursor = ne_response_header_iterate(req, cursor,
+ &name, &value)) != NULL) {
+ rtl::OUString aHeaderName( rtl::OUString::createFromAscii( name ) );
+ rtl::OUString aHeaderValue( rtl::OUString::createFromAscii( value ) );
+
+ // Note: Empty vector means that all headers are requested.
+ bool bIncludeIt = ( rHeaderNames.size() == 0 );
+
+ if ( !bIncludeIt )
+ {
+ // Check whether this header was requested.
+ std::vector< ::rtl::OUString >::const_iterator it(
+ rHeaderNames.begin() );
+ const std::vector< ::rtl::OUString >::const_iterator end(
+ rHeaderNames.end() );
+
+ while ( it != end )
+ {
+ if ( (*it) == aHeaderName )
+ break;
+
+ ++it;
+ }
+
+ if ( it != end )
+ bIncludeIt = true;
+ }
+
+ if ( bIncludeIt )
+ {
+ // Create & set the PropertyValue
+ DAVPropertyValue thePropertyValue;
+ thePropertyValue.Name = aHeaderName;
+ thePropertyValue.IsCaseSensitive = false;
+ thePropertyValue.Value <<= aHeaderValue;
+
+ // Add the newly created PropertyValue
+ rResource.properties.push_back( thePropertyValue );
+ }
+ }
+}
+#else
+struct NeonHeadRequestContext
+{
+ DAVResource * pResource;
+ const std::vector< ::rtl::OUString > * pHeaderNames;
+
+ NeonHeadRequestContext( DAVResource * p,
+ const std::vector< ::rtl::OUString > * pHeaders )
+ : pResource( p ), pHeaderNames( pHeaders ) {}
+};
+
+extern "C" void NHR_ResponseHeaderCatcher( void * userdata,
+ const char * value )
+{
+ rtl::OUString aHeader( rtl::OUString::createFromAscii( value ) );
+ sal_Int32 nPos = aHeader.indexOf( ':' );
+
+ if ( nPos != -1 )
+ {
+ rtl::OUString aHeaderName( aHeader.copy( 0, nPos ) );
+
+ NeonHeadRequestContext * pCtx
+ = static_cast< NeonHeadRequestContext * >( userdata );
+
+ // Note: Empty vector means that all headers are requested.
+ bool bIncludeIt = ( pCtx->pHeaderNames->size() == 0 );
+
+ if ( !bIncludeIt )
+ {
+ // Check whether this header was requested.
+ std::vector< ::rtl::OUString >::const_iterator it(
+ pCtx->pHeaderNames->begin() );
+ const std::vector< ::rtl::OUString >::const_iterator end(
+ pCtx->pHeaderNames->end() );
+
+ while ( it != end )
+ {
+ if ( (*it) == aHeaderName )
+ break;
+
+ ++it;
+ }
+
+ if ( it != end )
+ bIncludeIt = true;
+ }
+
+ if ( bIncludeIt )
+ {
+ // Create & set the PropertyValue
+ DAVPropertyValue thePropertyValue;
+ thePropertyValue.Name = aHeaderName;
+ thePropertyValue.IsCaseSensitive = false;
+
+ if ( nPos < aHeader.getLength() )
+ thePropertyValue.Value <<= aHeader.copy( nPos + 1 ).trim();
+
+ // Add the newly created PropertyValue
+ pCtx->pResource->properties.push_back( thePropertyValue );
+ }
+ }
+}
+#endif
+
+} // namespace
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+
+NeonHeadRequest::NeonHeadRequest( HttpSession* inSession,
+ const rtl::OUString & inPath,
+ const std::vector< ::rtl::OUString > &
+ inHeaderNames,
+ DAVResource & ioResource,
+ int & nError )
+{
+ ioResource.uri = inPath;
+ ioResource.properties.clear();
+
+ // Create and dispatch HEAD request. Install catcher for all response
+ // header fields.
+ ne_request * req = ne_request_create( inSession,
+ "HEAD",
+ rtl::OUStringToOString(
+ inPath,
+ RTL_TEXTENCODING_UTF8 ) );
+
+#if NEON_VERSION < 0x0250
+ NeonHeadRequestContext aCtx( &ioResource, &inHeaderNames );
+ ne_add_response_header_catcher( req, NHR_ResponseHeaderCatcher, &aCtx );
+#endif
+
+ nError = ne_request_dispatch( req );
+
+#if NEON_VERSION >= 0x0250
+ process_headers(req, ioResource, inHeaderNames);
+#endif
+
+ if ( nError == NE_OK && ne_get_status( req )->klass != 2 )
+ nError = NE_ERROR;
+
+ ne_request_destroy( req );
+}
+
+// -------------------------------------------------------------------
+// Destructor
+// -------------------------------------------------------------------
+NeonHeadRequest::~NeonHeadRequest()
+{
+}
+
diff --git a/ucb/source/ucp/webdav/NeonHeadRequest.hxx b/ucb/source/ucp/webdav/NeonHeadRequest.hxx
new file mode 100644
index 000000000000..eb79ae7658c2
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonHeadRequest.hxx
@@ -0,0 +1,53 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _NEONHEADREQUEST_HXX_
+#define _NEONHEADREQUEST_HXX_
+
+#include <vector>
+#include "NeonTypes.hxx"
+#include "DAVResource.hxx"
+
+namespace webdav_ucp
+{
+
+class NeonHeadRequest
+{
+public:
+ // named / allprop
+ NeonHeadRequest( HttpSession* inSession,
+ const rtl::OUString & inPath,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ int & nError );
+ ~NeonHeadRequest();
+};
+
+} // namespace webdav_ucp
+
+#endif // _NEONHEADREQUEST_HXX_
+
diff --git a/ucb/source/ucp/webdav/NeonInputStream.cxx b/ucb/source/ucp/webdav/NeonInputStream.cxx
new file mode 100644
index 000000000000..2e142af955c8
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonInputStream.cxx
@@ -0,0 +1,195 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+#include "NeonInputStream.hxx"
+#include <rtl/memory.h>
+
+using namespace cppu;
+using namespace rtl;
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+using namespace webdav_ucp;
+
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+NeonInputStream::NeonInputStream( void )
+: mLen( 0 ),
+ mPos( 0 )
+{
+}
+
+// -------------------------------------------------------------------
+// Destructor
+// -------------------------------------------------------------------
+NeonInputStream::~NeonInputStream( void )
+{
+}
+
+// -------------------------------------------------------------------
+// AddToStream
+// Allows the caller to add some data to the "end" of the stream
+// -------------------------------------------------------------------
+void NeonInputStream::AddToStream( const char * inBuf, sal_Int32 inLen )
+{
+ mInputBuffer.realloc( sal::static_int_cast<sal_Int32>(mLen) + inLen );
+ rtl_copyMemory( mInputBuffer.getArray() + mLen, inBuf, inLen );
+ mLen += inLen;
+}
+
+// -------------------------------------------------------------------
+// queryInterface
+// -------------------------------------------------------------------
+Any NeonInputStream::queryInterface( const Type &type )
+ throw( RuntimeException )
+{
+ Any aRet = ::cppu::queryInterface( type,
+ static_cast< XInputStream * >( this ),
+ static_cast< XSeekable * >( this ) );
+ return aRet.hasValue() ? aRet : OWeakObject::queryInterface( type );
+}
+
+// -------------------------------------------------------------------
+// readBytes
+// "Reads" the specified number of bytes from the stream
+// -------------------------------------------------------------------
+sal_Int32 SAL_CALL NeonInputStream::readBytes(
+ ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::BufferSizeExceededException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException )
+{
+ // Work out how much we're actually going to write
+ sal_Int32 theBytes2Read = nBytesToRead;
+ sal_Int32 theBytesLeft = sal::static_int_cast<sal_Int32>(mLen - mPos);
+ if ( theBytes2Read > theBytesLeft )
+ theBytes2Read = theBytesLeft;
+
+ // Realloc buffer.
+ aData.realloc( theBytes2Read );
+
+ // Write the data
+ rtl_copyMemory(
+ aData.getArray(), mInputBuffer.getConstArray() + mPos, theBytes2Read );
+
+ // Update our stream position for next time
+ mPos += theBytes2Read;
+
+ return theBytes2Read;
+}
+
+// -------------------------------------------------------------------
+// readSomeBytes
+// -------------------------------------------------------------------
+sal_Int32 SAL_CALL NeonInputStream::readSomeBytes(
+ ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::BufferSizeExceededException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException )
+{
+ // Warning: What should this be doing ?
+ return readBytes( aData, nMaxBytesToRead );
+}
+
+// -------------------------------------------------------------------
+// skipBytes
+// Moves the current stream position forward
+// -------------------------------------------------------------------
+void SAL_CALL NeonInputStream::skipBytes( sal_Int32 nBytesToSkip )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::BufferSizeExceededException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException )
+{
+ mPos += nBytesToSkip;
+ if ( mPos >= mLen )
+ mPos = mLen;
+}
+
+// -------------------------------------------------------------------
+// available
+// Returns the number of unread bytes currently remaining on the stream
+// -------------------------------------------------------------------
+sal_Int32 SAL_CALL NeonInputStream::available( )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException )
+{
+ return sal::static_int_cast<sal_Int32>(mLen - mPos);
+}
+
+// -------------------------------------------------------------------
+// closeInput
+// -------------------------------------------------------------------
+void SAL_CALL NeonInputStream::closeInput( void )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException )
+{
+}
+
+// -------------------------------------------------------------------
+// seek
+// -------------------------------------------------------------------
+void SAL_CALL NeonInputStream::seek( sal_Int64 location )
+ throw( ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException )
+{
+ if ( location < 0 )
+ throw ::com::sun::star::lang::IllegalArgumentException();
+
+ if ( location <= mLen )
+ mPos = location;
+ else
+ throw ::com::sun::star::lang::IllegalArgumentException();
+}
+
+// -------------------------------------------------------------------
+// getPosition
+// -------------------------------------------------------------------
+sal_Int64 SAL_CALL NeonInputStream::getPosition()
+ throw( ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException )
+{
+ return mPos;
+}
+
+// -------------------------------------------------------------------
+// getLength
+// -------------------------------------------------------------------
+sal_Int64 SAL_CALL NeonInputStream::getLength()
+ throw( ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException )
+{
+ return mLen;
+}
diff --git a/ucb/source/ucp/webdav/NeonInputStream.hxx b/ucb/source/ucp/webdav/NeonInputStream.hxx
new file mode 100644
index 000000000000..55bf64b1bfcc
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonInputStream.hxx
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _NEONINPUTSTREAM_HXX_
+#define _NEONINPUTSTREAM_HXX_
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <cppuhelper/weak.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+
+
+namespace webdav_ucp
+{
+
+// -------------------------------------------------------------------
+// NeonInputStream
+// A simple XInputStream implementation provided specifically for use
+// by the DAVSession::GET method.
+// -------------------------------------------------------------------
+class NeonInputStream : public ::com::sun::star::io::XInputStream,
+ public ::com::sun::star::io::XSeekable,
+ public ::cppu::OWeakObject
+{
+ private:
+ com::sun::star::uno::Sequence< sal_Int8 > mInputBuffer;
+ sal_Int64 mLen;
+ sal_Int64 mPos;
+
+ public:
+ NeonInputStream( void );
+ virtual ~NeonInputStream();
+
+ // Add some data to the end of the stream
+ void AddToStream( const char * inBuf, sal_Int32 inLen );
+
+ // XInterface
+ virtual com::sun::star::uno::Any SAL_CALL queryInterface(
+ const ::com::sun::star::uno::Type & type )
+ throw( ::com::sun::star::uno::RuntimeException );
+
+ virtual void SAL_CALL acquire( void )
+ throw ()
+ { OWeakObject::acquire(); }
+
+ virtual void SAL_CALL release( void )
+ throw()
+ { OWeakObject::release(); }
+
+
+ // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes(
+ ::com::sun::star::uno::Sequence< sal_Int8 > & aData,
+ sal_Int32 nBytesToRead )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::BufferSizeExceededException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int32 SAL_CALL readSomeBytes(
+ ::com::sun::star::uno::Sequence< sal_Int8 > & aData,
+ sal_Int32 nMaxBytesToRead )
+ 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 skipBytes( sal_Int32 nBytesToSkip )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::BufferSizeExceededException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int32 SAL_CALL available( void )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual void SAL_CALL closeInput( void )
+ throw( ::com::sun::star::io::NotConnectedException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+
+ // XSeekable
+ virtual void SAL_CALL seek( sal_Int64 location )
+ throw( ::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int64 SAL_CALL getPosition()
+ throw( ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+
+ virtual sal_Int64 SAL_CALL getLength()
+ throw( ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+};
+
+} // namespace webdav_ucp
+#endif // _NEONINPUTSTREAM_HXX_
diff --git a/ucb/source/ucp/webdav/NeonLockStore.cxx b/ucb/source/ucp/webdav/NeonLockStore.cxx
new file mode 100644
index 000000000000..82510fcc9b71
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonLockStore.cxx
@@ -0,0 +1,245 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <ne_locks.h>
+#include <ne_uri.h>
+#include "rtl/ustring.hxx"
+#include "osl/time.h"
+#include "osl/thread.hxx"
+#include "NeonSession.hxx"
+#include "NeonLockStore.hxx"
+
+using namespace webdav_ucp;
+
+namespace webdav_ucp {
+
+class TickerThread : public osl::Thread
+{
+ bool m_bFinish;
+ NeonLockStore & m_rLockStore;
+
+public:
+
+ TickerThread( NeonLockStore & rLockStore )
+ : osl::Thread(), m_bFinish( false ), m_rLockStore( rLockStore ) {}
+
+ void finish() { m_bFinish = true; }
+
+protected:
+
+ virtual void SAL_CALL run();
+};
+
+} // namespace webdav_ucp
+
+// -------------------------------------------------------------------
+void TickerThread::run()
+{
+ OSL_TRACE( "TickerThread: start." );
+
+ // 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 )
+ {
+ m_rLockStore.refreshLocks();
+ nCount = nNth;
+ }
+
+ TimeValue aTV;
+ aTV.Seconds = 0;
+ aTV.Nanosec = 1000000000 / nNth;
+ wait( aTV );
+ }
+
+ OSL_TRACE( "TickerThread: stop." );
+}
+
+// -------------------------------------------------------------------
+NeonLockStore::NeonLockStore()
+ : m_pNeonLockStore( ne_lockstore_create() ),
+ m_pTickerThread( 0 )
+{
+ OSL_ENSURE( m_pNeonLockStore, "Unable to create neon lock store!" );
+}
+
+// -------------------------------------------------------------------
+NeonLockStore::~NeonLockStore()
+{
+ stopTicker();
+
+ // release active locks, if any.
+ OSL_ENSURE( m_aLockInfoMap.size() == 0,
+ "NeonLockStore::~NeonLockStore - Releasing active locks!" );
+
+ LockInfoMap::const_iterator it( m_aLockInfoMap.begin() );
+ const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
+ while ( it != end )
+ {
+ NeonLock * pLock = (*it).first;
+ (*it).second.xSession->UNLOCK( pLock );
+
+ ne_lockstore_remove( m_pNeonLockStore, pLock );
+ ne_lock_destroy( pLock );
+
+ ++it;
+ }
+
+ ne_lockstore_destroy( m_pNeonLockStore );
+}
+
+// -------------------------------------------------------------------
+void NeonLockStore::startTicker()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( !m_pTickerThread )
+ {
+ m_pTickerThread = new TickerThread( *this );
+ m_pTickerThread->create();
+ }
+}
+
+// -------------------------------------------------------------------
+void NeonLockStore::stopTicker()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_pTickerThread )
+ {
+ m_pTickerThread->finish();
+ m_pTickerThread->join();
+ delete m_pTickerThread;
+ m_pTickerThread = 0;
+ }
+}
+
+// -------------------------------------------------------------------
+void NeonLockStore::registerSession( HttpSession * pHttpSession )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ne_lockstore_register( m_pNeonLockStore, pHttpSession );
+}
+
+// -------------------------------------------------------------------
+NeonLock * NeonLockStore::findByUri( rtl::OUString const & rUri )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ne_uri aUri;
+ ne_uri_parse( rtl::OUStringToOString(
+ rUri, RTL_TEXTENCODING_UTF8 ).getStr(), &aUri );
+ return ne_lockstore_findbyuri( m_pNeonLockStore, &aUri );
+}
+
+// -------------------------------------------------------------------
+void NeonLockStore::addLock( NeonLock * pLock,
+ rtl::Reference< NeonSession > const & xSession,
+ sal_Int32 nLastChanceToSendRefreshRequest )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ ne_lockstore_add( m_pNeonLockStore, pLock );
+ m_aLockInfoMap[ pLock ]
+ = LockInfo( xSession, nLastChanceToSendRefreshRequest );
+
+ startTicker();
+}
+
+// -------------------------------------------------------------------
+void NeonLockStore::updateLock( NeonLock * pLock,
+ sal_Int32 nLastChanceToSendRefreshRequest )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) );
+ OSL_ENSURE( it != m_aLockInfoMap.end(),
+ "NeonLockStore::updateLock: lock not found!" );
+
+ if ( it != m_aLockInfoMap.end() )
+ {
+ (*it).second.nLastChanceToSendRefreshRequest
+ = nLastChanceToSendRefreshRequest;
+ }
+}
+
+// -------------------------------------------------------------------
+void NeonLockStore::removeLock( NeonLock * pLock )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ m_aLockInfoMap.erase( pLock );
+ ne_lockstore_remove( m_pNeonLockStore, pLock );
+
+ if ( m_aLockInfoMap.size() == 0 )
+ stopTicker();
+}
+
+// -------------------------------------------------------------------
+void NeonLockStore::refreshLocks()
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ LockInfoMap::iterator it( m_aLockInfoMap.begin() );
+ const LockInfoMap::const_iterator end( m_aLockInfoMap.end() );
+ while ( it != end )
+ {
+ LockInfo & rInfo = (*it).second;
+ if ( rInfo.nLastChanceToSendRefreshRequest != -1 )
+ {
+ // 30 seconds or less remaining until lock expires?
+ TimeValue t1;
+ osl_getSystemTime( &t1 );
+ if ( rInfo.nLastChanceToSendRefreshRequest - 30
+ <= sal_Int32( t1.Seconds ) )
+ {
+ // refresh the lock.
+ sal_Int32 nlastChanceToSendRefreshRequest = -1;
+ if ( rInfo.xSession->LOCK(
+ (*it).first,
+ /* out param */ nlastChanceToSendRefreshRequest ) )
+ {
+ rInfo.nLastChanceToSendRefreshRequest
+ = nlastChanceToSendRefreshRequest;
+ }
+ else
+ {
+ // refresh failed. stop auto-refresh.
+ rInfo.nLastChanceToSendRefreshRequest = -1;
+ }
+ }
+ }
+ ++it;
+ }
+}
diff --git a/ucb/source/ucp/webdav/NeonLockStore.hxx b/ucb/source/ucp/webdav/NeonLockStore.hxx
new file mode 100644
index 000000000000..66f771f61901
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonLockStore.hxx
@@ -0,0 +1,102 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef INCLUDED_NEONLOCKSTORE_HXX
+#define INCLUDED_NEONLOCKSTORE_HXX
+
+#include <map>
+#include "ne_locks.h"
+#include "osl/mutex.hxx"
+#include "rtl/ref.hxx"
+#include "NeonTypes.hxx"
+
+namespace webdav_ucp
+{
+
+class TickerThread;
+class NeonSession;
+
+struct ltptr
+{
+ bool operator()( const NeonLock * p1, const NeonLock * p2 ) const
+ {
+ return p1 < p2;
+ }
+};
+
+typedef struct _LockInfo
+{
+ rtl::Reference< NeonSession > xSession;
+ sal_Int32 nLastChanceToSendRefreshRequest;
+
+ _LockInfo()
+ : nLastChanceToSendRefreshRequest( -1 ) {}
+
+ _LockInfo( rtl::Reference< NeonSession > const & _xSession,
+ sal_Int32 _nLastChanceToSendRefreshRequest )
+ : xSession( _xSession ),
+ nLastChanceToSendRefreshRequest( _nLastChanceToSendRefreshRequest ) {}
+
+} LockInfo;
+
+typedef std::map< NeonLock *, LockInfo, ltptr > LockInfoMap;
+
+class NeonLockStore
+{
+ osl::Mutex m_aMutex;
+ ne_lock_store * m_pNeonLockStore;
+ TickerThread * m_pTickerThread;
+ LockInfoMap m_aLockInfoMap;
+
+public:
+ NeonLockStore();
+ ~NeonLockStore();
+
+ void registerSession( HttpSession * pHttpSession );
+
+ NeonLock * findByUri( rtl::OUString const & rUri );
+
+ void addLock( NeonLock * pLock,
+ rtl::Reference< NeonSession > const & xSession,
+ // time in seconds since Jan 1 1970
+ // -1: infinite lock, no refresh
+ sal_Int32 nLastChanceToSendRefreshRequest );
+
+ void updateLock( NeonLock * pLock,
+ sal_Int32 nLastChanceToSendRefreshRequest );
+
+ void removeLock( NeonLock * pLock );
+
+ void refreshLocks();
+
+private:
+ void startTicker();
+ void stopTicker();
+};
+
+} // namespace webdav_ucp
+
+#endif // INCLUDED_NEONLOCKSTORE_HXX
diff --git a/ucb/source/ucp/webdav/NeonPropFindRequest.cxx b/ucb/source/ucp/webdav/NeonPropFindRequest.cxx
new file mode 100644
index 000000000000..85b5ea0393e0
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonPropFindRequest.cxx
@@ -0,0 +1,345 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include "osl/diagnose.h"
+#include "rtl/strbuf.hxx"
+#include "NeonTypes.hxx"
+#include "DAVException.hxx"
+#include "DAVProperties.hxx"
+#include "NeonPropFindRequest.hxx"
+#include "LinkSequence.hxx"
+#include "LockSequence.hxx"
+#include "LockEntrySequence.hxx"
+#include "UCBDeadPropertyValue.hxx"
+
+using namespace rtl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::ucb;
+using namespace std;
+using namespace webdav_ucp;
+
+// -------------------------------------------------------------------
+namespace
+{
+ // strip "DAV:" namespace from XML snippets to avoid
+ // parser error (undeclared namespace) later on.
+ rtl::OString stripDavNamespace( const rtl::OString & in )
+ {
+ const rtl::OString inXML( in.toAsciiLowerCase() );
+
+ rtl::OStringBuffer buf;
+ sal_Int32 start = 0;
+ sal_Int32 end = inXML.indexOf( "dav:" );
+ while ( end != -1 )
+ {
+ if ( inXML[ end - 1 ] == '<' ||
+ inXML[ end - 1 ] == '/' )
+ {
+ // copy from original buffer - preserve case.
+ buf.append( in.copy( start, end - start ) );
+ }
+ else
+ {
+ // copy from original buffer - preserve case.
+ buf.append( in.copy( start, end - start + 4 ) );
+ }
+ start = end + 4;
+ end = inXML.indexOf( "dav:", start );
+ }
+ buf.append( inXML.copy( start ) );
+
+ return rtl::OString( buf.makeStringAndClear() );
+ }
+}
+
+// -------------------------------------------------------------------
+extern "C" int NPFR_propfind_iter( void* userdata,
+ const NeonPropName* pname,
+ const char* value,
+ const HttpStatus* status )
+{
+ /*
+ HTTP Response Status Classes:
+
+ - 1: Informational - Request received, continuing process
+
+ - 2: Success - The action was successfully received,
+ understood, and accepted
+
+ - 3: Redirection - Further action must be taken in order to
+ complete the request
+
+ - 4: Client Error - The request contains bad syntax or cannot
+ be fulfilled
+
+ - 5: Server Error - The server failed to fulfill an apparently
+ valid request
+ */
+
+ if ( status->klass > 2 )
+ return 0; // Error getting this property. Go on.
+
+ // Create & set the PropertyValue
+ DAVPropertyValue thePropertyValue;
+ thePropertyValue.IsCaseSensitive = true;
+
+ OSL_ENSURE( pname->nspace, "NPFR_propfind_iter - No namespace!" );
+
+ DAVProperties::createUCBPropName( pname->nspace,
+ pname->name,
+ thePropertyValue.Name );
+ bool bHasValue = false;
+ if ( DAVProperties::isUCBDeadProperty( *pname ) )
+ {
+ // DAV dead property added by WebDAV UCP?
+ if ( UCBDeadPropertyValue::createFromXML(
+ value, thePropertyValue.Value ) )
+ {
+ OSL_ENSURE( thePropertyValue.Value.hasValue(),
+ "NPFR_propfind_iter - No value!" );
+ bHasValue = true;
+ }
+ }
+
+ if ( !bHasValue )
+ {
+ if ( rtl_str_compareIgnoreAsciiCase(
+ pname->name, "resourcetype" ) == 0 )
+ {
+ OString aValue( value );
+ aValue = aValue.trim(); // #107358# remove leading/trailing spaces
+ if ( aValue.getLength() )
+ {
+ aValue = stripDavNamespace( aValue ).toAsciiLowerCase();
+ if ( aValue.compareTo(
+ RTL_CONSTASCII_STRINGPARAM( "<collection" ) ) == 0 )
+ {
+ thePropertyValue.Value
+ <<= OUString::createFromAscii( "collection" );
+ }
+ }
+
+ if ( !thePropertyValue.Value.hasValue() )
+ {
+ // Take over the value exactly as supplied by the server.
+ thePropertyValue.Value <<= OUString::createFromAscii( value );
+ }
+ }
+ else if ( rtl_str_compareIgnoreAsciiCase(
+ pname->name, "supportedlock" ) == 0 )
+ {
+ Sequence< LockEntry > aEntries;
+ LockEntrySequence::createFromXML(
+ stripDavNamespace( value ), aEntries );
+ thePropertyValue.Value <<= aEntries;
+ }
+ else if ( rtl_str_compareIgnoreAsciiCase(
+ pname->name, "lockdiscovery" ) == 0 )
+ {
+ Sequence< Lock > aLocks;
+ LockSequence::createFromXML(
+ stripDavNamespace( value ), aLocks );
+ thePropertyValue.Value <<= aLocks;
+ }
+ else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 )
+ {
+ Sequence< Link > aLinks;
+ LinkSequence::createFromXML(
+ stripDavNamespace( value ), aLinks );
+ thePropertyValue.Value <<= aLinks;
+ }
+ else
+ {
+ thePropertyValue.Value
+ <<= OStringToOUString( value, RTL_TEXTENCODING_UTF8 );
+ }
+ }
+
+ // Add the newly created PropertyValue
+ DAVResource* theResource = static_cast< DAVResource * >( userdata );
+ theResource->properties.push_back( thePropertyValue );
+
+ return 0; // Go on.
+}
+
+// -------------------------------------------------------------------
+extern "C" void NPFR_propfind_results( void* userdata,
+#if NEON_VERSION >= 0x0260
+ const ne_uri* uri,
+#else
+ const char* href,
+#endif
+ const NeonPropFindResultSet* set )
+{
+ // @@@ href is not the uri! DAVResource ctor wants uri!
+
+#if NEON_VERSION >= 0x0260
+ DAVResource theResource(
+ OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
+#else
+ DAVResource theResource(
+ OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) );
+#endif
+
+ ne_propset_iterate( set, NPFR_propfind_iter, &theResource );
+
+ // Add entry to resources list.
+ vector< DAVResource > * theResources
+ = static_cast< vector< DAVResource > * >( userdata );
+ theResources->push_back( theResource );
+}
+// -------------------------------------------------------------------
+extern "C" int NPFR_propnames_iter( void* userdata,
+ const NeonPropName* pname,
+ const char* /*value*/,
+ const HttpStatus* /*status*/ )
+{
+ OUString aFullName;
+ DAVProperties::createUCBPropName( pname->nspace,
+ pname->name,
+ aFullName );
+
+ DAVResourceInfo* theResource = static_cast< DAVResourceInfo * >( userdata );
+ theResource->properties.push_back( aFullName );
+ return 0;
+}
+
+// -------------------------------------------------------------------
+extern "C" void NPFR_propnames_results( void* userdata,
+#if NEON_VERSION >= 0x0260
+ const ne_uri* uri,
+#else
+ const char* href,
+#endif
+ const NeonPropFindResultSet* results )
+{
+ // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
+ // Create entry for the resource.
+#if NEON_VERSION >= 0x0260
+ DAVResourceInfo theResource(
+ OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
+#else
+ DAVResourceInfo theResource(
+ OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) );
+#endif
+
+ // Fill entry.
+ ne_propset_iterate( results, NPFR_propnames_iter, &theResource );
+
+ // Add entry to resources list.
+ vector< DAVResourceInfo > * theResources
+ = static_cast< vector< DAVResourceInfo > * >( userdata );
+ theResources->push_back( theResource );
+}
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+
+NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession,
+ const char* inPath,
+ const Depth inDepth,
+ const vector< OUString >& inPropNames,
+ vector< DAVResource >& ioResources,
+ int & nError )
+{
+ // Generate the list of properties we're looking for
+ int thePropCount = inPropNames.size();
+ if ( thePropCount > 0 )
+ {
+ NeonPropName* thePropNames = new NeonPropName[ thePropCount + 1 ];
+ int theIndex;
+
+ for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
+ {
+ // Split fullname into namespace and name!
+ DAVProperties::createNeonPropName(
+ inPropNames[ theIndex ], thePropNames[ theIndex ] );
+ }
+ thePropNames[ theIndex ].nspace = NULL;
+ thePropNames[ theIndex ].name = NULL;
+
+ nError = ne_simple_propfind( inSession,
+ inPath,
+ inDepth,
+ thePropNames,
+ NPFR_propfind_results,
+ &ioResources );
+
+ for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
+ free( (void *)thePropNames[ theIndex ].name );
+
+ delete [] thePropNames;
+ }
+ else
+ {
+ // ALLPROP
+ nError = ne_simple_propfind( inSession,
+ inPath,
+ inDepth,
+ NULL, // 0 == allprop
+ NPFR_propfind_results,
+ &ioResources );
+ }
+
+ // #87585# - Sometimes neon lies (because some servers lie).
+ if ( ( nError == NE_OK ) && ioResources.empty() )
+ nError = NE_ERROR;
+}
+
+// -------------------------------------------------------------------
+// Constructor
+// - obtains property names
+// -------------------------------------------------------------------
+
+NeonPropFindRequest::NeonPropFindRequest(
+ HttpSession* inSession,
+ const char* inPath,
+ const Depth inDepth,
+ std::vector< DAVResourceInfo > & ioResInfo,
+ int & nError )
+{
+ nError = ne_propnames( inSession,
+ inPath,
+ inDepth,
+ NPFR_propnames_results,
+ &ioResInfo );
+
+ // #87585# - Sometimes neon lies (because some servers lie).
+ if ( ( nError == NE_OK ) && ioResInfo.empty() )
+ nError = NE_ERROR;
+}
+
+// -------------------------------------------------------------------
+// Destructor
+// -------------------------------------------------------------------
+NeonPropFindRequest::~NeonPropFindRequest( )
+{
+}
diff --git a/ucb/source/ucp/webdav/NeonPropFindRequest.hxx b/ucb/source/ucp/webdav/NeonPropFindRequest.hxx
new file mode 100644
index 000000000000..26e8793e2b96
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonPropFindRequest.hxx
@@ -0,0 +1,62 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _NEONPROPFINDREQUEST_HXX_
+#define _NEONPROPFINDREQUEST_HXX_
+
+#include <vector>
+#include <rtl/ustring.hxx>
+#include "NeonTypes.hxx"
+#include "DAVTypes.hxx"
+#include "DAVResource.hxx"
+
+namespace webdav_ucp
+{
+
+class NeonPropFindRequest
+{
+public:
+ // named / allprop
+ NeonPropFindRequest( HttpSession* inSession,
+ const char* inPath,
+ const Depth inDepth,
+ const std::vector< ::rtl::OUString > & inPropNames,
+ std::vector< DAVResource > & ioResources,
+ int & nError );
+ // propnames
+ NeonPropFindRequest( HttpSession* inSession,
+ const char* inPath,
+ const Depth inDepth,
+ std::vector< DAVResourceInfo > & ioResInfo,
+ int & nError );
+
+ ~NeonPropFindRequest();
+};
+
+} // namespace webdav_ucp
+
+#endif // _NEONPROPFINDREQUEST_HXX_
diff --git a/ucb/source/ucp/webdav/NeonSession.cxx b/ucb/source/ucp/webdav/NeonSession.cxx
new file mode 100644
index 000000000000..254fae546940
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonSession.cxx
@@ -0,0 +1,2184 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <hash_map>
+#include <vector>
+#include <string.h>
+#include "osl/diagnose.h"
+#include "osl/time.h"
+#include <rtl/string.h>
+#include <ne_socket.h>
+#include <ne_auth.h>
+#include <ne_redirect.h>
+#include <ne_ssl.h>
+#include <ne_compress.h>
+#include "libxml/parser.h"
+#include "rtl/ustrbuf.hxx"
+#include "comphelper/sequence.hxx"
+#include "ucbhelper/simplecertificatevalidationrequest.hxx"
+
+#include "DAVAuthListener.hxx"
+#include "NeonTypes.hxx"
+#include "NeonSession.hxx"
+#include "NeonInputStream.hxx"
+#include "NeonPropFindRequest.hxx"
+#include "NeonHeadRequest.hxx"
+#include "NeonUri.hxx"
+#include "LinkSequence.hxx"
+#include "UCBDeadPropertyValue.hxx"
+
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+#include <com/sun/star/security/CertificateContainerStatus.hpp>
+#include <com/sun/star/security/CertificateContainer.hpp>
+#include <com/sun/star/security/XCertificateContainer.hpp>
+#include <com/sun/star/ucb/Lock.hpp>
+#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
+
+using namespace com::sun::star;
+using namespace webdav_ucp;
+
+#define SEINITIALIZER_COMPONENT "com.sun.star.xml.crypto.SEInitializer"
+
+#ifndef EOL
+# define EOL "\r\n"
+#endif
+
+// -------------------------------------------------------------------
+// RequestData
+// -------------------------------------------------------------------
+
+struct RequestData
+{
+ // POST
+ rtl::OUString aContentType;
+ rtl::OUString aReferer;
+
+ RequestData() {}
+ RequestData( const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer )
+ : aContentType( rContentType ), aReferer( rReferer ) {}
+};
+
+// -------------------------------------------------------------------
+// RequestDataMap
+// -------------------------------------------------------------------
+
+struct equalPtr
+{
+ bool operator()( const ne_request* p1, const ne_request* p2 ) const
+ {
+ return p1 == p2;
+ }
+};
+
+struct hashPtr
+{
+ size_t operator()( const ne_request* p ) const
+ {
+ return (size_t)p;
+ }
+};
+
+typedef std::hash_map
+<
+ ne_request*,
+ RequestData,
+ hashPtr,
+ equalPtr
+>
+RequestDataMap;
+
+// -------------------------------------------------------------------
+// Helper fuction
+// -------------------------------------------------------------------
+static sal_uInt16 makeStatusCode( const rtl::OUString & rStatusText )
+{
+ // Extract status code from session error string. Unfortunately
+ // neon provides no direct access to the status code...
+
+ if ( rStatusText.getLength() < 3 )
+ {
+ OSL_ENSURE(
+ sal_False, "makeStatusCode - status text string to short!" );
+ return 0;
+ }
+
+ sal_Int32 nPos = rStatusText.indexOf( ' ' );
+ if ( nPos == -1 )
+ {
+ OSL_ENSURE( sal_False, "makeStatusCode - wrong status text format!" );
+ return 0;
+ }
+
+ return sal_uInt16( rStatusText.copy( 0, nPos ).toInt32() );
+}
+
+// -------------------------------------------------------------------
+struct NeonRequestContext
+{
+ uno::Reference< io::XOutputStream > xOutputStream;
+ rtl::Reference< NeonInputStream > xInputStream;
+ const std::vector< ::rtl::OUString > * pHeaderNames;
+ DAVResource * pResource;
+
+ NeonRequestContext( uno::Reference< io::XOutputStream > & xOutStrm )
+ : xOutputStream( xOutStrm ), xInputStream( 0 ),
+ pHeaderNames( 0 ), pResource( 0 ) {}
+
+ NeonRequestContext( const rtl::Reference< NeonInputStream > & xInStrm )
+ : xOutputStream( 0 ), xInputStream( xInStrm ),
+ pHeaderNames( 0 ), pResource( 0 ) {}
+
+ NeonRequestContext( uno::Reference< io::XOutputStream > & xOutStrm,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource )
+ : xOutputStream( xOutStrm ), xInputStream( 0 ),
+ pHeaderNames( &inHeaderNames ), pResource( &ioResource ) {}
+
+ NeonRequestContext( const rtl::Reference< NeonInputStream > & xInStrm,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource )
+ : xOutputStream( 0 ), xInputStream( xInStrm ),
+ pHeaderNames( &inHeaderNames ), pResource( &ioResource ) {}
+};
+
+//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+//
+// Callback functions
+//
+//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+// ResponseBlockReader
+// A simple Neon response_block_reader for use with an XInputStream
+// -------------------------------------------------------------------
+
+#if NEON_VERSION >= 0x0250
+extern "C" int NeonSession_ResponseBlockReader(void * inUserData,
+#else
+extern "C" void NeonSession_ResponseBlockReader(void * inUserData,
+#endif
+ const char * inBuf,
+ size_t inLen )
+{
+ // neon sometimes calls this function with (inLen == 0)...
+ if ( inLen > 0 )
+ {
+ NeonRequestContext * pCtx
+ = static_cast< NeonRequestContext * >( inUserData );
+
+ rtl::Reference< NeonInputStream > xInputStream(
+ pCtx->xInputStream );
+
+ if ( xInputStream.is() )
+ xInputStream->AddToStream( inBuf, inLen );
+ }
+#if NEON_VERSION >= 0x0250
+ return 0;
+#endif
+}
+
+// -------------------------------------------------------------------
+// ResponseBlockWriter
+// A simple Neon response_block_reader for use with an XOutputStream
+// -------------------------------------------------------------------
+
+#if NEON_VERSION >= 0x0250
+extern "C" int NeonSession_ResponseBlockWriter( void * inUserData,
+#else
+extern "C" void NeonSession_ResponseBlockWriter( void * inUserData,
+#endif
+ const char * inBuf,
+ size_t inLen )
+{
+ // neon calls this function with (inLen == 0)...
+ if ( inLen > 0 )
+ {
+ NeonRequestContext * pCtx
+ = static_cast< NeonRequestContext * >( inUserData );
+ uno::Reference< io::XOutputStream > xOutputStream
+ = pCtx->xOutputStream;
+
+ if ( xOutputStream.is() )
+ {
+ const uno::Sequence< sal_Int8 > aSeq( (sal_Int8 *)inBuf, inLen );
+ xOutputStream->writeBytes( aSeq );
+ }
+ }
+#if NEON_VERSION >= 0x0250
+ return 0;
+#endif
+}
+
+// -------------------------------------------------------------------
+extern "C" int NeonSession_NeonAuth( void * inUserData,
+#ifdef NE_FEATURE_SSPI
+ const char * inAuthProtocol,
+#endif
+ const char * inRealm,
+ int attempt,
+ char * inoutUserName,
+ char * inoutPassWord )
+{
+/* The callback used to request the username and password in the given
+ * realm. The username and password must be copied into the buffers
+ * which are both of size NE_ABUFSIZ. The 'attempt' parameter is zero
+ * on the first call to the callback, and increases by one each time
+ * an attempt to authenticate fails.
+ *
+ * The callback must return zero to indicate that authentication
+ * should be attempted with the username/password, or non-zero to
+ * cancel the request. (if non-zero, username and password are
+ * ignored.) */
+
+#if 0
+ // Give'em only a limited mumber of retries..
+ if ( attempt > 9 )
+ {
+ // abort
+ return -1;
+ }
+#endif
+
+ NeonSession * theSession = static_cast< NeonSession * >( inUserData );
+ DAVAuthListener * pListener
+ = theSession->getRequestEnvironment().m_xAuthListener.get();
+ if ( !pListener )
+ {
+ // abort
+ return -1;
+ }
+ rtl::OUString theUserName;
+ rtl::OUString thePassWord;
+
+ if ( attempt == 0 )
+ {
+ // neon does not handle username supplied with request URI (for
+ // instance when doing FTP over proxy - last checked: 0.23.5 )
+
+ try
+ {
+ NeonUri uri( theSession->getRequestEnvironment().m_aRequestURI );
+ rtl::OUString aUserInfo( uri.GetUserInfo() );
+ if ( aUserInfo.getLength() )
+ {
+ sal_Int32 nPos = aUserInfo.indexOf( '@' );
+ if ( nPos == -1 )
+ {
+ theUserName = aUserInfo;
+ }
+ else
+ {
+ theUserName = aUserInfo.copy( 0, nPos );
+ thePassWord = aUserInfo.copy( nPos + 1 );
+ }
+ }
+ }
+ catch ( DAVException const & )
+ {
+ // abort
+ return -1;
+ }
+ }
+ else
+ {
+ // username buffer is prefilled with user name from last attempt.
+ theUserName = rtl::OUString::createFromAscii( inoutUserName );
+ // @@@ Neon does not initialize password buffer (last checked: 0.22.0).
+ //thePassWord = rtl::OUString::createFromAscii( inoutPassWord );
+ }
+
+ bool bCanUseSystemCreds = false;
+
+#ifdef NE_FEATURE_SSPI
+ bCanUseSystemCreds
+ = (attempt == 0) && // avoid endless loops
+ ne_has_support( NE_FEATURE_SSPI ) && // Windows-only feature.
+ ( ( ne_strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) ||
+ ( ne_strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) );
+#endif
+
+ int theRetVal = pListener->authenticate(
+ rtl::OUString::createFromAscii( inRealm ),
+ theSession->getHostName(),
+ theUserName,
+ thePassWord,
+ bCanUseSystemCreds);
+
+ rtl::OString aUser(
+ rtl::OUStringToOString( theUserName, RTL_TEXTENCODING_UTF8 ) );
+ if ( aUser.getLength() > ( NE_ABUFSIZ - 1 ) )
+ {
+ OSL_ENSURE(
+ sal_False, "NeonSession_NeonAuth - username to long!" );
+ return -1;
+ }
+
+ rtl::OString aPass(
+ rtl::OUStringToOString( thePassWord, RTL_TEXTENCODING_UTF8 ) );
+ if ( aPass.getLength() > ( NE_ABUFSIZ - 1 ) )
+ {
+ OSL_ENSURE(
+ sal_False, "NeonSession_NeonAuth - password to long!" );
+ return -1;
+ }
+
+ strcpy( inoutUserName, // #100211# - checked
+ rtl::OUStringToOString( theUserName, RTL_TEXTENCODING_UTF8 ) );
+
+ strcpy( inoutPassWord, // #100211# - checked
+ rtl::OUStringToOString( thePassWord, RTL_TEXTENCODING_UTF8 ) );
+
+ return theRetVal;
+}
+
+// -------------------------------------------------------------------
+
+namespace {
+ // -------------------------------------------------------------------
+ // Helper function
+ ::rtl::OUString GetHostnamePart( const ::rtl::OUString& _rRawString )
+ {
+ ::rtl::OUString sPart;
+ ::rtl::OUString sPartId = ::rtl::OUString::createFromAscii( "CN=" );
+ sal_Int32 nContStart = _rRawString.indexOf( sPartId );
+ if ( nContStart != -1 )
+ {
+ nContStart = nContStart + sPartId.getLength();
+ sal_Int32 nContEnd
+ = _rRawString.indexOf( sal_Unicode( ',' ), nContStart );
+ sPart = _rRawString.copy( nContStart, nContEnd - nContStart );
+ }
+ return sPart;
+ }
+} // namespace
+
+// -------------------------------------------------------------------
+extern "C" int NeonSession_CertificationNotify( void *userdata,
+ int failures,
+ const ne_ssl_certificate *cert )
+{
+ OSL_ASSERT( cert );
+
+ NeonSession * pSession = static_cast< NeonSession * >( userdata );
+ uno::Reference< security::XCertificateContainer > xCertificateContainer;
+ try
+ {
+ xCertificateContainer
+ = uno::Reference< security::XCertificateContainer >(
+ pSession->getMSF()->createInstance(
+ rtl::OUString::createFromAscii(
+ "com.sun.star.security.CertificateContainer" ) ),
+ uno::UNO_QUERY );
+ }
+ catch ( uno::Exception const & )
+ {
+ }
+
+ if ( !xCertificateContainer.is() )
+ return 1;
+
+ failures = 0;
+
+ char * dn = ne_ssl_readable_dname( ne_ssl_cert_subject( cert ) );
+ rtl::OUString cert_subject( dn, strlen( dn ), RTL_TEXTENCODING_UTF8, 0 );
+
+ ne_free( dn );
+
+ security::CertificateContainerStatus certificateContainer(
+ xCertificateContainer->hasCertificate(
+ pSession->getHostName(), cert_subject ) );
+
+ if ( certificateContainer != security::CertificateContainerStatus_NOCERT )
+ return
+ certificateContainer == security::CertificateContainerStatus_TRUSTED
+ ? 0
+ : 1;
+
+ uno::Reference< xml::crypto::XSEInitializer > xSEInitializer;
+ try
+ {
+ xSEInitializer = uno::Reference< xml::crypto::XSEInitializer >(
+ pSession->getMSF()->createInstance(
+ rtl::OUString::createFromAscii( SEINITIALIZER_COMPONENT ) ),
+ uno::UNO_QUERY );
+ }
+ catch ( uno::Exception const & )
+ {
+ }
+
+ if ( !xSEInitializer.is() )
+ return 1;
+
+ uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext(
+ xSEInitializer->createSecurityContext( rtl::OUString() ) );
+
+ uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv(
+ xSecurityContext->getSecurityEnvironment() );
+
+ //The end entity certificate
+ char * eeCertB64 = ne_ssl_cert_export( cert );
+
+ rtl::OString sEECertB64( eeCertB64 );
+
+ uno::Reference< security::XCertificate > xEECert(
+ xSecurityEnv->createCertificateFromAscii(
+ rtl::OStringToOUString( sEECertB64, RTL_TEXTENCODING_ASCII_US ) ) );
+
+ ne_free( eeCertB64 );
+ eeCertB64 = 0;
+
+ std::vector< uno::Reference< security::XCertificate > > vecCerts;
+ const ne_ssl_certificate * issuerCert = cert;
+ do
+ {
+ //get the intermediate certificate
+ //the returned value is const ! Therfore it does not need to be freed
+ //with ne_ssl_cert_free, which takes a non-const argument
+ issuerCert = ne_ssl_cert_signedby( issuerCert );
+ if ( NULL == issuerCert )
+ break;
+
+ char * imCertB64 = ne_ssl_cert_export( issuerCert );
+ rtl::OString sInterMediateCertB64( imCertB64 );
+ ne_free( imCertB64 );
+
+ uno::Reference< security::XCertificate> xImCert(
+ xSecurityEnv->createCertificateFromAscii(
+ rtl::OStringToOUString(
+ sInterMediateCertB64, RTL_TEXTENCODING_ASCII_US ) ) );
+ if ( xImCert.is() )
+ vecCerts.push_back( xImCert );
+ }
+ while ( 1 );
+
+ sal_Int64 certValidity = xSecurityEnv->verifyCertificate( xEECert,
+ ::comphelper::containerToSequence( vecCerts ) );
+
+ if ( pSession->isDomainMatch(
+ GetHostnamePart( xEECert.get()->getSubjectName() ) ) )
+ {
+ // if host name matched with certificate then look if the
+ // certificate was ok
+ if( certValidity == security::CertificateValidity::VALID )
+ return 0;
+ }
+
+ const uno::Reference< ucb::XCommandEnvironment > xEnv(
+ pSession->getRequestEnvironment().m_xEnv );
+ if ( xEnv.is() )
+ {
+ failures = static_cast< int >( certValidity );
+
+ uno::Reference< task::XInteractionHandler > xIH(
+ xEnv->getInteractionHandler() );
+ if ( xIH.is() )
+ {
+ rtl::Reference< ucbhelper::SimpleCertificateValidationRequest >
+ xRequest( new ucbhelper::SimpleCertificateValidationRequest(
+ (sal_Int32)failures, xEECert, pSession->getHostName() ) );
+ xIH->handle( xRequest.get() );
+
+ rtl::Reference< ucbhelper::InteractionContinuation > xSelection
+ = xRequest->getSelection();
+
+ if ( xSelection.is() )
+ {
+ uno::Reference< task::XInteractionApprove > xApprove(
+ xSelection.get(), uno::UNO_QUERY );
+ if ( xApprove.is() )
+ {
+ xCertificateContainer->addCertificate(
+ pSession->getHostName(), cert_subject, sal_True );
+ return 0;
+ }
+ else
+ {
+ // Don't trust cert
+ xCertificateContainer->addCertificate(
+ pSession->getHostName(), cert_subject, sal_False );
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ // Don't trust cert
+ xCertificateContainer->addCertificate(
+ pSession->getHostName(), cert_subject, sal_False );
+ return 1;
+ }
+ }
+ return 1;
+}
+
+// -------------------------------------------------------------------
+extern "C" void NeonSession_PreSendRequest( ne_request * req,
+ void * userdata,
+ ne_buffer * headers )
+{
+ // userdata -> value returned by 'create'
+
+ NeonSession * pSession = static_cast< NeonSession * >( userdata );
+ if ( pSession )
+ {
+ // If there is a proxy server in between, it shall never use
+ // cached data. We always want 'up-to-date' data.
+ ne_buffer_concat( headers, "Pragma: no-cache", EOL, NULL );
+ // alternative, but understoud by HTTP 1.1 servers only:
+ // ne_buffer_concat( headers, "Cache-Control: max-age=0", EOL, NULL );
+
+ const RequestDataMap * pRequestData
+ = static_cast< const RequestDataMap* >(
+ pSession->getRequestData() );
+
+ RequestDataMap::const_iterator it = pRequestData->find( req );
+ if ( it != pRequestData->end() )
+ {
+ if ( (*it).second.aContentType.getLength() )
+ {
+ char * pData = headers->data;
+ if ( strstr( pData, "Content-Type:" ) == NULL )
+ {
+ rtl::OString aType
+ = rtl::OUStringToOString( (*it).second.aContentType,
+ RTL_TEXTENCODING_UTF8 );
+ ne_buffer_concat( headers, "Content-Type: ",
+ aType.getStr(), EOL, NULL );
+ }
+ }
+
+ if ( (*it).second.aReferer.getLength() )
+ {
+ char * pData = headers->data;
+ if ( strstr( pData, "Referer:" ) == NULL )
+ {
+ rtl::OString aReferer
+ = rtl::OUStringToOString( (*it).second.aReferer,
+ RTL_TEXTENCODING_UTF8 );
+ ne_buffer_concat( headers, "Referer: ",
+ aReferer.getStr(), EOL, NULL );
+ }
+ }
+ }
+
+ const DAVRequestHeaders & rHeaders
+ = pSession->getRequestEnvironment().m_aRequestHeaders;
+
+ DAVRequestHeaders::const_iterator it1( rHeaders.begin() );
+ const DAVRequestHeaders::const_iterator end1( rHeaders.end() );
+
+ while ( it1 != end1 )
+ {
+ rtl::OString aHeader
+ = rtl::OUStringToOString( (*it1).first,
+ RTL_TEXTENCODING_UTF8 );
+ rtl::OString aValue
+ = rtl::OUStringToOString( (*it1).second,
+ RTL_TEXTENCODING_UTF8 );
+ ne_buffer_concat( headers, aHeader.getStr(), ": ",
+ aValue.getStr(), EOL, NULL );
+
+ ++it1;
+ }
+ }
+}
+
+// -------------------------------------------------------------------
+// static members!
+bool NeonSession::m_bGlobalsInited = false;
+osl::Mutex NeonSession::m_aGlobalMutex;
+NeonLockStore NeonSession::m_aNeonLockStore;
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+NeonSession::NeonSession(
+ const rtl::Reference< DAVSessionFactory > & rSessionFactory,
+ const rtl::OUString& inUri,
+ const ucbhelper::InternetProxyDecider & rProxyDecider )
+ throw ( DAVException )
+: DAVSession( rSessionFactory ),
+ m_pHttpSession( 0 ),
+ m_pRequestData( new RequestDataMap ),
+ m_rProxyDecider( rProxyDecider )
+{
+ NeonUri theUri( inUri );
+ m_aScheme = theUri.GetScheme();
+ m_aHostName = theUri.GetHost();
+ m_nPort = theUri.GetPort();
+}
+
+// -------------------------------------------------------------------
+// Destructor
+// -------------------------------------------------------------------
+NeonSession::~NeonSession( )
+{
+ if ( m_pHttpSession )
+ {
+ ne_session_destroy( m_pHttpSession );
+ m_pHttpSession = 0;
+ }
+ delete static_cast< RequestDataMap * >( m_pRequestData );
+}
+
+// -------------------------------------------------------------------
+void NeonSession::Init( const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+ m_aEnv = rEnv;
+ Init();
+}
+
+// -------------------------------------------------------------------
+void NeonSession::Init()
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ bool bCreateNewSession = false;
+
+ if ( m_pHttpSession == 0 )
+ {
+ // Ensure that Neon sockets are initialized
+
+ // --> tkr #151111# crashed if copy and pasted pictures from the internet
+ // ne_sock_init() was executed by two threads at the same time.
+ osl::Guard< osl::Mutex > theGlobalGuard( m_aGlobalMutex );
+ // <--
+ if ( !m_bGlobalsInited )
+ {
+ if ( ne_sock_init() != 0 )
+ throw DAVException( DAVException::DAV_SESSION_CREATE,
+ NeonUri::makeConnectionEndPointString(
+ m_aHostName, m_nPort ) );
+
+ // #122205# - libxml2 needs to be initialized once if used by
+ // multithreaded programs like OOo.
+ xmlInitParser();
+#if 0
+ // for more debug flags see ne_utils.h; NE_DEBUGGING must be defined
+ // while compiling neon in order to actually activate neon debug
+ // output.
+ ne_debug_init( stderr, NE_DBG_FLUSH
+ | NE_DBG_HTTP
+ // | NE_DBG_HTTPBODY
+ // | NE_DBG_HTTPAUTH
+ // | NE_DBG_XML
+ // | NE_DBG_XMLPARSE
+ // | NE_DBG_LOCKS
+ );
+#endif
+ m_bGlobalsInited = true;
+ }
+
+ const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings();
+
+ m_aProxyName = rProxyCfg.aName;
+ m_nProxyPort = rProxyCfg.nPort;
+
+ // Not yet initialized. Create new session.
+ bCreateNewSession = true;
+ }
+ else
+ {
+ // #112271# Check whether proxy settings are still valid (They may
+ // change at any time). If not, create new Neon session.
+
+ const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings();
+
+ if ( ( rProxyCfg.aName != m_aProxyName )
+ || ( rProxyCfg.nPort != m_nProxyPort ) )
+ {
+ m_aProxyName = rProxyCfg.aName;
+ m_nProxyPort = rProxyCfg.nPort;
+
+ // new session needed, destroy old first
+ ne_session_destroy( m_pHttpSession );
+ m_pHttpSession = 0;
+ bCreateNewSession = true;
+ }
+ }
+
+ if ( bCreateNewSession )
+ {
+ // @@@ For FTP over HTTP proxy inUserInfo is needed to be able to
+ // build the complete request URI (including user:pass), but
+ // currently (0.22.0) neon does not allow to pass the user info
+ // to the session
+
+ m_pHttpSession = ne_session_create(
+ rtl::OUStringToOString( m_aScheme,
+ RTL_TEXTENCODING_UTF8 ).getStr(),
+ /* theUri.GetUserInfo(),
+ @@@ for FTP via HTTP proxy, but not supported by Neon */
+ rtl::OUStringToOString( m_aHostName,
+ RTL_TEXTENCODING_UTF8 ).getStr(),
+ m_nPort );
+
+ if ( m_pHttpSession == 0 )
+ throw DAVException( DAVException::DAV_SESSION_CREATE,
+ NeonUri::makeConnectionEndPointString(
+ m_aHostName, m_nPort ) );
+
+ // Register the session with the lock store
+ m_aNeonLockStore.registerSession( m_pHttpSession );
+
+ if ( m_aScheme.equalsIgnoreAsciiCase(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "https" ) ) ) )
+ {
+ // Set a failure callback for certificate check
+ ne_ssl_set_verify(
+ m_pHttpSession, NeonSession_CertificationNotify, this);
+ }
+
+ // Add hooks (i.e. for adding additional headers to the request)
+
+#if 0
+ /* Hook called when a request is created. */
+ //typedef void (*ne_create_request_fn)(ne_request *req, void *userdata,
+ // const char *method, const char *path);
+
+ ne_hook_create_request( m_pHttpSession, create_req_hook_fn, this );
+#endif
+
+ /* Hook called before the request is sent. 'header' is the raw HTTP
+ * header before the trailing CRLF is added: add in more here. */
+ //typedef void (*ne_pre_send_fn)(ne_request *req, void *userdata,
+ // ne_buffer *header);
+
+ ne_hook_pre_send( m_pHttpSession, NeonSession_PreSendRequest, this );
+#if 0
+ /* Hook called after the request is sent. May return:
+ * NE_OK everything is okay
+ * NE_RETRY try sending the request again.
+ * anything else signifies an error, and the request is failed. The
+ * return code is passed back the _dispatch caller, so the session error
+ * must also be set appropriately (ne_set_error).
+ */
+ //typedef int (*ne_post_send_fn)(ne_request *req, void *userdata,
+ // const ne_status *status);
+
+ ne_hook_post_send( m_pHttpSession, post_send_req_hook_fn, this );
+
+ /* Hook called when the request is destroyed. */
+ //typedef void (*ne_destroy_req_fn)(ne_request *req, void *userdata);
+
+ ne_hook_destroy_request( m_pHttpSession, destroy_req_hook_fn, this );
+
+ /* Hook called when the session is destroyed. */
+ //typedef void (*ne_destroy_sess_fn)(void *userdata);
+
+ ne_hook_destroy_session( m_pHttpSession, destroy_sess_hook_fn, this );
+#endif
+
+ if ( m_aProxyName.getLength() )
+ {
+ ne_session_proxy( m_pHttpSession,
+ rtl::OUStringToOString(
+ m_aProxyName,
+ RTL_TEXTENCODING_UTF8 ).getStr(),
+ m_nProxyPort );
+ }
+
+ // Register for redirects.
+ ne_redirect_register( m_pHttpSession );
+
+ // authentication callbacks.
+ ne_add_server_auth(
+ m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this );
+ ne_add_proxy_auth(
+ m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this );
+ }
+}
+
+// -------------------------------------------------------------------
+// virtual
+sal_Bool NeonSession::CanUse( const rtl::OUString & inUri )
+{
+ try
+ {
+ NeonUri theUri( inUri );
+ if ( ( theUri.GetPort() == m_nPort ) &&
+ ( theUri.GetHost() == m_aHostName ) &&
+ ( theUri.GetScheme() == m_aScheme ) )
+ return sal_True;
+ }
+ catch ( DAVException const & )
+ {
+ return sal_False;
+ }
+ return sal_False;
+}
+
+// -------------------------------------------------------------------
+// virtual
+sal_Bool NeonSession::UsesProxy()
+{
+ Init();
+ return ( m_aProxyName.getLength() > 0 );
+}
+
+// -------------------------------------------------------------------
+// OPTIONS
+// -------------------------------------------------------------------
+void NeonSession::OPTIONS( const rtl::OUString & inPath,
+ DAVCapabilities & outCapabilities,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ HttpServerCapabilities servercaps;
+ memset( &servercaps, 0, sizeof( servercaps ) );
+
+ int theRetVal = ne_options( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ &servercaps );
+
+ HandleError( theRetVal, inPath, rEnv );
+
+ outCapabilities.class1 = !!servercaps.dav_class1;
+ outCapabilities.class2 = !!servercaps.dav_class2;
+ outCapabilities.executable = !!servercaps.dav_executable;
+}
+
+// -------------------------------------------------------------------
+// PROPFIND - allprop & named
+// -------------------------------------------------------------------
+void NeonSession::PROPFIND( const rtl::OUString & inPath,
+ const Depth inDepth,
+ const std::vector< rtl::OUString > & inPropNames,
+ std::vector< DAVResource > & ioResources,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ int theRetVal = NE_OK;
+ NeonPropFindRequest theRequest( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ inDepth,
+ inPropNames,
+ ioResources,
+ theRetVal );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// PROPFIND - propnames
+// -------------------------------------------------------------------
+void NeonSession::PROPFIND( const rtl::OUString & inPath,
+ const Depth inDepth,
+ std::vector< DAVResourceInfo > & ioResInfo,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ int theRetVal = NE_OK;
+ NeonPropFindRequest theRequest( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ inDepth,
+ ioResInfo,
+ theRetVal );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// PROPPATCH
+// -------------------------------------------------------------------
+void NeonSession::PROPPATCH( const rtl::OUString & inPath,
+ const std::vector< ProppatchValue > & inValues,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException )
+{
+ /* @@@ Which standard live properties can be set by the client?
+ This is a known WebDAV RFC issue ( verified: 04/10/2001 )
+ --> http://www.ics.uci.edu/pub/ietf/webdav/protocol/issues.html
+
+ mod_dav implementation:
+
+ creationdate r ( File System prop )
+ displayname w
+ getcontentlanguage r ( #ifdef DAV_DISABLE_WRITEABLE_PROPS )
+ getcontentlength r ( File System prop )
+ getcontenttype r ( #ifdef DAV_DISABLE_WRITEABLE_PROPS )
+ getetag r ( File System prop )
+ getlastmodified r ( File System prop )
+ lockdiscovery r
+ resourcetype r
+ source w
+ supportedlock r
+ executable w ( #ifndef WIN32 )
+
+ All dead properties are of course writable.
+ */
+
+ int theRetVal = NE_OK;
+
+ int n; // for the "for" loop
+
+ // Generate the list of properties we want to set.
+ int nPropCount = inValues.size();
+ ne_proppatch_operation* pItems
+ = new ne_proppatch_operation[ nPropCount + 1 ];
+ for ( n = 0; n < nPropCount; ++n )
+ {
+ const ProppatchValue & rValue = inValues[ n ];
+
+ // Split fullname into namespace and name!
+ ne_propname * pName = new ne_propname;
+ DAVProperties::createNeonPropName( rValue.name, *pName );
+ pItems[ n ].name = pName;
+
+ if ( rValue.operation == PROPSET )
+ {
+ pItems[ n ].type = ne_propset;
+
+ rtl::OUString aStringValue;
+ if ( DAVProperties::isUCBDeadProperty( *pName ) )
+ {
+ // DAV dead property added by WebDAV UCP?
+ if ( !UCBDeadPropertyValue::toXML( rValue.value,
+ aStringValue ) )
+ {
+ // Error!
+ pItems[ n ].value = 0;
+ theRetVal = NE_ERROR;
+ nPropCount = n + 1;
+ break;
+ }
+ }
+ else if ( !( rValue.value >>= aStringValue ) )
+ {
+ // complex properties...
+ if ( rValue.name == DAVProperties::SOURCE )
+ {
+ uno::Sequence< ucb::Link > aLinks;
+ if ( rValue.value >>= aLinks )
+ {
+ LinkSequence::toXML( aLinks, aStringValue );
+ }
+ else
+ {
+ // Error!
+ pItems[ n ].value = 0;
+ theRetVal = NE_ERROR;
+ nPropCount = n + 1;
+ break;
+ }
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "NeonSession::PROPPATCH - unsupported type!" );
+ // Error!
+ pItems[ n ].value = 0;
+ theRetVal = NE_ERROR;
+ nPropCount = n + 1;
+ break;
+ }
+ }
+ pItems[ n ].value
+ = strdup( rtl::OUStringToOString( aStringValue,
+ RTL_TEXTENCODING_UTF8 ) );
+ }
+ else
+ {
+ pItems[ n ].type = ne_propremove;
+ pItems[ n ].value = 0;
+ }
+ }
+
+ if ( theRetVal == NE_OK )
+ {
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ pItems[ n ].name = 0;
+
+ theRetVal = ne_proppatch( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ pItems );
+ }
+
+ for ( n = 0; n < nPropCount; ++n )
+ {
+ free( (void *)pItems[ n ].name->name );
+ delete pItems[ n ].name;
+ free( (void *)pItems[ n ].value );
+ }
+
+ delete [] pItems;
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// HEAD
+// -------------------------------------------------------------------
+void NeonSession::HEAD( const ::rtl::OUString & inPath,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ int theRetVal = NE_OK;
+ NeonHeadRequest theRequest( m_pHttpSession,
+ inPath,
+ inHeaderNames,
+ ioResource,
+ theRetVal );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// GET
+// -------------------------------------------------------------------
+uno::Reference< io::XInputStream >
+NeonSession::GET( const rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
+ NeonRequestContext aCtx( xInputStream );
+ int theRetVal = GET( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ NeonSession_ResponseBlockReader,
+ false,
+ &aCtx );
+
+ HandleError( theRetVal, inPath, rEnv );
+
+ return uno::Reference< io::XInputStream >( xInputStream.get() );
+}
+
+// -------------------------------------------------------------------
+// GET
+// -------------------------------------------------------------------
+void NeonSession::GET( const rtl::OUString & inPath,
+ uno::Reference< io::XOutputStream > & ioOutputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ NeonRequestContext aCtx( ioOutputStream );
+ int theRetVal = GET( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ NeonSession_ResponseBlockWriter,
+ false,
+ &aCtx );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// GET
+// -------------------------------------------------------------------
+uno::Reference< io::XInputStream >
+NeonSession::GET( const rtl::OUString & inPath,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ ioResource.uri = inPath;
+ ioResource.properties.clear();
+
+ rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
+ NeonRequestContext aCtx( xInputStream, inHeaderNames, ioResource );
+ int theRetVal = GET( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ NeonSession_ResponseBlockReader,
+ true,
+ &aCtx );
+
+ HandleError( theRetVal, inPath, rEnv );
+
+ return uno::Reference< io::XInputStream >( xInputStream.get() );
+}
+
+// -------------------------------------------------------------------
+// GET
+// -------------------------------------------------------------------
+void NeonSession::GET( const rtl::OUString & inPath,
+ uno::Reference< io::XOutputStream > & ioOutputStream,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ ioResource.uri = inPath;
+ ioResource.properties.clear();
+
+ NeonRequestContext aCtx( ioOutputStream, inHeaderNames, ioResource );
+ int theRetVal = GET( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ NeonSession_ResponseBlockWriter,
+ true,
+ &aCtx );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// PUT
+// -------------------------------------------------------------------
+void NeonSession::PUT( const rtl::OUString & inPath,
+ const uno::Reference< io::XInputStream > & inInputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ uno::Sequence< sal_Int8 > aDataToSend;
+ if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ Init( rEnv );
+
+ int theRetVal = PUT( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ reinterpret_cast< const char * >(
+ aDataToSend.getConstArray() ),
+ aDataToSend.getLength() );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// POST
+// -------------------------------------------------------------------
+uno::Reference< io::XInputStream >
+NeonSession::POST( const rtl::OUString & inPath,
+ const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer,
+ const uno::Reference< io::XInputStream > & inInputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ uno::Sequence< sal_Int8 > aDataToSend;
+ if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ Init( rEnv );
+
+ rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
+ NeonRequestContext aCtx( xInputStream );
+ int theRetVal = POST( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ reinterpret_cast< const char * >(
+ aDataToSend.getConstArray() ),
+ NeonSession_ResponseBlockReader,
+ &aCtx,
+ rContentType,
+ rReferer );
+
+ HandleError( theRetVal, inPath, rEnv );
+
+ return uno::Reference< io::XInputStream >( xInputStream.get() );
+}
+
+// -------------------------------------------------------------------
+// POST
+// -------------------------------------------------------------------
+void NeonSession::POST( const rtl::OUString & inPath,
+ const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer,
+ const uno::Reference< io::XInputStream > & inInputStream,
+ uno::Reference< io::XOutputStream > & oOutputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ uno::Sequence< sal_Int8 > aDataToSend;
+ if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ Init( rEnv );
+
+ NeonRequestContext aCtx( oOutputStream );
+ int theRetVal = POST( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ),
+ reinterpret_cast< const char * >(
+ aDataToSend.getConstArray() ),
+ NeonSession_ResponseBlockWriter,
+ &aCtx,
+ rContentType,
+ rReferer );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// MKCOL
+// -------------------------------------------------------------------
+void NeonSession::MKCOL( const rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ int theRetVal = ne_mkcol( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ) );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// COPY
+// -------------------------------------------------------------------
+void NeonSession::COPY( const rtl::OUString & inSourceURL,
+ const rtl::OUString & inDestinationURL,
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool inOverWrite )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ NeonUri theSourceUri( inSourceURL );
+ NeonUri theDestinationUri( inDestinationURL );
+
+ int theRetVal = ne_copy( m_pHttpSession,
+ inOverWrite ? 1 : 0,
+ NE_DEPTH_INFINITE,
+ rtl::OUStringToOString(
+ theSourceUri.GetPath(),
+ RTL_TEXTENCODING_UTF8 ),
+ rtl::OUStringToOString(
+ theDestinationUri.GetPath(),
+ RTL_TEXTENCODING_UTF8 ) );
+
+ HandleError( theRetVal, inSourceURL, rEnv );
+}
+
+// -------------------------------------------------------------------
+// MOVE
+// -------------------------------------------------------------------
+void NeonSession::MOVE( const rtl::OUString & inSourceURL,
+ const rtl::OUString & inDestinationURL,
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool inOverWrite )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ NeonUri theSourceUri( inSourceURL );
+ NeonUri theDestinationUri( inDestinationURL );
+ int theRetVal = ne_move( m_pHttpSession,
+ inOverWrite ? 1 : 0,
+ rtl::OUStringToOString(
+ theSourceUri.GetPath(),
+ RTL_TEXTENCODING_UTF8 ),
+ rtl::OUStringToOString(
+ theDestinationUri.GetPath(),
+ RTL_TEXTENCODING_UTF8 ) );
+
+ HandleError( theRetVal, inSourceURL, rEnv );
+}
+
+// -------------------------------------------------------------------
+// DESTROY
+// -------------------------------------------------------------------
+void NeonSession::DESTROY( const rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ int theRetVal = ne_delete( m_pHttpSession,
+ rtl::OUStringToOString(
+ inPath, RTL_TEXTENCODING_UTF8 ) );
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+namespace
+{
+ sal_Int32 lastChanceToSendRefreshRequest( TimeValue const & rStart,
+ int timeout )
+ {
+ TimeValue aEnd;
+ osl_getSystemTime( &aEnd );
+
+ // Try to estimate a safe absolute time for sending the
+ // lock refresh request.
+ sal_Int32 lastChanceToSendRefreshRequest = -1;
+ if ( timeout != NE_TIMEOUT_INFINITE )
+ {
+ sal_Int32 calltime = aEnd.Seconds - rStart.Seconds;
+ if ( calltime <= timeout )
+ {
+ lastChanceToSendRefreshRequest
+ = aEnd.Seconds + timeout - calltime;
+ }
+ else
+ {
+ OSL_TRACE( "No chance to refresh lock before timeout!" );
+ }
+ }
+ return lastChanceToSendRefreshRequest;
+ }
+
+} // namespace
+
+// -------------------------------------------------------------------
+// LOCK (set new lock)
+// -------------------------------------------------------------------
+void NeonSession::LOCK( const ::rtl::OUString & inPath,
+ ucb::Lock & rLock,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ Init( rEnv );
+
+ /* Create a depth zero, exclusive write lock, with default timeout
+ * (allowing a server to pick a default). token, owner and uri are
+ * unset. */
+ NeonLock * theLock = ne_lock_create();
+
+ // Set the lock uri
+ ne_uri aUri;
+ ne_uri_parse( rtl::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
+ rtl::OUString aValue;
+ rLock.Owner >>= aValue;
+ theLock->owner =
+ ne_strdup( rtl::OUStringToOString( aValue,
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ TimeValue startCall;
+ osl_getSystemTime( &startCall );
+
+ int theRetVal = ne_lock( m_pHttpSession, theLock );
+
+ if ( theRetVal == NE_OK )
+ {
+ m_aNeonLockStore.addLock( theLock,
+ this,
+ lastChanceToSendRefreshRequest(
+ startCall, theLock->timeout ) );
+
+ uno::Sequence< rtl::OUString > aTokens( 1 );
+ aTokens[ 0 ] = rtl::OUString::createFromAscii( theLock->token );
+ rLock.LockTokens = aTokens;
+
+ OSL_TRACE( "NeonSession::LOCK: created lock for %s. token: %s",
+ rtl::OUStringToOString( makeAbsoluteURL( inPath ),
+ RTL_TEXTENCODING_UTF8 ).getStr(),
+ theLock->token );
+ }
+ else
+ {
+ ne_lock_destroy( theLock );
+
+ OSL_TRACE( "NeonSession::LOCK: obtaining lock for %s failed!",
+ rtl::OUStringToOString( makeAbsoluteURL( inPath ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// LOCK (refresh existing lock)
+// -------------------------------------------------------------------
+sal_Int64 NeonSession::LOCK( const ::rtl::OUString & inPath,
+ sal_Int64 nTimeout,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ // Try to get the neon lock from lock store
+ NeonLock * theLock
+ = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) );
+ if ( !theLock )
+ throw DAVException( DAVException::DAV_NOT_LOCKED );
+
+ Init( rEnv );
+
+ // refresh existing lock.
+ theLock->timeout = static_cast< long >( nTimeout );
+
+ TimeValue startCall;
+ osl_getSystemTime( &startCall );
+
+ int theRetVal = ne_lock_refresh( m_pHttpSession, theLock );
+
+ if ( theRetVal == NE_OK )
+ {
+ m_aNeonLockStore.updateLock( theLock,
+ lastChanceToSendRefreshRequest(
+ startCall, theLock->timeout ) );
+ }
+
+ HandleError( theRetVal, inPath, rEnv );
+
+ return theLock->timeout;
+}
+
+// -------------------------------------------------------------------
+// LOCK (refresh existing lock)
+// -------------------------------------------------------------------
+bool NeonSession::LOCK( NeonLock * pLock,
+ sal_Int32 & rlastChanceToSendRefreshRequest )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+#if OSL_DEBUG_LEVEL > 0
+ char * p = ne_uri_unparse( &(pLock->uri) );
+ OSL_TRACE( "NeonSession::LOCK: Refreshing lock for %s.", p );
+ ne_free( p );
+#endif
+
+ // refresh existing lock.
+
+ TimeValue startCall;
+ osl_getSystemTime( &startCall );
+
+ if ( ne_lock_refresh( m_pHttpSession, pLock ) == NE_OK )
+ {
+ rlastChanceToSendRefreshRequest
+ = lastChanceToSendRefreshRequest( startCall, pLock->timeout );
+
+ OSL_TRACE( "Lock successfully refreshed." );
+ return true;
+ }
+ else
+ {
+ OSL_TRACE( "Lock not refreshed!" );
+ return false;
+ }
+}
+
+// -------------------------------------------------------------------
+// UNLOCK
+// -------------------------------------------------------------------
+void NeonSession::UNLOCK( const ::rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+ // get the neon lock from lock store
+ NeonLock * theLock
+ = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) );
+ if ( !theLock )
+ throw DAVException( DAVException::DAV_NOT_LOCKED );
+
+ Init( rEnv );
+
+ int theRetVal = ne_unlock( m_pHttpSession, theLock );
+
+ if ( theRetVal == NE_OK )
+ {
+ m_aNeonLockStore.removeLock( theLock );
+ ne_lock_destroy( theLock );
+ }
+ else
+ {
+ OSL_TRACE( "NeonSession::UNLOCK: unlocking of %s failed.",
+ rtl::OUStringToOString( makeAbsoluteURL( inPath ),
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+
+ HandleError( theRetVal, inPath, rEnv );
+}
+
+// -------------------------------------------------------------------
+// UNLOCK
+// -------------------------------------------------------------------
+bool NeonSession::UNLOCK( NeonLock * pLock )
+{
+ osl::Guard< osl::Mutex > theGuard( m_aMutex );
+
+#if OSL_DEBUG_LEVEL > 0
+ char * p = ne_uri_unparse( &(pLock->uri) );
+ OSL_TRACE( "NeonSession::UNLOCK: Unlocking %s.", p );
+ ne_free( p );
+#endif
+
+ if ( ne_unlock( m_pHttpSession, pLock ) == NE_OK )
+ {
+ OSL_TRACE( "UNLOCK succeeded." );
+ return true;
+ }
+ else
+ {
+ OSL_TRACE( "UNLOCK failed!" );
+ return false;
+ }
+}
+
+// -------------------------------------------------------------------
+void NeonSession::abort()
+ throw ( DAVException )
+{
+ // 11.11.09 (tkr): The following code lines causing crashes if
+ // closing a ongoing connection. It turned out that this existing
+ // solution doesn't work in multi-threading environments.
+ // So I disabled them in 3.2. . Issue #73893# should fix it in OOo 3.3.
+ //if ( m_pHttpSession )
+ // ne_close_connection( m_pHttpSession );
+}
+
+// -------------------------------------------------------------------
+const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const
+{
+ if ( m_aScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "http" ) ) ||
+ m_aScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "https" ) ) )
+ {
+ return m_rProxyDecider.getProxy( m_aScheme,
+ m_aHostName,
+ m_nPort );
+ }
+ else
+ {
+ return m_rProxyDecider.getProxy( m_aScheme,
+ rtl::OUString() /* not used */,
+ -1 /* not used */ );
+ }
+}
+
+// -------------------------------------------------------------------
+namespace {
+
+bool containsLocktoken( const uno::Sequence< ucb::Lock > & rLocks,
+ const char * token )
+{
+ for ( sal_Int32 n = 0; n < rLocks.getLength(); ++n )
+ {
+ const uno::Sequence< rtl::OUString > & rTokens
+ = rLocks[ n ].LockTokens;
+ for ( sal_Int32 m = 0; m < rTokens.getLength(); ++m )
+ {
+ if ( rTokens[ m ].equalsAscii( token ) )
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+// -------------------------------------------------------------------
+bool NeonSession::removeExpiredLocktoken( const rtl::OUString & inURL,
+ const DAVRequestEnvironment & rEnv )
+{
+ NeonLock * theLock = m_aNeonLockStore.findByUri( inURL );
+ if ( !theLock )
+ return false;
+
+ // do a lockdiscovery to check whether this lock is still valid.
+ try
+ {
+ // @@@ Alternative: use ne_lock_discover() => less overhead
+
+ std::vector< DAVResource > aResources;
+ std::vector< rtl::OUString > aPropNames;
+ aPropNames.push_back( DAVProperties::LOCKDISCOVERY );
+
+ PROPFIND( rEnv.m_aRequestURI, DAVZERO, aPropNames, aResources, rEnv );
+
+ if ( aResources.size() == 0 )
+ return false;
+
+ std::vector< DAVPropertyValue >::const_iterator it
+ = aResources[ 0 ].properties.begin();
+ std::vector< DAVPropertyValue >::const_iterator end
+ = aResources[ 0 ].properties.end();
+
+ while ( it != end )
+ {
+ if ( (*it).Name.equals( DAVProperties::LOCKDISCOVERY ) )
+ {
+ uno::Sequence< ucb::Lock > aLocks;
+ if ( !( (*it).Value >>= aLocks ) )
+ return false;
+
+ if ( !containsLocktoken( aLocks, theLock->token ) )
+ {
+ // expired!
+ break;
+ }
+
+ // still valid.
+ return false;
+ }
+ ++it;
+ }
+
+ // No lockdiscovery prop in propfind result / locktoken not found
+ // in propfind result -> not locked
+ OSL_TRACE( "NeonSession::removeExpiredLocktoken: Removing "
+ " expired lock token for %s. token: %s",
+ rtl::OUStringToOString( inURL,
+ RTL_TEXTENCODING_UTF8 ).getStr(),
+ theLock->token );
+
+ m_aNeonLockStore.removeLock( theLock );
+ ne_lock_destroy( theLock );
+ return true;
+ }
+ catch ( DAVException const & )
+ {
+ }
+ return false;
+}
+
+// -------------------------------------------------------------------
+// HandleError
+// Common Error Handler
+// -------------------------------------------------------------------
+void NeonSession::HandleError( int nError,
+ const rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException )
+{
+ m_aEnv = DAVRequestEnvironment();
+
+ // Map error code to DAVException.
+ switch ( nError )
+ {
+ case NE_OK:
+ return;
+
+ case NE_ERROR: // Generic error
+ {
+ rtl::OUString aText = rtl::OUString::createFromAscii(
+ ne_get_error( m_pHttpSession ) );
+
+ sal_uInt16 code = makeStatusCode( aText );
+
+ if ( code == SC_LOCKED )
+ {
+ if ( m_aNeonLockStore.findByUri(
+ makeAbsoluteURL( inPath ) ) == 0 )
+ {
+ // locked by 3rd party
+ throw DAVException( DAVException::DAV_LOCKED );
+ }
+ else
+ {
+ // locked by ourself
+ throw DAVException( DAVException::DAV_LOCKED_SELF );
+ }
+ }
+
+ // Special handling for 400 and 412 status codes, which may indicate
+ // that a lock previously obtained by us has been released meanwhile
+ // by the server. Unfortunately, RFC is not clear at this point,
+ // thus server implementations behave different...
+ else if ( code == SC_BAD_REQUEST || code == SC_PRECONDITION_FAILED )
+ {
+ if ( removeExpiredLocktoken( makeAbsoluteURL( inPath ), rEnv ) )
+ throw DAVException( DAVException::DAV_LOCK_EXPIRED );
+ }
+
+ throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code );
+ }
+ case NE_LOOKUP: // Name lookup failed.
+ throw DAVException( DAVException::DAV_HTTP_LOOKUP,
+ NeonUri::makeConnectionEndPointString(
+ m_aHostName, m_nPort ) );
+
+ case NE_AUTH: // User authentication failed on server
+ throw DAVException( DAVException::DAV_HTTP_AUTH,
+ NeonUri::makeConnectionEndPointString(
+ m_aHostName, m_nPort ) );
+
+ case NE_PROXYAUTH: // User authentication failed on proxy
+ throw DAVException( DAVException::DAV_HTTP_AUTHPROXY,
+ NeonUri::makeConnectionEndPointString(
+ m_aProxyName, m_nProxyPort ) );
+
+ case NE_CONNECT: // Could not connect to server
+ throw DAVException( DAVException::DAV_HTTP_CONNECT,
+ NeonUri::makeConnectionEndPointString(
+ m_aHostName, m_nPort ) );
+
+ case NE_TIMEOUT: // Connection timed out
+ throw DAVException( DAVException::DAV_HTTP_TIMEOUT,
+ NeonUri::makeConnectionEndPointString(
+ m_aHostName, m_nPort ) );
+
+ case NE_FAILED: // The precondition failed
+ throw DAVException( DAVException::DAV_HTTP_FAILED,
+ NeonUri::makeConnectionEndPointString(
+ m_aHostName, m_nPort ) );
+
+ case NE_RETRY: // Retry request (ne_end_request ONLY)
+ throw DAVException( DAVException::DAV_HTTP_RETRY,
+ NeonUri::makeConnectionEndPointString(
+ m_aHostName, m_nPort ) );
+
+ case NE_REDIRECT:
+ {
+ NeonUri aUri( ne_redirect_location( m_pHttpSession ) );
+ throw DAVException(
+ DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() );
+ }
+ default:
+ {
+ OSL_TRACE( "NeonSession::HandleError : Unknown Neon error code!" );
+ throw DAVException( DAVException::DAV_HTTP_ERROR,
+ rtl::OUString::createFromAscii(
+ ne_get_error( m_pHttpSession ) ) );
+ }
+ }
+}
+
+// -------------------------------------------------------------------
+namespace {
+
+void runResponseHeaderHandler( void * userdata,
+ const char * value )
+{
+ rtl::OUString aHeader( rtl::OUString::createFromAscii( value ) );
+ sal_Int32 nPos = aHeader.indexOf( ':' );
+
+ if ( nPos != -1 )
+ {
+ rtl::OUString aHeaderName( aHeader.copy( 0, nPos ) );
+
+ NeonRequestContext * pCtx
+ = static_cast< NeonRequestContext * >( userdata );
+
+ // Note: Empty vector means that all headers are requested.
+ bool bIncludeIt = ( pCtx->pHeaderNames->size() == 0 );
+
+ if ( !bIncludeIt )
+ {
+ // Check whether this header was requested.
+ std::vector< ::rtl::OUString >::const_iterator it(
+ pCtx->pHeaderNames->begin() );
+ const std::vector< ::rtl::OUString >::const_iterator end(
+ pCtx->pHeaderNames->end() );
+
+ while ( it != end )
+ {
+ // header names are case insensitive
+ if ( (*it).equalsIgnoreAsciiCase( aHeaderName ) )
+ {
+ aHeaderName = (*it);
+ break;
+ }
+ ++it;
+ }
+
+ if ( it != end )
+ bIncludeIt = true;
+ }
+
+ if ( bIncludeIt )
+ {
+ // Create & set the PropertyValue
+ DAVPropertyValue thePropertyValue;
+ thePropertyValue.IsCaseSensitive = false;
+ thePropertyValue.Name = aHeaderName;
+
+ if ( nPos < aHeader.getLength() )
+ thePropertyValue.Value <<= aHeader.copy( nPos + 1 ).trim();
+
+ // Add the newly created PropertyValue
+ pCtx->pResource->properties.push_back( thePropertyValue );
+ }
+ }
+}
+
+} // namespace
+
+// -------------------------------------------------------------------
+// static
+int NeonSession::GET( ne_session * sess,
+ const char * uri,
+ ne_block_reader reader,
+ bool getheaders,
+ void * userdata )
+{
+ //struct get_context ctx;
+ ne_request * req = ne_request_create( sess, "GET", uri );
+ int ret;
+ void *cursor = NULL;
+ const char *name, *value;
+
+#if NEON_VERSION < 0x0250
+ if ( getheaders )
+ ne_add_response_header_catcher(
+ req, runResponseHeaderHandler, userdata );
+#endif
+ ne_decompress * dc
+ = ne_decompress_reader( req, ne_accept_2xx, reader, userdata );
+
+ ret = ne_request_dispatch( req );
+
+#if NEON_VERSION >= 0x0250
+ if ( getheaders )
+ {
+ while ( ( cursor = ne_response_header_iterate(
+ req, cursor, &name, &value ) ) != NULL )
+ {
+ char buffer[8192];
+
+ ne_snprintf(buffer, sizeof buffer, "%s: %s", name, value);
+ runResponseHeaderHandler(userdata, buffer);
+ }
+ }
+#endif
+ if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
+ ret = NE_ERROR;
+
+ if ( dc != 0 )
+ ne_decompress_destroy(dc);
+
+ ne_request_destroy( req );
+ return ret;
+}
+
+// -------------------------------------------------------------------
+// static
+int NeonSession::PUT( ne_session * sess,
+ const char * uri,
+ const char * buffer,
+ size_t size)
+{
+ ne_request * req = ne_request_create( sess, "PUT", uri );
+ int ret;
+
+ ne_lock_using_resource( req, uri, 0 );
+ ne_lock_using_parent( req, uri );
+
+ ne_set_request_body_buffer( req, buffer, size );
+
+ ret = ne_request_dispatch( req );
+
+ if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
+ ret = NE_ERROR;
+
+ ne_request_destroy( req );
+ return ret;
+}
+
+// -------------------------------------------------------------------
+int NeonSession::POST( ne_session * sess,
+ const char * uri,
+ const char * buffer,
+ ne_block_reader reader,
+ void * userdata,
+ const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer )
+{
+ ne_request * req = ne_request_create( sess, "POST", uri );
+ //struct get_context ctx;
+ int ret;
+
+ RequestDataMap * pData = 0;
+
+ if ( rContentType.getLength() || rReferer.getLength() )
+ {
+ // Remember contenttype and referer. Data will be added to HTTP request
+ // header in in 'PreSendRequest' callback.
+ pData = static_cast< RequestDataMap* >( m_pRequestData );
+ (*pData)[ req ] = RequestData( rContentType, rReferer );
+ }
+
+ //ctx.total = -1;
+ //ctx.fd = fd;
+ //ctx.error = 0;
+ //ctx.session = sess;
+
+ ///* Read the value of the Content-Length header into ctx.total */
+ //ne_add_response_header_handler( req, "Content-Length",
+ // ne_handle_numeric_header, &ctx.total );
+
+ ne_add_response_body_reader( req, ne_accept_2xx, reader, userdata );
+
+ ne_set_request_body_buffer( req, buffer, strlen( buffer ) );
+
+ ret = ne_request_dispatch( req );
+
+ //if ( ctx.error )
+ // ret = NE_ERROR;
+ //else
+ if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
+ ret = NE_ERROR;
+
+ ne_request_destroy( req );
+
+ if ( pData )
+ {
+ // Remove request data from session's list.
+ RequestDataMap::iterator it = pData->find( req );
+ if ( it != pData->end() )
+ pData->erase( it );
+ }
+
+ return ret;
+}
+
+// -------------------------------------------------------------------
+// static
+bool
+NeonSession::getDataFromInputStream(
+ const uno::Reference< io::XInputStream > & xStream,
+ uno::Sequence< sal_Int8 > & rData,
+ bool bAppendTrailingZeroByte )
+{
+ if ( xStream.is() )
+ {
+ uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY );
+ if ( xSeekable.is() )
+ {
+ try
+ {
+ sal_Int32 nSize
+ = sal::static_int_cast<sal_Int32>(xSeekable->getLength());
+ sal_Int32 nRead
+ = xStream->readBytes( rData, nSize );
+
+ if ( nRead == nSize )
+ {
+ if ( bAppendTrailingZeroByte )
+ {
+ rData.realloc( nSize + 1 );
+ rData[ nSize ] = sal_Int8( 0 );
+ }
+ return true;
+ }
+ }
+ catch ( io::NotConnectedException const & )
+ {
+ // readBytes
+ }
+ catch ( io::BufferSizeExceededException const & )
+ {
+ // readBytes
+ }
+ catch ( io::IOException const & )
+ {
+ // getLength, readBytes
+ }
+ }
+ else
+ {
+ try
+ {
+ uno::Sequence< sal_Int8 > aBuffer;
+ sal_Int32 nPos = 0;
+
+ sal_Int32 nRead = xStream->readSomeBytes( aBuffer, 65536 );
+ while ( nRead > 0 )
+ {
+ if ( rData.getLength() < ( nPos + nRead ) )
+ rData.realloc( nPos + nRead );
+
+ aBuffer.realloc( nRead );
+ rtl_copyMemory( (void*)( rData.getArray() + nPos ),
+ (const void*)aBuffer.getConstArray(),
+ nRead );
+ nPos += nRead;
+
+ aBuffer.realloc( 0 );
+ nRead = xStream->readSomeBytes( aBuffer, 65536 );
+ }
+
+ if ( bAppendTrailingZeroByte )
+ {
+ rData.realloc( nPos + 1 );
+ rData[ nPos ] = sal_Int8( 0 );
+ }
+ return true;
+ }
+ catch ( io::NotConnectedException const & )
+ {
+ // readBytes
+ }
+ catch ( io::BufferSizeExceededException const & )
+ {
+ // readBytes
+ }
+ catch ( io::IOException const & )
+ {
+ // readBytes
+ }
+ }
+ }
+ return false;
+}
+
+// ---------------------------------------------------------------------
+sal_Bool
+NeonSession::isDomainMatch( rtl::OUString certHostName )
+{
+ rtl::OUString hostName = getHostName();
+
+ if (hostName.equalsIgnoreAsciiCase( certHostName ) )
+ return sal_True;
+
+ if ( 0 == certHostName.indexOf( rtl::OUString::createFromAscii( "*" ) ) &&
+ hostName.getLength() >= certHostName.getLength() )
+ {
+ rtl::OUString cmpStr = certHostName.copy( 1 );
+
+ if ( hostName.matchIgnoreAsciiCase(
+ cmpStr, hostName.getLength() - cmpStr.getLength() ) )
+ return sal_True;
+ }
+ return sal_False;
+}
+
+// ---------------------------------------------------------------------
+rtl::OUString NeonSession::makeAbsoluteURL( rtl::OUString const & rURL ) const
+{
+ try
+ {
+ // Is URL relative or already absolute?
+ if ( rURL[ 0 ] != sal_Unicode( '/' ) )
+ {
+ // absolute.
+ return rtl::OUString( rURL );
+ }
+ else
+ {
+ ne_uri aUri;
+ memset( &aUri, 0, sizeof( aUri ) );
+
+ ne_fill_server_uri( m_pHttpSession, &aUri );
+ aUri.path
+ = ne_strdup( rtl::OUStringToOString(
+ rURL, RTL_TEXTENCODING_UTF8 ).getStr() );
+ NeonUri aNeonUri( &aUri );
+ ne_uri_free( &aUri );
+ return aNeonUri.GetURI();
+ }
+ }
+ catch ( DAVException const & )
+ {
+ }
+ // error.
+ return rtl::OUString();
+}
diff --git a/ucb/source/ucp/webdav/NeonSession.hxx b/ucb/source/ucp/webdav/NeonSession.hxx
new file mode 100644
index 000000000000..65c2c25e4ec9
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonSession.hxx
@@ -0,0 +1,295 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _NEONSESSION_HXX_
+#define _NEONSESSION_HXX_
+
+#include <vector>
+#include <osl/mutex.hxx>
+#include "DAVSession.hxx"
+#include "NeonTypes.hxx"
+#include "NeonLockStore.hxx"
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+namespace ucbhelper { class ProxyDecider; }
+
+namespace webdav_ucp
+{
+
+// -------------------------------------------------------------------
+// NeonSession
+// A DAVSession implementation using the neon/expat library
+// -------------------------------------------------------------------
+
+class NeonSession : public DAVSession
+{
+private:
+ osl::Mutex m_aMutex;
+ rtl::OUString m_aScheme;
+ rtl::OUString m_aHostName;
+ rtl::OUString m_aProxyName;
+ sal_Int32 m_nPort;
+ sal_Int32 m_nProxyPort;
+ HttpSession * m_pHttpSession;
+ void * m_pRequestData;
+ const ucbhelper::InternetProxyDecider & m_rProxyDecider;
+
+ // @@@ This should really be per-request data. But Neon currently
+ // (0.23.5) has no interface for passing per-request user data.
+ // Theoretically, a NeonSession instance could handle multiple requests
+ // at a time --currently it doesn't. Thus this is not an issue at the
+ // moment.
+ DAVRequestEnvironment m_aEnv;
+
+ static bool m_bGlobalsInited;
+ static osl::Mutex m_aGlobalMutex;
+ static NeonLockStore m_aNeonLockStore;
+
+protected:
+ virtual ~NeonSession();
+
+public:
+ NeonSession( const rtl::Reference< DAVSessionFactory > & rSessionFactory,
+ const rtl::OUString& inUri,
+ const ucbhelper::InternetProxyDecider & rProxyDecider )
+ throw ( DAVException );
+
+ // DAVSession methods
+ virtual sal_Bool CanUse( const ::rtl::OUString & inUri );
+
+ virtual sal_Bool UsesProxy();
+
+ const DAVRequestEnvironment & getRequestEnvironment() const
+ { return m_aEnv; }
+
+ virtual void
+ OPTIONS( const ::rtl::OUString & inPath,
+ DAVCapabilities & outCapabilities,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ // allprop & named
+ virtual void
+ PROPFIND( const ::rtl::OUString & inPath,
+ const Depth inDepth,
+ const std::vector< ::rtl::OUString > & inPropNames,
+ std::vector< DAVResource > & ioResources,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ // propnames
+ virtual void
+ PROPFIND( const ::rtl::OUString & inPath,
+ const Depth inDepth,
+ std::vector< DAVResourceInfo >& ioResInfo,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void
+ PROPPATCH( const ::rtl::OUString & inPath,
+ const std::vector< ProppatchValue > & inValues,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void
+ HEAD( const ::rtl::OUString & inPath,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ GET( const ::rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void
+ GET( const ::rtl::OUString & inPath,
+ com::sun::star::uno::Reference<
+ com::sun::star::io::XOutputStream > & ioOutputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ GET( const ::rtl::OUString & inPath,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void
+ GET( const ::rtl::OUString & inPath,
+ com::sun::star::uno::Reference<
+ com::sun::star::io::XOutputStream > & ioOutputStream,
+ const std::vector< ::rtl::OUString > & inHeaderNames,
+ DAVResource & ioResource,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void
+ PUT( const ::rtl::OUString & inPath,
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & inInputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
+ POST( const rtl::OUString & inPath,
+ const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer,
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & inInputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void
+ POST( const rtl::OUString & inPath,
+ const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer,
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & inInputStream,
+ com::sun::star::uno::Reference<
+ com::sun::star::io::XOutputStream > & oOutputStream,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void
+ MKCOL( const ::rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void
+ COPY( const ::rtl::OUString & inSourceURL,
+ const ::rtl::OUString & inDestinationURL,
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool inOverWrite )
+ throw ( DAVException );
+
+ virtual void
+ MOVE( const ::rtl::OUString & inSourceURL,
+ const ::rtl::OUString & inDestinationURL,
+ const DAVRequestEnvironment & rEnv,
+ sal_Bool inOverWrite )
+ throw ( DAVException );
+
+ virtual void DESTROY( const ::rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ // set new lock.
+ virtual void LOCK( const ::rtl::OUString & inURL,
+ com::sun::star::ucb::Lock & inLock,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ // refresh existing lock.
+ virtual sal_Int64 LOCK( const ::rtl::OUString & inURL,
+ sal_Int64 nTimeout,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ virtual void UNLOCK( const ::rtl::OUString & inURL,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ // helpers
+ virtual void abort()
+ throw ( DAVException );
+
+ const rtl::OUString & getHostName() const { return m_aHostName; }
+
+ const ::uno::Reference< ::lang::XMultiServiceFactory > getMSF()
+ { return m_xFactory->getServiceFactory(); }
+
+ const void * getRequestData() const { return m_pRequestData; }
+
+ sal_Bool isDomainMatch( rtl::OUString certHostName );
+
+private:
+ friend class NeonLockStore;
+
+ void Init( void )
+ throw ( DAVException );
+
+ void Init( const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ // ret: true => retry request.
+ void HandleError( int nError,
+ const rtl::OUString & inPath,
+ const DAVRequestEnvironment & rEnv )
+ throw ( DAVException );
+
+ const ucbhelper::InternetProxyServer & getProxySettings() const;
+
+ bool removeExpiredLocktoken( const rtl::OUString & inURL,
+ const DAVRequestEnvironment & rEnv );
+
+ // refresh lock, called by NeonLockStore::refreshLocks
+ bool LOCK( NeonLock * pLock,
+ sal_Int32 & rlastChanceToSendRefreshRequest );
+
+ // unlock, called by NeonLockStore::~NeonLockStore
+ bool UNLOCK( NeonLock * pLock );
+
+ // low level GET implementation, used by public GET implementations
+ static int GET( ne_session * sess,
+ const char * uri,
+ ne_block_reader reader,
+ bool getheaders,
+ void * userdata );
+
+ // Buffer-based PUT implementation. Neon only has file descriptor-
+ // based API.
+ static int PUT( ne_session * sess,
+ const char * uri,
+ const char * buffer,
+ size_t size );
+
+ // Buffer-based POST implementation. Neon only has file descriptor-
+ // based API.
+ int POST( ne_session * sess,
+ const char * uri,
+ const char * buffer,
+ ne_block_reader reader,
+ void * userdata,
+ const rtl::OUString & rContentType,
+ const rtl::OUString & rReferer );
+
+ // Helper: XInputStream -> Sequence< sal_Int8 >
+ static bool getDataFromInputStream(
+ const com::sun::star::uno::Reference<
+ com::sun::star::io::XInputStream > & xStream,
+ com::sun::star::uno::Sequence< sal_Int8 > & rData,
+ bool bAppendTrailingZeroByte );
+
+ rtl::OUString makeAbsoluteURL( rtl::OUString const & rURL ) const;
+};
+
+} // namespace webdav_ucp
+
+#endif // _NEONSESSION_HXX_
diff --git a/ucb/source/ucp/webdav/NeonTypes.hxx b/ucb/source/ucp/webdav/NeonTypes.hxx
new file mode 100644
index 000000000000..21902f352691
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonTypes.hxx
@@ -0,0 +1,46 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _NEONTYPES_HXX_
+#define _NEONTYPES_HXX_
+
+#include <ne_session.h>
+#include <ne_utils.h>
+#include <ne_basic.h>
+#include <ne_props.h>
+#include <ne_locks.h>
+
+typedef ne_session HttpSession;
+typedef ne_status HttpStatus;
+typedef ne_server_capabilities HttpServerCapabilities;
+
+typedef ne_propname NeonPropName;
+typedef ne_prop_result_set NeonPropFindResultSet;
+
+typedef struct ne_lock NeonLock;
+
+#endif // _NEONTYPES_HXX_
diff --git a/ucb/source/ucp/webdav/NeonUri.cxx b/ucb/source/ucp/webdav/NeonUri.cxx
new file mode 100644
index 000000000000..774faa06b9dd
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonUri.cxx
@@ -0,0 +1,358 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <string.h>
+#include <rtl/uri.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include "ne_alloc.h"
+#include "NeonUri.hxx"
+#include "DAVException.hxx"
+
+#include "../inc/urihelper.hxx"
+
+using namespace webdav_ucp;
+
+# if defined __SUNPRO_CC
+// FIXME: not sure whether initializing a ne_uri statically is supposed to work
+// the string fields of ne_uri are char*, not const char*
+# pragma disable_warn
+# endif
+
+#if defined __GNUC__
+#define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+/* Diagnostics pragma was introduced with gcc-4.2.1 */
+#if GCC_VERSION > 40201
+#pragma GCC diagnostic ignored "-Wwrite-strings"
+#endif
+#endif
+
+namespace {
+
+const ne_uri g_sUriDefaultsHTTP = { "http",
+#if NEON_VERSION >= 0x0260
+ NULL,
+#endif
+ NULL,
+ DEFAULT_HTTP_PORT,
+#if NEON_VERSION >= 0x0260
+ NULL,
+#endif
+ NULL,
+ NULL };
+const ne_uri g_sUriDefaultsHTTPS = { "https",
+#if NEON_VERSION >= 0x0260
+ NULL,
+#endif
+ NULL,
+ DEFAULT_HTTPS_PORT,
+#if NEON_VERSION >= 0x0260
+ NULL,
+#endif
+ NULL,
+ NULL };
+const ne_uri g_sUriDefaultsFTP = { "ftp",
+#if NEON_VERSION >= 0x0260
+ NULL,
+#endif
+ NULL,
+ DEFAULT_FTP_PORT,
+#if NEON_VERSION >= 0x0260
+ NULL,
+#endif
+ NULL,
+ NULL };
+} // namespace
+
+# if defined __SUNPRO_CC
+# pragma enable_warn
+#endif
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+
+namespace {
+
+//TODO! rtl::OString::matchIgnoreAsciiCaseAsciiL() missing
+inline bool matchIgnoreAsciiCase(rtl::OString const & rStr1,
+ sal_Char const * pStr2,
+ sal_Int32 nStr2Len) SAL_THROW(())
+{
+ return
+ rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
+ rStr1.getStr(), rStr1.getLength(), pStr2, nStr2Len, nStr2Len)
+ == 0;
+}
+
+}
+
+NeonUri::NeonUri( const ne_uri * inUri )
+ throw ( DAVException )
+{
+ if ( inUri == 0 )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ char * uri = ne_uri_unparse( inUri );
+
+ if ( uri == 0 )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ init( rtl::OString( uri ), inUri );
+ ne_free( uri );
+
+ calculateURI();
+}
+
+NeonUri::NeonUri( const rtl::OUString & inUri )
+ throw ( DAVException )
+{
+ if ( inUri.getLength() <= 0 )
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+
+ // #i77023#
+ rtl::OUString aEscapedUri( ucb_impl::urihelper::encodeURI( inUri ) );
+
+ rtl::OString theInputUri(
+ aEscapedUri.getStr(), aEscapedUri.getLength(), RTL_TEXTENCODING_UTF8 );
+
+ ne_uri theUri;
+ if ( ne_uri_parse( theInputUri.getStr(), &theUri ) != 0 )
+ {
+ ne_uri_free( &theUri );
+ throw DAVException( DAVException::DAV_INVALID_ARG );
+ }
+
+ init( theInputUri, &theUri );
+ ne_uri_free( &theUri );
+
+ calculateURI();
+}
+
+void NeonUri::init( const rtl::OString & rUri, const ne_uri * pUri )
+{
+ // Complete URI.
+ const ne_uri * pUriDefs
+ = matchIgnoreAsciiCase( rUri,
+ RTL_CONSTASCII_STRINGPARAM( "ftp:" ) ) ?
+ &g_sUriDefaultsFTP :
+ matchIgnoreAsciiCase( rUri,
+ RTL_CONSTASCII_STRINGPARAM( "https:" ) ) ?
+ &g_sUriDefaultsHTTPS :
+ &g_sUriDefaultsHTTP;
+
+ mScheme = rtl::OStringToOUString(
+ pUri->scheme ? pUri->scheme : pUriDefs->scheme,
+ RTL_TEXTENCODING_UTF8 );
+ mUserInfo = rtl::OStringToOUString(
+#if NEON_VERSION >= 0x0260
+ pUri->userinfo ? pUri->userinfo : pUriDefs->userinfo,
+#else
+ pUri->authinfo ? pUri->authinfo : pUriDefs->authinfo,
+#endif
+ RTL_TEXTENCODING_UTF8 );
+ mHostName = rtl::OStringToOUString(
+ pUri->host ? pUri->host : pUriDefs->host,
+ RTL_TEXTENCODING_UTF8 );
+ mPort = pUri->port > 0 ? pUri->port : pUriDefs->port;
+ mPath = rtl::OStringToOUString(
+ pUri->path ? pUri->path : pUriDefs->path,
+ RTL_TEXTENCODING_UTF8 );
+
+#if NEON_VERSION >= 0x0260
+ if ( pUri->query )
+ {
+ mPath += rtl::OUString::createFromAscii( "?" );
+ mPath += rtl::OStringToOUString(
+ pUri->query, RTL_TEXTENCODING_UTF8 );
+ }
+
+ if ( pUri->fragment )
+ {
+ mPath += rtl::OUString::createFromAscii( "#" );
+ mPath += rtl::OStringToOUString(
+ pUri->fragment, RTL_TEXTENCODING_UTF8 );
+ }
+#endif
+}
+
+// -------------------------------------------------------------------
+// Destructor
+// -------------------------------------------------------------------
+NeonUri::~NeonUri( )
+{
+}
+
+void NeonUri::calculateURI ()
+{
+ rtl::OUStringBuffer aBuf( mScheme );
+ aBuf.appendAscii( "://" );
+ if ( mUserInfo.getLength() > 0 )
+ {
+ //TODO! differentiate between empty and missing userinfo
+ aBuf.append( mUserInfo );
+ aBuf.appendAscii( "@" );
+ }
+ // Is host a numeric IPv6 address?
+ if ( ( mHostName.indexOf( ':' ) != -1 ) &&
+ ( mHostName[ 0 ] != sal_Unicode( '[' ) ) )
+ {
+ aBuf.appendAscii( "[" );
+ aBuf.append( mHostName );
+ aBuf.appendAscii( "]" );
+ }
+ else
+ {
+ aBuf.append( mHostName );
+ }
+
+ // append port, but only, if not default port.
+ bool bAppendPort = true;
+ switch ( mPort )
+ {
+ case DEFAULT_HTTP_PORT:
+ bAppendPort
+ = !mScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "http" ) );
+ break;
+
+ case DEFAULT_HTTPS_PORT:
+ bAppendPort
+ = !mScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "https" ) );
+ break;
+
+ case DEFAULT_FTP_PORT:
+ bAppendPort
+ = !mScheme.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ftp" ) );
+ break;
+ }
+ if ( bAppendPort )
+ {
+ aBuf.appendAscii( ":" );
+ aBuf.append( rtl::OUString::valueOf( mPort ) );
+ }
+ aBuf.append( mPath );
+
+ mURI = aBuf.makeStringAndClear();
+}
+
+::rtl::OUString NeonUri::GetPathBaseName () const
+{
+ sal_Int32 nPos = mPath.lastIndexOf ('/');
+ sal_Int32 nTrail = 0;
+ if (nPos == mPath.getLength () - 1)
+ {
+ // Trailing slash found. Skip.
+ nTrail = 1;
+ nPos = mPath.lastIndexOf ('/', nPos);
+ }
+ if (nPos != -1)
+ {
+ rtl::OUString aTemp(
+ mPath.copy (nPos + 1, mPath.getLength () - nPos - 1 - nTrail) );
+
+ // query, fragment present?
+ nPos = aTemp.indexOf( '?' );
+ if ( nPos == -1 )
+ nPos = aTemp.indexOf( '#' );
+
+ if ( nPos != -1 )
+ aTemp = aTemp.copy( 0, nPos );
+
+ return aTemp;
+ }
+ else
+ return rtl::OUString::createFromAscii ("/");
+}
+
+bool NeonUri::operator== ( const NeonUri & rOther ) const
+{
+ return ( mURI == rOther.mURI );
+}
+
+::rtl::OUString NeonUri::GetPathBaseNameUnescaped () const
+{
+ return unescape( GetPathBaseName() );
+}
+
+void NeonUri::AppendPath (const rtl::OUString& rPath)
+{
+ if (mPath.lastIndexOf ('/') != mPath.getLength () - 1)
+ mPath += rtl::OUString::createFromAscii ("/");
+
+ mPath += rPath;
+ calculateURI ();
+};
+
+// static
+rtl::OUString NeonUri::escapeSegment( const rtl::OUString& segment )
+{
+ return rtl::Uri::encode( segment,
+ rtl_UriCharClassPchar,
+ rtl_UriEncodeIgnoreEscapes,
+ RTL_TEXTENCODING_UTF8 );
+}
+
+// static
+rtl::OUString NeonUri::unescape( const rtl::OUString& segment )
+{
+ return rtl::Uri::decode( segment,
+ rtl_UriDecodeWithCharset,
+ RTL_TEXTENCODING_UTF8 );
+}
+
+// static
+rtl::OUString NeonUri::makeConnectionEndPointString(
+ const rtl::OUString & rHostName, int nPort )
+{
+ rtl::OUStringBuffer aBuf;
+
+ // Is host a numeric IPv6 address?
+ if ( ( rHostName.indexOf( ':' ) != -1 ) &&
+ ( rHostName[ 0 ] != sal_Unicode( '[' ) ) )
+ {
+ aBuf.appendAscii( "[" );
+ aBuf.append( rHostName );
+ aBuf.appendAscii( "]" );
+ }
+ else
+ {
+ aBuf.append( rHostName );
+ }
+
+ if ( ( nPort != DEFAULT_HTTP_PORT ) && ( nPort != DEFAULT_HTTPS_PORT ) )
+ {
+ aBuf.appendAscii( ":" );
+ aBuf.append( rtl::OUString::valueOf( sal_Int32( nPort ) ) );
+ }
+ return aBuf.makeStringAndClear();
+}
+
diff --git a/ucb/source/ucp/webdav/NeonUri.hxx b/ucb/source/ucp/webdav/NeonUri.hxx
new file mode 100644
index 000000000000..c83ca47d5a1c
--- /dev/null
+++ b/ucb/source/ucp/webdav/NeonUri.hxx
@@ -0,0 +1,102 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _NEONURI_HXX_
+#define _NEONURI_HXX_
+
+#include <ne_uri.h>
+#include <rtl/ustring.hxx>
+#include <DAVException.hxx>
+
+namespace webdav_ucp
+{
+
+#define DEFAULT_HTTP_PORT 80
+#define DEFAULT_HTTPS_PORT 443
+#define DEFAULT_FTP_PORT 21
+
+// -------------------------------------------------------------------
+// NeonUri
+// A URI implementation for use with the neon/expat library
+// -------------------------------------------------------------------
+class NeonUri
+{
+ private:
+ ::rtl::OUString mURI;
+ ::rtl::OUString mScheme;
+ ::rtl::OUString mUserInfo;
+ ::rtl::OUString mHostName;
+ sal_Int32 mPort;
+ ::rtl::OUString mPath;
+
+ void init( const rtl::OString & rUri, const ne_uri * pUri );
+ void calculateURI ();
+
+ public:
+ NeonUri( const ::rtl::OUString & inUri ) throw ( DAVException );
+ NeonUri( const ne_uri * inUri ) throw ( DAVException );
+ ~NeonUri( );
+
+ bool operator== ( const NeonUri & rOther ) const;
+ bool operator!= ( const NeonUri & rOther ) const
+ { return !operator==( rOther ); }
+
+ const ::rtl::OUString & GetURI( void ) const
+ { return mURI; };
+ const ::rtl::OUString & GetScheme( void ) const
+ { return mScheme; };
+ const ::rtl::OUString & GetUserInfo( void ) const
+ { return mUserInfo; };
+ const ::rtl::OUString & GetHost( void ) const
+ { return mHostName; };
+ sal_Int32 GetPort( void ) const
+ { return mPort; };
+ const ::rtl::OUString & GetPath( void ) const
+ { return mPath; };
+
+ ::rtl::OUString GetPathBaseName ( void ) const;
+
+ ::rtl::OUString GetPathBaseNameUnescaped ( void ) const;
+
+ void SetScheme (const ::rtl::OUString& scheme)
+ { mScheme = scheme; calculateURI (); };
+
+ void AppendPath (const ::rtl::OUString& rPath);
+
+ static ::rtl::OUString escapeSegment( const ::rtl::OUString& segment );
+ static ::rtl::OUString unescape( const ::rtl::OUString& string );
+
+ // "host:port", omit ":port" for port 80 and 443
+ static rtl::OUString makeConnectionEndPointString(
+ const rtl::OUString & rHostName,
+ int nPort );
+ rtl::OUString makeConnectionEndPointString() const
+ { return makeConnectionEndPointString( GetHost(), GetPort() ); }
+};
+
+} // namespace webdav_ucp
+
+#endif // _NEONURI_HXX_
diff --git a/ucb/source/ucp/webdav/PropertyMap.hxx b/ucb/source/ucp/webdav/PropertyMap.hxx
new file mode 100644
index 000000000000..624187b1746e
--- /dev/null
+++ b/ucb/source/ucp/webdav/PropertyMap.hxx
@@ -0,0 +1,65 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WEBDAV_UCP_PROPERTYMAP_HXX
+#define _WEBDAV_UCP_PROPERTYMAP_HXX
+
+#include <hash_set>
+#include <com/sun/star/beans/Property.hpp>
+
+namespace webdav_ucp {
+
+//=========================================================================
+
+struct equalPropertyName
+{
+ bool operator()( const ::com::sun::star::beans::Property & p1,
+ const ::com::sun::star::beans::Property & p2 ) const
+ {
+ return !!( p1.Name == p2.Name );
+ }
+};
+
+struct hashPropertyName
+{
+ size_t operator()( const ::com::sun::star::beans::Property & p ) const
+ {
+ return p.Name.hashCode();
+ }
+};
+
+typedef std::hash_set
+<
+ ::com::sun::star::beans::Property,
+ hashPropertyName,
+ equalPropertyName
+>
+PropertyMap;
+
+}
+
+#endif
diff --git a/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx b/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx
new file mode 100644
index 000000000000..1ce4c70e6b21
--- /dev/null
+++ b/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx
@@ -0,0 +1,547 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+#include <string.h>
+#include <ne_xml.h>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+#include "UCBDeadPropertyValue.hxx"
+
+using namespace webdav_ucp;
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////
+
+struct UCBDeadPropertyValueParseContext
+{
+ rtl::OUString * pType;
+ rtl::OUString * pValue;
+
+ UCBDeadPropertyValueParseContext() : pType( 0 ), pValue( 0 ) {}
+ ~UCBDeadPropertyValueParseContext() { delete pType; delete pValue; }
+};
+
+// static
+const rtl::OUString UCBDeadPropertyValue::aTypeString
+ = rtl::OUString::createFromAscii( "string" );
+const rtl::OUString UCBDeadPropertyValue::aTypeLong
+ = rtl::OUString::createFromAscii( "long" );
+const rtl::OUString UCBDeadPropertyValue::aTypeShort
+ = rtl::OUString::createFromAscii( "short" );
+const rtl::OUString UCBDeadPropertyValue::aTypeBoolean
+ = rtl::OUString::createFromAscii( "boolean" );
+const rtl::OUString UCBDeadPropertyValue::aTypeChar
+ = rtl::OUString::createFromAscii( "char" );
+const rtl::OUString UCBDeadPropertyValue::aTypeByte
+ = rtl::OUString::createFromAscii( "byte" );
+const rtl::OUString UCBDeadPropertyValue::aTypeHyper
+ = rtl::OUString::createFromAscii( "hyper" );
+const rtl::OUString UCBDeadPropertyValue::aTypeFloat
+ = rtl::OUString::createFromAscii( "float" );
+const rtl::OUString UCBDeadPropertyValue::aTypeDouble
+ = rtl::OUString::createFromAscii( "double" );
+
+// static
+const rtl::OUString UCBDeadPropertyValue::aXMLPre
+ = rtl::OUString::createFromAscii( "<ucbprop><type>" );
+const rtl::OUString UCBDeadPropertyValue::aXMLMid
+ = rtl::OUString::createFromAscii( "</type><value>" );
+const rtl::OUString UCBDeadPropertyValue::aXMLEnd
+ = rtl::OUString::createFromAscii( "</value></ucbprop>" );
+
+#define STATE_TOP (1)
+
+#define STATE_UCBPROP (STATE_TOP)
+#define STATE_TYPE (STATE_TOP + 1)
+#define STATE_VALUE (STATE_TOP + 2)
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int UCBDeadPropertyValue_startelement_callback(
+ void *,
+ int parent,
+ const char * /*nspace*/,
+ const char *name,
+ const char ** )
+{
+ if ( name != 0 )
+ {
+ switch ( parent )
+ {
+ case NE_XML_STATEROOT:
+ if ( strcmp( name, "ucbprop" ) == 0 )
+ return STATE_UCBPROP;
+ break;
+
+ case STATE_UCBPROP:
+ if ( strcmp( name, "type" ) == 0 )
+ return STATE_TYPE;
+ else if ( strcmp( name, "value" ) == 0 )
+ return STATE_VALUE;
+ break;
+ }
+ }
+ return NE_XML_DECLINE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int UCBDeadPropertyValue_chardata_callback(
+ void *userdata,
+ int state,
+ const char *buf,
+ size_t len )
+{
+ UCBDeadPropertyValueParseContext * pCtx
+ = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
+
+ switch ( state )
+ {
+ case STATE_TYPE:
+ OSL_ENSURE( !pCtx->pType,
+ "UCBDeadPropertyValue_endelement_callback - "
+ "Type already set!" );
+ pCtx->pType
+ = new rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
+ break;
+
+ case STATE_VALUE:
+ OSL_ENSURE( !pCtx->pValue,
+ "UCBDeadPropertyValue_endelement_callback - "
+ "Value already set!" );
+ pCtx->pValue
+ = new rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
+ break;
+ }
+ return 0; // zero to continue, non-zero to abort parsing
+}
+
+//////////////////////////////////////////////////////////////////////////
+extern "C" int UCBDeadPropertyValue_endelement_callback(
+ void *userdata,
+ int state,
+ const char *,
+ const char * )
+{
+ UCBDeadPropertyValueParseContext * pCtx
+ = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
+
+ switch ( state )
+ {
+ case STATE_TYPE:
+ if ( !pCtx->pType )
+ return 1; // abort
+ break;
+
+ case STATE_VALUE:
+ if ( !pCtx->pValue )
+ return 1; // abort
+ break;
+
+ case STATE_UCBPROP:
+ if ( !pCtx->pType || ! pCtx->pValue )
+ return 1; // abort
+ break;
+ }
+ return 0; // zero to continue, non-zero to abort parsing
+}
+
+//////////////////////////////////////////////////////////////////////////
+static rtl::OUString encodeValue( const rtl::OUString & rValue )
+{
+ // Note: I do not use the usual &amp; + &lt; + &gt; encoding, because
+ // I want to prevent any XML parser from trying to 'understand'
+ // the value. This caused problems:
+ //
+ // Example:
+ // - Unencoded property value: x<z
+ // PROPPATCH:
+ // - Encoded property value: x&lt;z
+ // - UCBDeadPropertyValue::toXML result:
+ // <ucbprop><type>string</type><value>x&lt;z</value></ucbprop>
+ // PROPFIND:
+ // - parser replaces &lt; by > ==> error (not well formed)
+
+ rtl::OUStringBuffer aResult;
+ const sal_Unicode * pValue = rValue.getStr();
+
+ sal_Int32 nCount = rValue.getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const sal_Unicode c = pValue[ n ];
+
+ if ( '%' == c )
+ aResult.appendAscii( "%per;" );
+ else if ( '<' == c )
+ aResult.appendAscii( "%lt;" );
+ else if ( '>' == c )
+ aResult.appendAscii( "%gt;" );
+ else
+ aResult.append( c );
+ }
+ return rtl::OUString( aResult );
+}
+
+//////////////////////////////////////////////////////////////////////////
+static rtl::OUString decodeValue( const rtl::OUString & rValue )
+{
+ rtl::OUStringBuffer aResult;
+ const sal_Unicode * pValue = rValue.getStr();
+
+ sal_Int32 nPos = 0;
+ sal_Int32 nEnd = rValue.getLength();
+
+ while ( nPos < nEnd )
+ {
+ sal_Unicode c = pValue[ nPos ];
+
+ if ( '%' == c )
+ {
+ nPos++;
+
+ if ( nPos == nEnd )
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::decodeValue - syntax error!" );
+ return rtl::OUString();
+ }
+
+ c = pValue[ nPos ];
+
+ if ( 'p' == c )
+ {
+ // %per;
+
+ if ( nPos > nEnd - 4 )
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::decodeValue - syntax error!" );
+ return rtl::OUString();
+ }
+
+ if ( ( 'e' == pValue[ nPos + 1 ] )
+ &&
+ ( 'r' == pValue[ nPos + 2 ] )
+ &&
+ ( ';' == pValue[ nPos + 3 ] ) )
+ {
+ aResult.append( sal_Unicode( '%' ) );
+ nPos += 3;
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::decodeValue - syntax error!" );
+ return rtl::OUString();
+ }
+ }
+ else if ( 'l' == c )
+ {
+ // %lt;
+
+ if ( nPos > nEnd - 3 )
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::decodeValue - syntax error!" );
+ return rtl::OUString();
+ }
+
+ if ( ( 't' == pValue[ nPos + 1 ] )
+ &&
+ ( ';' == pValue[ nPos + 2 ] ) )
+ {
+ aResult.append( sal_Unicode( '<' ) );
+ nPos += 2;
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::decodeValue - syntax error!" );
+ return rtl::OUString();
+ }
+ }
+ else if ( 'g' == c )
+ {
+ // %gt;
+
+ if ( nPos > nEnd - 3 )
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::decodeValue - syntax error!" );
+ return rtl::OUString();
+ }
+
+ if ( ( 't' == pValue[ nPos + 1 ] )
+ &&
+ ( ';' == pValue[ nPos + 2 ] ) )
+ {
+ aResult.append( sal_Unicode( '>' ) );
+ nPos += 2;
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::decodeValue - syntax error!" );
+ return rtl::OUString();
+ }
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::decodeValue - syntax error!" );
+ return rtl::OUString();
+ }
+ }
+ else
+ aResult.append( c );
+
+ nPos++;
+ }
+
+ return rtl::OUString( aResult );
+}
+
+//////////////////////////////////////////////////////////////////////////
+// static
+bool UCBDeadPropertyValue::supportsType( const uno::Type & rType )
+{
+ if ( ( rType != getCppuType( static_cast< const rtl::OUString * >( 0 ) ) )
+ &&
+ ( rType != getCppuType( static_cast< const sal_Int32 * >( 0 ) ) )
+ &&
+ ( rType != getCppuType( static_cast< const sal_Int16 * >( 0 ) ) )
+ &&
+ ( rType != getCppuBooleanType() )
+ &&
+ ( rType != getCppuCharType() )
+ &&
+ ( rType != getCppuType( static_cast< const sal_Int8 * >( 0 ) ) )
+ &&
+ ( rType != getCppuType( static_cast< const sal_Int64 * >( 0 ) ) )
+ &&
+ ( rType != getCppuType( static_cast< const float * >( 0 ) ) )
+ &&
+ ( rType != getCppuType( static_cast< const double * >( 0 ) ) ) )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// static
+bool UCBDeadPropertyValue::createFromXML( const rtl::OString & rInData,
+ uno::Any & rOutData )
+{
+ bool success = false;
+
+ ne_xml_parser * parser = ne_xml_create();
+ if ( parser )
+ {
+ UCBDeadPropertyValueParseContext aCtx;
+ ne_xml_push_handler( parser,
+ UCBDeadPropertyValue_startelement_callback,
+ UCBDeadPropertyValue_chardata_callback,
+ UCBDeadPropertyValue_endelement_callback,
+ &aCtx );
+
+ ne_xml_parse( parser, rInData.getStr(), rInData.getLength() );
+
+#if NEON_VERSION >= 0x0250
+ success = !ne_xml_failed( parser );
+#else
+ success = !!ne_xml_valid( parser );
+#endif
+
+ ne_xml_destroy( parser );
+
+ if ( success )
+ {
+ if ( aCtx.pType && aCtx.pValue )
+ {
+ // Decode aCtx.pValue! It may contain XML reserved chars.
+ rtl::OUString aStringValue = decodeValue( *aCtx.pValue );
+ if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeString ) )
+ {
+ rOutData <<= aStringValue;
+ }
+ else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeLong ) )
+ {
+ rOutData <<= aStringValue.toInt32();
+ }
+ else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeShort ) )
+ {
+ rOutData <<= sal_Int16( aStringValue.toInt32() );
+ }
+ else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeBoolean ) )
+ {
+ if ( aStringValue.equalsIgnoreAsciiCase(
+ rtl::OUString::createFromAscii( "true" ) ) )
+ rOutData <<= sal_Bool( sal_True );
+ else
+ rOutData <<= sal_Bool( sal_False );
+ }
+ else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeChar ) )
+ {
+ rOutData <<= aStringValue.toChar();
+ }
+ else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeByte ) )
+ {
+ rOutData <<= sal_Int8( aStringValue.toChar() );
+ }
+ else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeHyper ) )
+ {
+ rOutData <<= aStringValue.toInt64();
+ }
+ else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeFloat ) )
+ {
+ rOutData <<= aStringValue.toFloat();
+ }
+ else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeDouble ) )
+ {
+ rOutData <<= aStringValue.toDouble();
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::createFromXML - "
+ "Unsupported property type!" );
+ success = false;
+ }
+ }
+ else
+ success = false;
+ }
+ }
+
+ return success;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// static
+bool UCBDeadPropertyValue::toXML( const uno::Any & rInData,
+ rtl::OUString & rOutData )
+{
+ // <ucbprop><type>the_type</type><value>the_value</value></ucbprop>
+
+ // Check property type. Extract type and value as string.
+
+ const uno::Type& rType = rInData.getValueType();
+ rtl::OUString aStringValue;
+ rtl::OUString aStringType;
+
+ if ( rType == getCppuType( static_cast< const rtl::OUString * >( 0 ) ) )
+ {
+ // string
+ rInData >>= aStringValue;
+ aStringType = aTypeString;
+ }
+ else if ( rType == getCppuType( static_cast< const sal_Int32 * >( 0 ) ) )
+ {
+ // long
+ sal_Int32 nValue = 0;
+ rInData >>= nValue;
+ aStringValue = rtl::OUString::valueOf( nValue );
+ aStringType = aTypeLong;
+ }
+ else if ( rType == getCppuType( static_cast< const sal_Int16 * >( 0 ) ) )
+ {
+ // short
+ sal_Int32 nValue = 0;
+ rInData >>= nValue;
+ aStringValue = rtl::OUString::valueOf( nValue );
+ aStringType = aTypeShort;
+ }
+ else if ( rType == getCppuBooleanType() )
+ {
+ // boolean
+ sal_Bool bValue = false;
+ rInData >>= bValue;
+ aStringValue = rtl::OUString::valueOf( bValue );
+ aStringType = aTypeBoolean;
+ }
+ else if ( rType == getCppuCharType() )
+ {
+ // char
+ sal_Unicode cValue = 0;
+ rInData >>= cValue;
+ aStringValue = rtl::OUString::valueOf( cValue );
+ aStringType = aTypeChar;
+ }
+ else if ( rType == getCppuType( static_cast< const sal_Int8 * >( 0 ) ) )
+ {
+ // byte
+ sal_Int8 nValue = 0;
+ rInData >>= nValue;
+ aStringValue = rtl::OUString::valueOf( sal_Unicode( nValue ) );
+ aStringType = aTypeByte;
+ }
+ else if ( rType == getCppuType( static_cast< const sal_Int64 * >( 0 ) ) )
+ {
+ // hyper
+ sal_Int64 nValue = 0;
+ rInData >>= nValue;
+ aStringValue = rtl::OUString::valueOf( nValue );
+ aStringType = aTypeHyper;
+ }
+ else if ( rType == getCppuType( static_cast< const float * >( 0 ) ) )
+ {
+ // float
+ float nValue = 0;
+ rInData >>= nValue;
+ aStringValue = rtl::OUString::valueOf( nValue );
+ aStringType = aTypeFloat;
+ }
+ else if ( rType == getCppuType( static_cast< const double * >( 0 ) ) )
+ {
+ // double
+ double nValue = 0;
+ rInData >>= nValue;
+ aStringValue = rtl::OUString::valueOf( nValue );
+ aStringType = aTypeDouble;
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "UCBDeadPropertyValue::toXML - "
+ "Unsupported property type!" );
+ return false;
+ }
+
+ // Encode value! It must not contain XML reserved chars!
+ aStringValue = encodeValue( aStringValue );
+
+ rOutData = aXMLPre;
+ rOutData += aStringType;
+ rOutData += aXMLMid;
+ rOutData += aStringValue;
+ rOutData += aXMLEnd;
+
+ return true;
+}
diff --git a/ucb/source/ucp/webdav/UCBDeadPropertyValue.hxx b/ucb/source/ucp/webdav/UCBDeadPropertyValue.hxx
new file mode 100644
index 000000000000..69dc5d3c80bf
--- /dev/null
+++ b/ucb/source/ucp/webdav/UCBDeadPropertyValue.hxx
@@ -0,0 +1,65 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _UCBDEADPROPERTYVALUE_HXX_
+#define _UCBDEADPROPERTYVALUE_HXX_
+
+#include <rtl/string.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+namespace webdav_ucp
+{
+
+class UCBDeadPropertyValue
+{
+private:
+ static const rtl::OUString aTypeString;
+ static const rtl::OUString aTypeLong;
+ static const rtl::OUString aTypeShort;
+ static const rtl::OUString aTypeBoolean;
+ static const rtl::OUString aTypeChar;
+ static const rtl::OUString aTypeByte;
+ static const rtl::OUString aTypeHyper;
+ static const rtl::OUString aTypeFloat;
+ static const rtl::OUString aTypeDouble;
+
+ static const rtl::OUString aXMLPre;
+ static const rtl::OUString aXMLMid;
+ static const rtl::OUString aXMLEnd;
+
+public:
+ static bool supportsType( const com::sun::star::uno::Type & rType );
+
+ static bool createFromXML( const rtl::OString & rInData,
+ com::sun::star::uno::Any & rOutData );
+ static bool toXML( const com::sun::star::uno::Any & rInData,
+ rtl::OUString & rOutData );
+};
+
+}
+
+#endif /* _UCBDEADPROPERTYVALUE_HXX_ */
diff --git a/ucb/source/ucp/webdav/makefile.mk b/ucb/source/ucp/webdav/makefile.mk
new file mode 100644
index 000000000000..162d58266406
--- /dev/null
+++ b/ucb/source/ucp/webdav/makefile.mk
@@ -0,0 +1,168 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+# UCP Version - Increase, if UCP libraray becomes incompatible.
+UCP_VERSION=1
+
+# Name for the UCP. Will become part of the library name (See below).
+UCP_NAME=dav
+
+# Relative path to project root.
+PRJ = ..$/..$/..
+
+# Project Name.
+PRJNAME=ucb
+
+TARGET=ucp$(UCP_NAME)
+
+ENABLE_EXCEPTIONS=TRUE
+USE_DEFFILE=TRUE
+NO_BSYMBOLIC=TRUE
+
+# --- Settings ---------------------------------------------------------
+
+.INCLUDE: settings.mk
+.IF "$(L10N_framework)"==""
+
+.IF "$(DISABLE_NEON)" == "TRUE"
+
+@all:
+ @echo "neon disabled...."
+
+.ELSE
+
+NEONINCDIR=external$/neon
+
+.IF "$(SYSTEM_NEON)" != "YES"
+.INCLUDE: $(SOLARINCDIR)$/$(NEONINCDIR)$/version.mk
+.ENDIF
+
+CFLAGS+= -DNEON_VERSION=0x$(NEON_VERSION)
+
+.IF "$(SYSTEM_NEON)" == "YES"
+CFLAGS+= $(NEON_CFLAGS)
+.ELSE
+CFLAGS+= -I$(SOLARINCDIR)$/$(NEONINCDIR)
+.ENDIF
+
+.IF "$(SYSTEM_LIBXML)" == "YES"
+CFLAGS+= $(LIBXML_CFLAGS)
+.ELSE
+LIBXMLINCDIR=external$/libxml
+CFLAGS+= -I$(SOLARINCDIR)$/$(LIBXMLINCDIR)
+.ENDIF
+
+.IF "$(SYSTEM_OPENSSL)" == "YES"
+CFLAGS+= $(OPENSSL_CFLAGS)
+.ENDIF
+
+# --- General -----------------------------------------------------
+
+SLOFILES=\
+ $(SLO)$/webdavservices.obj \
+ $(SLO)$/webdavprovider.obj \
+ $(SLO)$/webdavcontent.obj \
+ $(SLO)$/webdavcontentcaps.obj \
+ $(SLO)$/webdavresultset.obj \
+ $(SLO)$/webdavdatasupplier.obj \
+ $(SLO)$/ContentProperties.obj \
+ $(SLO)$/DAVProperties.obj \
+ $(SLO)$/DAVSessionFactory.obj \
+ $(SLO)$/DAVResourceAccess.obj \
+ $(SLO)$/NeonUri.obj \
+ $(SLO)$/NeonInputStream.obj \
+ $(SLO)$/NeonPropFindRequest.obj \
+ $(SLO)$/NeonHeadRequest.obj \
+ $(SLO)$/NeonSession.obj \
+ $(SLO)$/NeonLockStore.obj \
+ $(SLO)$/DateTimeHelper.obj \
+ $(SLO)$/LinkSequence.obj \
+ $(SLO)$/LockSequence.obj \
+ $(SLO)$/LockEntrySequence.obj \
+ $(SLO)$/UCBDeadPropertyValue.obj
+
+LIB1TARGET=$(SLB)$/_$(TARGET).lib
+LIB1OBJFILES=$(SLOFILES)
+
+# --- Shared-Library ---------------------------------------------------
+
+SHL1TARGET=$(TARGET)$(UCP_VERSION)
+SHL1IMPLIB=i$(TARGET)
+
+SHL1VERSIONMAP=$(SOLARENV)/src/component.map
+
+SHL1STDLIBS=\
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(SALLIB) \
+ $(SALHELPERLIB) \
+ $(UCBHELPERLIB) \
+ $(COMPHELPERLIB) \
+ $(NEON3RDLIB) \
+ $(LIBXML2LIB)
+
+.IF "$(GUI)"=="WNT"
+SHL1STDLIBS+= $(WSOCK32LIB)
+.IF "$(WINDOWS_VISTA_PSDK)" != ""
+SHL1STDLIBS+= $(WS2_32LIB)
+.ENDIF
+SHL1STDLIBS+= $(OPENSSLLIB)
+.ELSE # WNT
+.IF "$(OS)"=="SOLARIS"
+SHL1STDLIBS+= -lnsl -lsocket -ldl
+.ENDIF # SOLARIS
+.IF "$(OS)"=="OS2"
+SHL1STDLIBS+= pthread.lib libz.lib
+.ENDIF # OS2
+.IF "$(SYSTEM_OPENSSL)"=="YES"
+SHL1STDLIBS+= $(OPENSSLLIB)
+.ELSE
+SHL1STDLIBS+= $(OPENSSLLIBST)
+.ENDIF
+.ENDIF # WNT
+
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+SHL1LIBS=$(LIB1TARGET)
+
+# --- Def-File ---------------------------------------------------------
+
+DEF1NAME=$(SHL1TARGET)
+
+.ENDIF #"$(DISABLE_NEON)" == "TRUE"
+
+.ENDIF # L10N_framework
+# --- Targets ----------------------------------------------------------
+
+.INCLUDE: target.mk
+
+ALLTAR : $(MISC)/ucpdav1.component
+
+$(MISC)/ucpdav1.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \
+ ucpdav1.component
+ $(XSLTPROC) --nonet --stringparam uri \
+ '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \
+ $(SOLARENV)/bin/createcomponent.xslt ucpdav1.component
diff --git a/ucb/source/ucp/webdav/ucpdav.xml b/ucb/source/ucp/webdav/ucpdav.xml
new file mode 100644
index 000000000000..ccb993b3138c
--- /dev/null
+++ b/ucb/source/ucp/webdav/ucpdav.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd">
+<module-description xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <module-name>
+ ucpdav
+ </module-name>
+
+ <component-description>
+ <author>
+ Kai Sommerfeld
+ </author>
+ <name>
+ com.sun.star.comp.ucb.WebDAVContentProvider
+ </name>
+ <description>
+ This component implements a Content Provider for the Universal
+ Content Broker. It provides access to contents stored on an HTTP/WebDAV
+ server.
+ </description>
+ <loader-name>
+ com.sun.star.loader.SharedLibrary
+ </loader-name>
+ <language>
+ c++
+ </language>
+ <status value="final"/>
+ <supported-service>
+ com.sun.star.ucb.WebDAVContentProvider
+ </supported-service>
+ </component-description>
+
+ <project-build-dependency> external </project-build-dependency>
+ <project-build-dependency> sal </project-build-dependency>
+ <project-build-dependency> cppu </project-build-dependency>
+ <project-build-dependency> cppuhelper </project-build-dependency>
+ <project-build-dependency> ucbhelper </project-build-dependency>
+
+ <runtime-module-dependency> sal3 </runtime-module-dependency>
+ <runtime-module-dependency> cppu3 </runtime-module-dependency>
+ <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency>
+ <runtime-module-dependency> ucbhelper4$(COM) </runtime-module-dependency>
+
+ <type> com.sun.star.beans.PropertyAttribute </type>
+ <type> com.sun.star.beans.PropertyValue </type>
+ <type> com.sun.star.beans.XPropertiesChangeNotifier </type>
+ <type> com.sun.star.beans.XPropertyAccess </type>
+ <type> com.sun.star.beans.XPropertyContainer </type>
+ <type> com.sun.star.beans.XPropertySetInfoChangeNotifier </type>
+ <type> com.sun.star.container.XChild </type>
+ <type> com.sun.star.io.XActiveDataSink </type>
+ <type> com.sun.star.io.XInputStream </type>
+ <type> com.sun.star.io.XOutputStream </type>
+ <type> com.sun.star.io.XSeekable </type>
+ <type> com.sun.star.lang.IllegalAccessException </type>
+ <type> com.sun.star.lang.XComponent </type>
+ <type> com.sun.star.lang.XMultiServiceFactory </type>
+ <type> com.sun.star.lang.XServiceInfo </type>
+ <type> com.sun.star.lang.XSingleServiceFactory </type>
+ <type> com.sun.star.lang.XTypeProvider </type>
+ <type> com.sun.star.registry.XRegistryKey </type>
+ <type> com.sun.star.sdbc.XCloseable </type>
+ <type> com.sun.star.sdbc.XColumnLocate </type>
+ <type> com.sun.star.sdbc.XResultSetMetaDataSupplier </type>
+ <type> com.sun.star.sdbc.XRow </type>
+ <type> com.sun.star.task.InteractionClassification </type>
+ <type> com.sun.star.task.XInteractionAbort </type>
+ <type> com.sun.star.task.XInteractionReply </type>
+ <type> com.sun.star.ucb.AuthenticationRequest </type>
+ <type> com.sun.star.ucb.CommandFailedException </type>
+ <type> com.sun.star.ucb.ContentCreationException </type>
+ <type> com.sun.star.ucb.ContentInfoAttribute </type>
+ <type> com.sun.star.ucb.InsertCommandArgument </type>
+ <type> com.sun.star.ucb.InteractiveAugmentedIOException </type>
+ <type> com.sun.star.ucb.InteractiveBadTransferURLException </type>
+ <type> com.sun.star.ucb.InteractiveNetworkConnectException </type>
+ <type> com.sun.star.ucb.InteractiveNetworkGeneralException </type>
+ <type> com.sun.star.ucb.InteractiveNetworkReadException </type>
+ <type> com.sun.star.ucb.InteractiveNetworkResolveNameException </type>
+ <type> com.sun.star.ucb.InteractiveNetworkWriteException </type>
+ <type> com.sun.star.ucb.Link </type>
+ <type> com.sun.star.ucb.Lock </type>
+ <type> com.sun.star.ucb.MissingInputStreamException </type>
+ <type> com.sun.star.ucb.MissingPropertiesException </type>
+ <type> com.sun.star.ucb.NameClash </type>
+ <type> com.sun.star.ucb.NameClashException </type>
+ <type> com.sun.star.ucb.OpenCommandArgument2 </type>
+ <type> com.sun.star.ucb.OpenMode </type>
+ <type> com.sun.star.ucb.PostCommandArgument2 </type>
+ <type> com.sun.star.ucb.RememberAuthentication </type>
+ <type> com.sun.star.ucb.ResultSetException </type>
+ <type> com.sun.star.ucb.TransferInfo </type>
+ <type> com.sun.star.ucb.XCommandEnvironment </type>
+ <type> com.sun.star.ucb.UnsupportedCommandException </type>
+ <type> com.sun.star.ucb.UnsupportedDataSinkException </type>
+ <type> com.sun.star.ucb.UnsupportedNameClashException </type>
+ <type> com.sun.star.ucb.UnsupportedOpenModeException </type>
+ <type> com.sun.star.ucb.XCommandInfo </type>
+ <type> com.sun.star.ucb.XCommandInfoChangeNotifier </type>
+ <type> com.sun.star.ucb.XCommandProcessor </type>
+ <type> com.sun.star.ucb.XContentAccess </type>
+ <type> com.sun.star.ucb.XContentCreator </type>
+ <type> com.sun.star.ucb.XContentProvider </type>
+ <type> com.sun.star.ucb.XDynamicResultSet </type>
+ <type> com.sun.star.ucb.XInteractionSupplyAuthentication </type>
+ <type> com.sun.star.ucb.XPersistentPropertySet </type>
+ <type> com.sun.star.uno.XAggregation </type>
+ <type> com.sun.star.util.DateTime </type>
+</module-description>
diff --git a/ucb/source/ucp/webdav/ucpdav1.component b/ucb/source/ucp/webdav/ucpdav1.component
new file mode 100644
index 000000000000..4e18b566e1a4
--- /dev/null
+++ b/ucb/source/ucp/webdav/ucpdav1.component
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--**********************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+**********************************************************************-->
+
+<component loader="com.sun.star.loader.SharedLibrary"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.WebDAVContentProvider">
+ <service name="com.sun.star.ucb.WebDAVContentProvider"/>
+ </implementation>
+</component>
diff --git a/ucb/source/ucp/webdav/webdavcontent.cxx b/ucb/source/ucp/webdav/webdavcontent.cxx
new file mode 100644
index 000000000000..26b2a044e7b6
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavcontent.cxx
@@ -0,0 +1,3247 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+
+#include <osl/diagnose.h>
+#include "osl/doublecheckedlocking.h"
+#include <rtl/uri.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <ucbhelper/contentidentifier.hxx>
+#include <ucbhelper/propertyvalueset.hxx>
+#include <ucbhelper/simpleinteractionrequest.hxx>
+#include <ucbhelper/cancelcommandexecution.hxx>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertySetInfoChange.hpp>
+#include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/lang/IllegalAccessException.hpp>
+#include <com/sun/star/task/PasswordContainerInteractionHandler.hpp>
+#include <com/sun/star/ucb/CommandEnvironment.hpp>
+#include <com/sun/star/ucb/CommandFailedException.hpp>
+#include <com/sun/star/ucb/ContentInfoAttribute.hpp>
+#include <com/sun/star/ucb/InsertCommandArgument.hpp>
+#include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include "com/sun/star/ucb/InteractiveLockingLockedException.hpp"
+#include "com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp"
+#include "com/sun/star/ucb/InteractiveLockingNotLockedException.hpp"
+#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
+#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
+#include <com/sun/star/ucb/MissingInputStreamException.hpp>
+#include <com/sun/star/ucb/MissingPropertiesException.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <com/sun/star/ucb/NameClashException.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/ucb/PostCommandArgument2.hpp>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/ucb/UnsupportedCommandException.hpp>
+#include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
+#include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
+#include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
+#include <com/sun/star/ucb/XCommandInfo.hpp>
+#include <com/sun/star/ucb/XPersistentPropertySet.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include "webdavcontent.hxx"
+#include "webdavprovider.hxx"
+#include "webdavresultset.hxx"
+#include "ContentProperties.hxx"
+#include "NeonUri.hxx"
+#include "UCBDeadPropertyValue.hxx"
+
+using namespace com::sun::star;
+using namespace webdav_ucp;
+
+//=========================================================================
+//=========================================================================
+//
+// Content Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+//=========================================================================
+// ctr for content on an existing webdav resource
+Content::Content(
+ const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
+ ContentProvider* pProvider,
+ const uno::Reference< ucb::XContentIdentifier >& Identifier,
+ rtl::Reference< DAVSessionFactory > const & rSessionFactory )
+ throw ( ucb::ContentCreationException )
+: ContentImplHelper( rxSMgr, pProvider, Identifier ),
+ m_eResourceType( UNKNOWN ),
+ m_pProvider( pProvider ),
+ m_bTransient( false ),
+ m_bCollection( false ),
+ m_bDidGetOrHead( false )
+{
+ try
+ {
+ m_xResAccess.reset( new DAVResourceAccess(
+ rxSMgr,
+ rSessionFactory,
+ Identifier->getContentIdentifier() ) );
+
+ NeonUri aURI( Identifier->getContentIdentifier() );
+ m_aEscapedTitle = aURI.GetPathBaseName();
+ }
+ catch ( DAVException const & )
+ {
+ throw ucb::ContentCreationException();
+ }
+}
+
+//=========================================================================
+// ctr for content on an non-existing webdav resource
+Content::Content(
+ const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
+ ContentProvider* pProvider,
+ const uno::Reference< ucb::XContentIdentifier >& Identifier,
+ rtl::Reference< DAVSessionFactory > const & rSessionFactory,
+ sal_Bool isCollection )
+ throw ( ucb::ContentCreationException )
+: ContentImplHelper( rxSMgr, pProvider, Identifier ),
+ m_eResourceType( UNKNOWN ),
+ m_pProvider( pProvider ),
+ m_bTransient( true ),
+ m_bCollection( isCollection ),
+ m_bDidGetOrHead( false )
+{
+ try
+ {
+ m_xResAccess.reset( new DAVResourceAccess(
+ rxSMgr, rSessionFactory, Identifier->getContentIdentifier() ) );
+ }
+ catch ( DAVException const & )
+ {
+ throw ucb::ContentCreationException();
+ }
+
+ // Do not set m_aEscapedTitle here! Content::insert relays on this!!!
+}
+
+//=========================================================================
+// virtual
+Content::~Content()
+{
+}
+
+//=========================================================================
+//
+// XInterface methods.
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL Content::acquire()
+ throw( )
+{
+ ContentImplHelper::acquire();
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Content::release()
+ throw( )
+{
+ ContentImplHelper::release();
+}
+
+//=========================================================================
+// virtual
+uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
+ throw ( uno::RuntimeException )
+{
+ // Note: isFolder may require network activities! So call it only
+ // if it is really necessary!!!
+ uno::Any aRet = cppu::queryInterface(
+ rType,
+ static_cast< ucb::XContentCreator * >( this ) );
+ if ( aRet.hasValue() )
+ {
+ try
+ {
+ uno::Reference< beans::XPropertySet > const xProps(
+ m_xSMgr, uno::UNO_QUERY_THROW );
+ uno::Reference< uno::XComponentContext > xCtx;
+ xCtx.set( xProps->getPropertyValue(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ),
+ uno::UNO_QUERY_THROW );
+
+ uno::Reference< task::XInteractionHandler > xIH(
+ task::PasswordContainerInteractionHandler::create( xCtx ) );
+
+ // Supply a command env to isFolder() that contains an interaction
+ // handler that uses the password container service to obtain
+ // credentials without displaying a password gui.
+
+ uno::Reference< ucb::XCommandEnvironment > xCmdEnv(
+ ucb::CommandEnvironment::create(
+ xCtx,
+ xIH,
+ uno::Reference< ucb::XProgressHandler >() ) );
+
+ return isFolder( xCmdEnv ) ? aRet : uno::Any();
+ }
+ catch ( uno::RuntimeException const & )
+ {
+ throw;
+ }
+ catch ( uno::Exception const & )
+ {
+ return uno::Any();
+ }
+ }
+ return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
+}
+
+//=========================================================================
+//
+// XTypeProvider methods.
+//
+//=========================================================================
+
+XTYPEPROVIDER_COMMON_IMPL( Content );
+
+//=========================================================================
+// virtual
+uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
+ throw( uno::RuntimeException )
+{
+ sal_Bool bFolder = sal_False;
+ try
+ {
+ bFolder
+ = isFolder( uno::Reference< ucb::XCommandEnvironment >() );
+ }
+ catch ( uno::RuntimeException const & )
+ {
+ throw;
+ }
+ catch ( uno::Exception const & )
+ {
+ }
+
+ cppu::OTypeCollection * pCollection = 0;
+
+ if ( bFolder )
+ {
+ static cppu::OTypeCollection* pFolderTypes = 0;
+
+ pCollection = pFolderTypes;
+ if ( !pCollection )
+ {
+ osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
+
+ pCollection = pFolderTypes;
+ if ( !pCollection )
+ {
+ static cppu::OTypeCollection aCollection(
+ CPPU_TYPE_REF( lang::XTypeProvider ),
+ CPPU_TYPE_REF( lang::XServiceInfo ),
+ CPPU_TYPE_REF( lang::XComponent ),
+ CPPU_TYPE_REF( ucb::XContent ),
+ CPPU_TYPE_REF( ucb::XCommandProcessor ),
+ CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
+ CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
+ CPPU_TYPE_REF( beans::XPropertyContainer ),
+ CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
+ CPPU_TYPE_REF( container::XChild ),
+ CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
+ pCollection = &aCollection;
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ pFolderTypes = pCollection;
+ }
+ }
+ else {
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ }
+ }
+ else
+ {
+ static cppu::OTypeCollection* pDocumentTypes = 0;
+
+ pCollection = pDocumentTypes;
+ if ( !pCollection )
+ {
+ osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
+
+ pCollection = pDocumentTypes;
+ if ( !pCollection )
+ {
+ static cppu::OTypeCollection aCollection(
+ CPPU_TYPE_REF( lang::XTypeProvider ),
+ CPPU_TYPE_REF( lang::XServiceInfo ),
+ CPPU_TYPE_REF( lang::XComponent ),
+ CPPU_TYPE_REF( ucb::XContent ),
+ CPPU_TYPE_REF( ucb::XCommandProcessor ),
+ CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
+ CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
+ CPPU_TYPE_REF( beans::XPropertyContainer ),
+ CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
+ CPPU_TYPE_REF( container::XChild ) );
+ pCollection = &aCollection;
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ pDocumentTypes = pCollection;
+ }
+ }
+ else {
+ OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
+ }
+ }
+
+ return (*pCollection).getTypes();
+}
+
+//=========================================================================
+//
+// XServiceInfo methods.
+//
+//=========================================================================
+
+// virtual
+rtl::OUString SAL_CALL Content::getImplementationName()
+ throw( uno::RuntimeException )
+{
+ return rtl::OUString::createFromAscii(
+ "com.sun.star.comp.ucb.WebDAVContent" );
+}
+
+//=========================================================================
+// virtual
+uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< rtl::OUString > aSNS( 1 );
+ aSNS.getArray()[ 0 ]
+ = rtl::OUString::createFromAscii( WEBDAV_CONTENT_SERVICE_NAME );
+ return aSNS;
+}
+
+//=========================================================================
+//
+// XContent methods.
+//
+//=========================================================================
+
+// virtual
+rtl::OUString SAL_CALL Content::getContentType()
+ throw( uno::RuntimeException )
+{
+ sal_Bool bFolder = sal_False;
+ try
+ {
+ bFolder
+ = isFolder( uno::Reference< ucb::XCommandEnvironment >() );
+ }
+ catch ( uno::RuntimeException const & )
+ {
+ throw;
+ }
+ catch ( uno::Exception const & )
+ {
+ }
+
+ if ( bFolder )
+ return rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE );
+
+ return rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE );
+}
+
+//=========================================================================
+//
+// XCommandProcessor methods.
+//
+//=========================================================================
+
+// virtual
+uno::Any SAL_CALL Content::execute(
+ const ucb::Command& aCommand,
+ sal_Int32 /*CommandId*/,
+ const uno::Reference< ucb::XCommandEnvironment >& Environment )
+ throw( uno::Exception,
+ ucb::CommandAbortedException,
+ uno::RuntimeException )
+{
+ OSL_TRACE( ">>>>> Content::execute: start: command: %s, env: %s",
+ rtl::OUStringToOString( aCommand.Name,
+ RTL_TEXTENCODING_UTF8 ).getStr(),
+ Environment.is() ? "present" : "missing" );
+
+ uno::Any aRet;
+
+ if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // getPropertyValues
+ //////////////////////////////////////////////////////////////////
+
+ uno::Sequence< beans::Property > Properties;
+ if ( !( aCommand.Argument >>= Properties ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ aRet <<= getPropertyValues( Properties, Environment );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // setPropertyValues
+ //////////////////////////////////////////////////////////////////
+
+ uno::Sequence< beans::PropertyValue > aProperties;
+ if ( !( aCommand.Argument >>= aProperties ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ if ( !aProperties.getLength() )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "No properties!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ aRet <<= setPropertyValues( aProperties, Environment );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // getPropertySetInfo
+ //////////////////////////////////////////////////////////////////
+
+ // Note: Implemented by base class.
+ aRet <<= getPropertySetInfo( Environment,
+ sal_False /* don't cache data */ );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // getCommandInfo
+ //////////////////////////////////////////////////////////////////
+
+ // Note: Implemented by base class.
+ aRet <<= getCommandInfo( Environment, sal_False );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // open
+ //////////////////////////////////////////////////////////////////
+
+ ucb::OpenCommandArgument2 aOpenCommand;
+ if ( !( aCommand.Argument >>= aOpenCommand ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ aRet = open( aOpenCommand, Environment );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // insert
+ //////////////////////////////////////////////////////////////////
+
+ ucb::InsertCommandArgument arg;
+ if ( !( aCommand.Argument >>= arg ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ insert( arg.Data, arg.ReplaceExisting, Environment );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // delete
+ //////////////////////////////////////////////////////////////////
+
+ sal_Bool bDeletePhysical = sal_False;
+ aCommand.Argument >>= bDeletePhysical;
+
+// KSO: Ignore parameter and destroy the content, if you don't support
+// putting objects into trashcan. ( Since we do not have a trash can
+// service yet (src603), you actually have no other choice. )
+// if ( bDeletePhysical )
+// {
+ try
+ {
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+ xResAccess->DESTROY( Environment );
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, Environment, sal_True );
+ // Unreachable
+ }
+// }
+
+ // Propagate destruction.
+ destroy( bDeletePhysical );
+
+ // Remove own and all children's Additional Core Properties.
+ removeAdditionalPropertySet( sal_True );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "transfer" ) )
+ && isFolder( Environment ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // transfer
+ // ( Not available at documents )
+ //////////////////////////////////////////////////////////////////
+
+ ucb::TransferInfo transferArgs;
+ if ( !( aCommand.Argument >>= transferArgs ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ transfer( transferArgs, Environment );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "post" ) ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // post
+ //////////////////////////////////////////////////////////////////
+
+ ucb::PostCommandArgument2 aArg;
+ if ( !( aCommand.Argument >>= aArg ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ post( aArg, Environment );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "lock" ) ) &&
+ supportsExclusiveWriteLock( Environment ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // lock
+ //////////////////////////////////////////////////////////////////
+
+ lock( Environment );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "unlock" ) ) &&
+ supportsExclusiveWriteLock( Environment ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // unlock
+ //////////////////////////////////////////////////////////////////
+
+ unlock( Environment );
+ }
+ else if ( aCommand.Name.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) &&
+ isFolder( Environment ) )
+ {
+ //////////////////////////////////////////////////////////////////
+ // createNewContent
+ //////////////////////////////////////////////////////////////////
+
+ ucb::ContentInfo aArg;
+ if ( !( aCommand.Argument >>= aArg ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Wrong argument type!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ Environment );
+ // Unreachable
+ }
+
+ aRet = uno::makeAny( createNewContent( aArg ) );
+ }
+ else
+ {
+ //////////////////////////////////////////////////////////////////
+ // Unsupported command
+ //////////////////////////////////////////////////////////////////
+
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( ucb::UnsupportedCommandException(
+ aCommand.Name,
+ static_cast< cppu::OWeakObject * >( this ) ) ),
+ Environment );
+ // Unreachable
+ }
+
+ OSL_TRACE( "<<<<< Content::execute: end: command: %s",
+ rtl::OUStringToOString( aCommand.Name,
+ RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ return aRet;
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
+ throw( uno::RuntimeException )
+{
+ try
+ {
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+ xResAccess->abort();
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+ }
+ catch ( DAVException const & )
+ {
+ // abort failed!
+ }
+}
+
+//=========================================================================
+//
+// XPropertyContainer methods.
+//
+//=========================================================================
+
+// virtual
+void SAL_CALL Content::addProperty( const rtl::OUString& Name,
+ sal_Int16 Attributes,
+ const uno::Any& DefaultValue )
+ throw( beans::PropertyExistException,
+ beans::IllegalTypeException,
+ lang::IllegalArgumentException,
+ uno::RuntimeException )
+{
+// if ( m_bTransient )
+// @@@ ???
+
+ if ( !Name.getLength() )
+ throw lang::IllegalArgumentException();
+
+ // Check property type.
+ if ( !UCBDeadPropertyValue::supportsType( DefaultValue.getValueType() ) )
+ {
+ OSL_ENSURE( sal_False,
+ "Content::addProperty - Unsupported property type!" );
+ throw beans::IllegalTypeException();
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Make sure a property with the requested name does not already
+ // exist in dynamic and static(!) properties.
+ //////////////////////////////////////////////////////////////////////
+
+ // @@@ Need real command environment here, but where to get it from?
+ // XPropertyContainer interface should be replaced by
+ // XCommandProcessor commands!
+ uno::Reference< ucb::XCommandEnvironment > xEnv;
+
+ // Note: This requires network access!
+ if ( getPropertySetInfo( xEnv, sal_False /* don't cache data */ )
+ ->hasPropertyByName( Name ) )
+ {
+ // Property does already exist.
+ throw beans::PropertyExistException();
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Add a new dynamic property.
+ //////////////////////////////////////////////////////////////////////
+
+ ProppatchValue aValue( PROPSET, Name, DefaultValue );
+
+ std::vector< ProppatchValue > aProppatchValues;
+ aProppatchValues.push_back( aValue );
+
+ try
+ {
+ // Set property value at server.
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+ xResAccess->PROPPATCH( aProppatchValues, xEnv );
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+
+ // Notify propertyset info change listeners.
+ beans::PropertySetInfoChangeEvent evt(
+ static_cast< cppu::OWeakObject * >( this ),
+ Name,
+ -1, // No handle available
+ beans::PropertySetInfoChange::PROPERTY_INSERTED );
+ notifyPropertySetInfoChange( evt );
+ }
+ catch ( DAVException const & e )
+ {
+ if ( e.getStatus() == SC_FORBIDDEN )
+ {
+ // Support for setting arbitrary dead properties is optional!
+
+ // Store property locally.
+ ContentImplHelper::addProperty(
+ Name, Attributes, DefaultValue );
+ }
+ else
+ {
+ if ( shouldAccessNetworkAfterException( e ) )
+ {
+ try
+ {
+ const ResourceType & rType = getResourceType( xEnv );
+ switch ( rType )
+ {
+ case UNKNOWN:
+ case DAV:
+ throw lang::IllegalArgumentException();
+
+ case FTP:
+ case NON_DAV:
+ // Store property locally.
+ ContentImplHelper::addProperty( Name,
+ Attributes,
+ DefaultValue );
+ break;
+
+ default:
+ OSL_ENSURE( sal_False,
+ "Content::addProperty - "
+ "Unsupported resource type!" );
+ break;
+ }
+ }
+ catch ( uno::Exception const & )
+ {
+ OSL_ENSURE( sal_False,
+ "Content::addProperty - "
+ "Unable to determine resource type!" );
+ }
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "Content::addProperty - "
+ "Unable to determine resource type!" );
+ }
+ }
+ }
+}
+
+//=========================================================================
+// virtual
+void SAL_CALL Content::removeProperty( const rtl::OUString& Name )
+ throw( beans::UnknownPropertyException,
+ beans::NotRemoveableException,
+ uno::RuntimeException )
+{
+ // @@@ Need real command environment here, but where to get it from?
+ // XPropertyContainer interface should be replaced by
+ // XCommandProcessor commands!
+ uno::Reference< ucb::XCommandEnvironment > xEnv;
+
+#if 0
+ // @@@ REMOVEABLE z.Z. nicht richtig an der PropSetInfo gesetzt!!!
+ try
+ {
+ beans::Property aProp
+ = getPropertySetInfo( xEnv, sal_False /* don't cache data */ )
+ ->getPropertyByName( Name );
+
+ if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVEABLE ) )
+ {
+ // Not removeable!
+ throw beans::NotRemoveableException();
+ }
+ }
+ catch ( beans::UnknownPropertyException const & )
+ {
+ //OSL_ENSURE( sal_False, "removeProperty - Unknown property!" );
+ throw;
+ }
+#endif
+
+ //////////////////////////////////////////////////////////////////////
+ // Try to remove property from server.
+ //////////////////////////////////////////////////////////////////////
+
+ try
+ {
+ std::vector< ProppatchValue > aProppatchValues;
+ ProppatchValue aValue( PROPREMOVE, Name, uno::Any() );
+ aProppatchValues.push_back( aValue );
+
+ // Remove property value from server.
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+ xResAccess->PROPPATCH( aProppatchValues, xEnv );
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+
+ // Notify propertyset info change listeners.
+ beans::PropertySetInfoChangeEvent evt(
+ static_cast< cppu::OWeakObject * >( this ),
+ Name,
+ -1, // No handle available
+ beans::PropertySetInfoChange::PROPERTY_REMOVED );
+ notifyPropertySetInfoChange( evt );
+ }
+ catch ( DAVException const & e )
+ {
+ if ( e.getStatus() == SC_FORBIDDEN )
+ {
+ // Support for setting arbitrary dead properties is optional!
+
+ // Try to remove property from local store.
+ ContentImplHelper::removeProperty( Name );
+ }
+ else
+ {
+ if ( shouldAccessNetworkAfterException( e ) )
+ {
+ try
+ {
+ const ResourceType & rType = getResourceType( xEnv );
+ switch ( rType )
+ {
+ case UNKNOWN:
+ case DAV:
+ throw beans::UnknownPropertyException();
+
+ case FTP:
+ case NON_DAV:
+ // Try to remove property from local store.
+ ContentImplHelper::removeProperty( Name );
+ break;
+
+ default:
+ OSL_ENSURE( sal_False,
+ "Content::removeProperty - "
+ "Unsupported resource type!" );
+ break;
+ }
+ }
+ catch ( uno::Exception const & )
+ {
+ OSL_ENSURE( sal_False,
+ "Content::removeProperty - "
+ "Unable to determine resource type!" );
+ }
+ }
+ else
+ {
+ OSL_ENSURE( sal_False,
+ "Content::removeProperty - "
+ "Unable to determine resource type!" );
+// throw beans::UnknownPropertyException();
+ }
+ }
+ }
+}
+
+//=========================================================================
+//
+// XContentCreator methods.
+//
+//=========================================================================
+
+// virtual
+uno::Sequence< ucb::ContentInfo > SAL_CALL
+Content::queryCreatableContentsInfo()
+ throw( uno::RuntimeException )
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ uno::Sequence< ucb::ContentInfo > aSeq( 2 );
+
+ // document.
+ aSeq.getArray()[ 0 ].Type
+ = rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE );
+ aSeq.getArray()[ 0 ].Attributes
+ = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
+ | ucb::ContentInfoAttribute::KIND_DOCUMENT;
+
+ beans::Property aProp;
+ m_pProvider->getProperty(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), aProp );
+
+ uno::Sequence< beans::Property > aDocProps( 1 );
+ aDocProps.getArray()[ 0 ] = aProp;
+ aSeq.getArray()[ 0 ].Properties = aDocProps;
+
+ // folder.
+ aSeq.getArray()[ 1 ].Type
+ = rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE );
+ aSeq.getArray()[ 1 ].Attributes
+ = ucb::ContentInfoAttribute::KIND_FOLDER;
+
+ uno::Sequence< beans::Property > aFolderProps( 1 );
+ aFolderProps.getArray()[ 0 ] = aProp;
+ aSeq.getArray()[ 1 ].Properties = aFolderProps;
+ return aSeq;
+}
+
+//=========================================================================
+// virtual
+uno::Reference< ucb::XContent > SAL_CALL
+Content::createNewContent( const ucb::ContentInfo& Info )
+ throw( uno::RuntimeException )
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ if ( !Info.Type.getLength() )
+ return uno::Reference< ucb::XContent >();
+
+ if ( ( !Info.Type.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( WEBDAV_COLLECTION_TYPE ) ) )
+ &&
+ ( !Info.Type.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( WEBDAV_CONTENT_TYPE ) ) ) )
+ return uno::Reference< ucb::XContent >();
+
+ rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
+
+ OSL_ENSURE( aURL.getLength() > 0,
+ "WebdavContent::createNewContent - empty identifier!" );
+
+ if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
+ aURL += rtl::OUString::createFromAscii( "/" );
+
+ sal_Bool isCollection;
+ if ( Info.Type.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( WEBDAV_COLLECTION_TYPE ) ) )
+ {
+ aURL += rtl::OUString::createFromAscii( "New_Collection" );
+ isCollection = sal_True;
+ }
+ else
+ {
+ aURL += rtl::OUString::createFromAscii( "New_Content" );
+ isCollection = sal_False;
+ }
+
+ uno::Reference< ucb::XContentIdentifier > xId(
+ new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) );
+
+ // create the local content
+ try
+ {
+ return new ::webdav_ucp::Content( m_xSMgr,
+ m_pProvider,
+ xId,
+ m_xResAccess->getSessionFactory(),
+ isCollection );
+ }
+ catch ( ucb::ContentCreationException & )
+ {
+ return uno::Reference< ucb::XContent >();
+ }
+}
+
+//=========================================================================
+// virtual
+rtl::OUString Content::getParentURL()
+{
+ // <scheme>:// -> ""
+ // <scheme>://foo -> ""
+ // <scheme>://foo/ -> ""
+ // <scheme>://foo/bar -> <scheme>://foo/
+ // <scheme>://foo/bar/ -> <scheme>://foo/
+ // <scheme>://foo/bar/abc -> <scheme>://foo/bar/
+
+ rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
+
+ sal_Int32 nPos = aURL.lastIndexOf( '/' );
+ if ( nPos == ( aURL.getLength() - 1 ) )
+ {
+ // Trailing slash found. Skip.
+ nPos = aURL.lastIndexOf( '/', nPos );
+ }
+
+ sal_Int32 nPos1 = aURL.lastIndexOf( '/', nPos );
+ if ( nPos1 != -1 )
+ nPos1 = aURL.lastIndexOf( '/', nPos1 );
+
+ if ( nPos1 == -1 )
+ return rtl::OUString();
+
+ return rtl::OUString( aURL.copy( 0, nPos + 1 ) );
+}
+
+//=========================================================================
+//
+// Non-interface methods.
+//
+//=========================================================================
+
+// static
+uno::Reference< sdbc::XRow > Content::getPropertyValues(
+ const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
+ const uno::Sequence< beans::Property >& rProperties,
+ const ContentProperties& rData,
+ const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider,
+ const rtl::OUString& rContentId )
+{
+ // Note: Empty sequence means "get values of all supported properties".
+
+ rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
+ = new ::ucbhelper::PropertyValueSet( rSMgr );
+
+ sal_Int32 nCount = rProperties.getLength();
+ if ( nCount )
+ {
+ uno::Reference< beans::XPropertySet > xAdditionalPropSet;
+ sal_Bool bTriedToGetAdditonalPropSet = sal_False;
+
+ const beans::Property* pProps = rProperties.getConstArray();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const beans::Property& rProp = pProps[ n ];
+
+ // Process standard UCB, DAV and HTTP properties.
+ const uno::Any & rValue = rData.getValue( rProp.Name );
+ if ( rValue.hasValue() )
+ {
+ xRow->appendObject( rProp, rValue );
+ }
+ else
+ {
+ // Process local Additional Properties.
+ if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
+ {
+ xAdditionalPropSet
+ = uno::Reference< beans::XPropertySet >(
+ rProvider->getAdditionalPropertySet( rContentId,
+ sal_False ),
+ uno::UNO_QUERY );
+ bTriedToGetAdditonalPropSet = sal_True;
+ }
+
+ if ( !xAdditionalPropSet.is() ||
+ !xRow->appendPropertySetValue(
+ xAdditionalPropSet, rProp ) )
+ {
+ // Append empty entry.
+ xRow->appendVoid( rProp );
+ }
+ }
+ }
+ }
+ else
+ {
+ // Append all standard UCB, DAV and HTTP properties.
+
+ const std::auto_ptr< PropertyValueMap > & xProps = rData.getProperties();
+
+ PropertyValueMap::const_iterator it = xProps->begin();
+ PropertyValueMap::const_iterator end = xProps->end();
+
+ ContentProvider * pProvider
+ = static_cast< ContentProvider * >( rProvider.get() );
+ beans::Property aProp;
+
+ while ( it != end )
+ {
+ if ( pProvider->getProperty( (*it).first, aProp ) )
+ xRow->appendObject( aProp, (*it).second.value() );
+
+ ++it;
+ }
+
+ // Append all local Additional Properties.
+ uno::Reference< beans::XPropertySet > xSet(
+ rProvider->getAdditionalPropertySet( rContentId, sal_False ),
+ uno::UNO_QUERY );
+ xRow->appendPropertySet( xSet );
+ }
+
+ return uno::Reference< sdbc::XRow >( xRow.get() );
+}
+
+//=========================================================================
+uno::Reference< sdbc::XRow > Content::getPropertyValues(
+ const uno::Sequence< beans::Property >& rProperties,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw ( uno::Exception )
+{
+ std::auto_ptr< ContentProperties > xProps;
+ std::auto_ptr< ContentProperties > xCachedProps;
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ rtl::OUString aEscapedTitle;
+ bool bHasAll = false;
+ uno::Reference< lang::XMultiServiceFactory > xSMgr;
+ uno::Reference< ucb::XContentIdentifier > xIdentifier;
+ rtl::Reference< ::ucbhelper::ContentProviderImplHelper > xProvider;
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ aEscapedTitle = NeonUri::unescape( m_aEscapedTitle );
+ xSMgr.set( m_xSMgr );
+ xIdentifier.set( m_xIdentifier );
+ xProvider.set( m_xProvider.get() );
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+
+ // First, ask cache...
+ if ( m_xCachedProps.get() )
+ {
+ xCachedProps.reset( new ContentProperties( *m_xCachedProps.get() ) );
+
+ std::vector< rtl::OUString > aMissingProps;
+ if ( xCachedProps->containsAllNames( rProperties, aMissingProps ) )
+ {
+ // All properties are already in cache! No server access needed.
+ bHasAll = true;
+ }
+
+ // use the cached ContentProperties instance
+ xProps.reset( new ContentProperties( *xCachedProps.get() ) );
+ }
+ }
+
+ if ( !m_bTransient && !bHasAll )
+ {
+ /////////////////////////////////////////////////////////////////////
+ // Obtain values from server...
+ /////////////////////////////////////////////////////////////////////
+
+ // First, identify whether resource is DAV or not
+ const ResourceType & rType = getResourceType( xEnv, xResAccess );
+
+ bool bNetworkAccessAllowed = true;
+
+ if ( DAV == rType )
+ {
+ // cache lookup... getResourceType may fill the props cache via
+ // PROPFIND!
+ if ( m_xCachedProps.get() )
+ {
+ xCachedProps.reset(
+ new ContentProperties( *m_xCachedProps.get() ) );
+
+ std::vector< rtl::OUString > aMissingProps;
+ if ( xCachedProps->containsAllNames(
+ rProperties, aMissingProps ) )
+ {
+ // All properties are already in cache! No server access
+ // needed.
+ bHasAll = true;
+ }
+
+ // use the cached ContentProperties instance
+ xProps.reset( new ContentProperties( *xCachedProps.get() ) );
+ }
+
+ if ( !bHasAll )
+ {
+ // Only DAV resources support PROPFIND
+ std::vector< rtl::OUString > aPropNames;
+
+ uno::Sequence< beans::Property > aProperties(
+ rProperties.getLength() );
+
+ if ( m_aFailedPropNames.size() > 0 )
+ {
+ sal_Int32 nProps = 0;
+ sal_Int32 nCount = rProperties.getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const rtl::OUString & rName = rProperties[ n ].Name;
+
+ std::vector< rtl::OUString >::const_iterator it
+ = m_aFailedPropNames.begin();
+ std::vector< rtl::OUString >::const_iterator end
+ = m_aFailedPropNames.end();
+
+ while ( it != end )
+ {
+ if ( *it == rName )
+ break;
+
+ ++it;
+ }
+
+ if ( it == end )
+ {
+ aProperties[ nProps ] = rProperties[ n ];
+ nProps++;
+ }
+ }
+
+ aProperties.realloc( nProps );
+ }
+ else
+ {
+ aProperties = rProperties;
+ }
+
+ if ( aProperties.getLength() > 0 )
+ ContentProperties::UCBNamesToDAVNames(
+ aProperties, aPropNames );
+
+ if ( aPropNames.size() > 0 )
+ {
+ std::vector< DAVResource > resources;
+ try
+ {
+ xResAccess->PROPFIND(
+ DAVZERO, aPropNames, resources, xEnv );
+
+ if ( 1 == resources.size() )
+ {
+ if ( xProps.get())
+ xProps->addProperties(
+ aPropNames,
+ ContentProperties( resources[ 0 ] ));
+ else
+ xProps.reset(
+ new ContentProperties( resources[ 0 ] ) );
+ }
+ }
+ catch ( DAVException const & e )
+ {
+ bNetworkAccessAllowed
+ = shouldAccessNetworkAfterException( e );
+
+ if ( !bNetworkAccessAllowed )
+ {
+ cancelCommandExecution( e, xEnv );
+ // unreachable
+ }
+ }
+ }
+ }
+ }
+
+ if ( bNetworkAccessAllowed )
+ {
+ // All properties obtained already?
+ std::vector< rtl::OUString > aMissingProps;
+ if ( !( xProps.get()
+ && xProps->containsAllNames(
+ rProperties, aMissingProps ) )
+ && !m_bDidGetOrHead )
+ {
+ // Possibly the missing props can be obtained using a HEAD
+ // request.
+
+ std::vector< rtl::OUString > aHeaderNames;
+ ContentProperties::UCBNamesToHTTPNames(
+ rProperties,
+ aHeaderNames,
+ true /* bIncludeUnmatched */ );
+
+ if ( aHeaderNames.size() > 0 )
+ {
+ try
+ {
+ DAVResource resource;
+ xResAccess->HEAD( aHeaderNames, resource, xEnv );
+ m_bDidGetOrHead = true;
+
+ if ( xProps.get() )
+ xProps->addProperties(
+ aMissingProps,
+ ContentProperties( resource ) );
+ else
+ xProps.reset ( new ContentProperties( resource ) );
+
+ if ( m_eResourceType == NON_DAV )
+ xProps->addProperties( aMissingProps,
+ ContentProperties(
+ aEscapedTitle,
+ false ) );
+ }
+ catch ( DAVException const & e )
+ {
+ bNetworkAccessAllowed
+ = shouldAccessNetworkAfterException( e );
+
+ if ( !bNetworkAccessAllowed )
+ {
+ cancelCommandExecution( e, xEnv );
+ // unreachable
+ }
+ }
+ }
+ }
+ }
+
+ // might trigger HTTP redirect.
+ // Therefore, title must be updated here.
+ NeonUri aUri( xResAccess->getURL() );
+ aEscapedTitle = aUri.GetPathBaseName();
+
+ if ( UNKNOWN == rType )
+ {
+ xProps.reset( new ContentProperties( aEscapedTitle ) );
+ }
+
+ // For DAV resources we only know the Title, for non-DAV
+ // resources we additionally know that it is a document.
+ if ( DAV == rType )
+ {
+ //xProps.reset(
+ // new ContentProperties( aEscapedTitle ) );
+ xProps->addProperty(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
+ uno::makeAny( aEscapedTitle ),
+ true );
+ }
+ else
+ {
+ if ( !xProps.get() )
+ xProps.reset( new ContentProperties( aEscapedTitle, false ) );
+ else
+ xProps->addProperty(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
+ uno::makeAny( aEscapedTitle ),
+ true );
+
+ xProps->addProperty(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ),
+ uno::makeAny( false ),
+ true );
+ xProps->addProperty(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ),
+ uno::makeAny( true ),
+ true );
+ }
+ }
+ else
+ {
+ // No server access for just created (not yet committed) objects.
+ // Only a minimal set of properties supported at this stage.
+ if (m_bTransient)
+ xProps.reset( new ContentProperties( aEscapedTitle,
+ m_bCollection ) );
+ }
+
+ sal_Int32 nCount = rProperties.getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const rtl::OUString rName = rProperties[ n ].Name;
+ if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "BaseURI" ) ) )
+ {
+ // Add BaseURI property, if requested.
+ xProps->addProperty(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ),
+ uno::makeAny( getBaseURI( xResAccess ) ),
+ true );
+ }
+ else if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
+ {
+ // Add CreatableContentsInfo property, if requested.
+ sal_Bool bFolder = sal_False;
+ xProps->getValue(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ) )
+ >>= bFolder;
+ xProps->addProperty(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ),
+ uno::makeAny( bFolder
+ ? queryCreatableContentsInfo()
+ : uno::Sequence< ucb::ContentInfo >() ),
+ true );
+ }
+ }
+
+ uno::Reference< sdbc::XRow > xResultRow
+ = getPropertyValues( xSMgr,
+ rProperties,
+ *xProps,
+ xProvider,
+ xIdentifier->getContentIdentifier() );
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ if ( !m_xCachedProps.get() )
+ m_xCachedProps.reset( new ContentProperties( *xProps.get() ) );
+ else
+ m_xCachedProps->addProperties( *xProps.get() );
+
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ m_aEscapedTitle = aEscapedTitle;
+ }
+
+ return xResultRow;
+}
+
+//=========================================================================
+uno::Sequence< uno::Any > Content::setPropertyValues(
+ const uno::Sequence< beans::PropertyValue >& rValues,
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw ( uno::Exception )
+{
+ uno::Reference< lang::XMultiServiceFactory > xSMgr;
+ uno::Reference< ucb::XContentIdentifier > xIdentifier;
+ rtl::Reference< ContentProvider > xProvider;
+ sal_Bool bTransient;
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ xProvider.set( m_pProvider );
+ xIdentifier.set( m_xIdentifier );
+ bTransient = m_bTransient;
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ xSMgr.set( m_xSMgr );
+ }
+
+ uno::Sequence< uno::Any > aRet( rValues.getLength() );
+ uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
+ sal_Int32 nChanged = 0;
+
+ beans::PropertyChangeEvent aEvent;
+ aEvent.Source = static_cast< cppu::OWeakObject * >( this );
+ aEvent.Further = sal_False;
+ // aEvent.PropertyName =
+ aEvent.PropertyHandle = -1;
+ // aEvent.OldValue =
+ // aEvent.NewValue =
+
+ std::vector< ProppatchValue > aProppatchValues;
+ std::vector< sal_Int32 > aProppatchPropsPositions;
+
+ uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
+ sal_Bool bTriedToGetAdditonalPropSet = sal_False;
+
+ sal_Bool bExchange = sal_False;
+ rtl::OUString aNewTitle;
+ rtl::OUString aOldTitle;
+ sal_Int32 nTitlePos = -1;
+
+ uno::Reference< beans::XPropertySetInfo > xInfo;
+
+ const beans::PropertyValue* pValues = rValues.getConstArray();
+ sal_Int32 nCount = rValues.getLength();
+ for ( sal_Int32 n = 0; n < nCount; ++n )
+ {
+ const beans::PropertyValue& rValue = pValues[ n ];
+ const rtl::OUString & rName = rValue.Name;
+
+ beans::Property aTmpProp;
+ xProvider->getProperty( rName, aTmpProp );
+
+ if ( aTmpProp.Attributes & beans::PropertyAttribute::READONLY )
+ {
+ // Read-only property!
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ continue;
+ }
+
+ //////////////////////////////////////////////////////////////////
+ // Mandatory props.
+ //////////////////////////////////////////////////////////////////
+
+ if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
+ {
+ // Read-only property!
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ else if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
+ {
+ // Read-only property!
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ else if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
+ {
+ // Read-only property!
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
+ {
+ rtl::OUString aNewValue;
+ if ( rValue.Value >>= aNewValue )
+ {
+ // No empty titles!
+ if ( aNewValue.getLength() > 0 )
+ {
+ try
+ {
+ NeonUri aURI( xIdentifier->getContentIdentifier() );
+ aOldTitle = aURI.GetPathBaseNameUnescaped();
+
+ if ( aNewValue != aOldTitle )
+ {
+ // modified title -> modified URL -> exchange !
+ if ( !bTransient )
+ bExchange = sal_True;
+
+ // new value will be set later...
+ aNewTitle = aNewValue;
+
+ // remember position within sequence of values (for
+ // error handling).
+ nTitlePos = n;
+ }
+ }
+ catch ( DAVException const & )
+ {
+ aRet[ n ] <<= lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Invalid content identifier!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 );
+ }
+ }
+ else
+ {
+ aRet[ n ] <<= lang::IllegalArgumentException(
+ rtl::OUString::createFromAscii(
+ "Empty title not allowed!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 );
+ }
+ }
+ else
+ {
+ aRet[ n ] <<= beans::IllegalTypeException(
+ rtl::OUString::createFromAscii(
+ "Property value has wrong type!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ }
+ else
+ {
+ //////////////////////////////////////////////////////////////
+ // Optional props.
+ //////////////////////////////////////////////////////////////
+
+ if ( !xInfo.is() )
+ xInfo = getPropertySetInfo( xEnv,
+ sal_False /* don't cache data */ );
+
+ if ( !xInfo->hasPropertyByName( rName ) )
+ {
+ // Check, whether property exists. Skip otherwise.
+ // PROPPATCH::set would add the property automatically, which
+ // is not allowed for "setPropertyValues" command!
+ aRet[ n ] <<= beans::UnknownPropertyException(
+ rtl::OUString::createFromAscii(
+ "Property is unknown!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ continue;
+ }
+
+ if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
+ {
+ // Read-only property!
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ else if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) )
+ {
+ // Read-only property!
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ else if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
+ {
+ // Read-only property!
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ else if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
+ {
+ // Read-only property!
+ // (but could be writable, if 'getcontenttype' would be)
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ if ( rName.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
+ {
+ // Read-only property!
+ aRet[ n ] <<= lang::IllegalAccessException(
+ rtl::OUString::createFromAscii(
+ "Property is read-only!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ else
+ {
+ if ( getResourceType( xEnv, xResAccess ) == DAV )
+ {
+ // Property value will be set on server.
+ ProppatchValue aValue( PROPSET, rName, rValue.Value );
+ aProppatchValues.push_back( aValue );
+
+ // remember position within sequence of values (for
+ // error handling).
+ aProppatchPropsPositions.push_back( n );
+ }
+ else
+ {
+ // Property value will be stored in local property store.
+ if ( !bTriedToGetAdditonalPropSet &&
+ !xAdditionalPropSet.is() )
+ {
+ xAdditionalPropSet
+ = getAdditionalPropertySet( sal_False );
+ bTriedToGetAdditonalPropSet = sal_True;
+ }
+
+ if ( xAdditionalPropSet.is() )
+ {
+ try
+ {
+ uno::Any aOldValue
+ = xAdditionalPropSet->getPropertyValue( rName );
+ if ( aOldValue != rValue.Value )
+ {
+ xAdditionalPropSet->setPropertyValue(
+ rName, rValue.Value );
+
+ aEvent.PropertyName = rName;
+ aEvent.OldValue = aOldValue;
+ aEvent.NewValue = rValue.Value;
+
+ aChanges.getArray()[ nChanged ] = aEvent;
+ nChanged++;
+ }
+ }
+ catch ( beans::UnknownPropertyException const & e )
+ {
+ aRet[ n ] <<= e;
+ }
+ catch ( lang::WrappedTargetException const & e )
+ {
+ aRet[ n ] <<= e;
+ }
+ catch ( beans::PropertyVetoException const & e )
+ {
+ aRet[ n ] <<= e;
+ }
+ catch ( lang::IllegalArgumentException const & e )
+ {
+ aRet[ n ] <<= e;
+ }
+ }
+ else
+ {
+ aRet[ n ] <<= uno::Exception(
+ rtl::OUString::createFromAscii(
+ "No property set for storing the value!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ }
+ }
+ }
+ } // for
+
+ if ( !bTransient && aProppatchValues.size() )
+ {
+ try
+ {
+ // Set property values at server.
+ xResAccess->PROPPATCH( aProppatchValues, xEnv );
+
+ std::vector< ProppatchValue >::const_iterator it
+ = aProppatchValues.begin();
+ std::vector< ProppatchValue >::const_iterator end
+ = aProppatchValues.end();
+
+ while ( it != end )
+ {
+ aEvent.PropertyName = (*it).name;
+ aEvent.OldValue = uno::Any(); // @@@ to expensive to obtain!
+ aEvent.NewValue = (*it).value;
+
+ aChanges.getArray()[ nChanged ] = aEvent;
+ nChanged++;
+
+ ++it;
+ }
+ }
+ catch ( DAVException const & e )
+ {
+// OSL_ENSURE( sal_False,
+// "Content::setPropertyValues - PROPPATCH failed!" );
+
+#if 1
+ cancelCommandExecution( e, xEnv );
+ // unreachable
+#else
+ // Note: PROPPATCH either sets ALL property values OR NOTHING.
+
+ std::vector< sal_Int32 >::const_iterator it
+ = aProppatchPropsPositions.begin();
+ std::vector< sal_Int32 >::const_iterator end
+ = aProppatchPropsPositions.end();
+
+ while ( it != end )
+ {
+ // Set error.
+ aRet[ (*it) ] <<= MapDAVException( e, sal_True );
+ ++it;
+ }
+#endif
+ }
+ }
+
+ if ( bExchange )
+ {
+ // Assemble new content identifier...
+
+ rtl::OUString aNewURL = getParentURL();
+ if ( aNewURL.lastIndexOf( '/' ) != ( aNewURL.getLength() - 1 ) )
+ aNewURL += rtl::OUString::createFromAscii( "/" );
+
+ aNewURL += NeonUri::escapeSegment( aNewTitle );
+
+ uno::Reference< ucb::XContentIdentifier > xNewId
+ = new ::ucbhelper::ContentIdentifier( xSMgr, aNewURL );
+ uno::Reference< ucb::XContentIdentifier > xOldId = xIdentifier;
+
+ try
+ {
+ NeonUri sourceURI( xOldId->getContentIdentifier() );
+ NeonUri targetURI( xNewId->getContentIdentifier() );
+ targetURI.SetScheme( sourceURI.GetScheme() );
+
+ xResAccess->MOVE(
+ sourceURI.GetPath(), targetURI.GetURI(), sal_False, xEnv );
+ // @@@ Should check for resources that could not be moved
+ // (due to source access or target overwrite) and send
+ // this information through the interaction handler.
+
+ // @@@ Existing content should be checked to see if it needs
+ // to be deleted at the source
+
+ // @@@ Existing content should be checked to see if it has
+ // been overwritten at the target
+
+ if ( exchangeIdentity( xNewId ) )
+ {
+ xResAccess->setURL( aNewURL );
+
+// DAV resources store all additional props on server!
+// // Adapt Additional Core Properties.
+// renameAdditionalPropertySet( xOldId->getContentIdentifier(),
+// xNewId->getContentIdentifier(),
+// sal_True );
+ }
+ else
+ {
+ // Do not set new title!
+ aNewTitle = rtl::OUString();
+
+ // Set error .
+ aRet[ nTitlePos ] <<= uno::Exception(
+ rtl::OUString::createFromAscii( "Exchange failed!" ),
+ static_cast< cppu::OWeakObject * >( this ) );
+ }
+ }
+ catch ( DAVException const & e )
+ {
+ // Do not set new title!
+ aNewTitle = rtl::OUString();
+
+ // Set error .
+ aRet[ nTitlePos ] <<= MapDAVException( e, sal_True );
+ }
+ }
+
+ if ( aNewTitle.getLength() )
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" );
+ aEvent.OldValue = uno::makeAny( aOldTitle );
+ aEvent.NewValue = uno::makeAny( aNewTitle );
+
+ m_aEscapedTitle = NeonUri::escapeSegment( aNewTitle );
+
+ aChanges.getArray()[ nChanged ] = aEvent;
+ nChanged++;
+ }
+
+ if ( nChanged > 0 )
+ {
+ aChanges.realloc( nChanged );
+ notifyPropertiesChange( aChanges );
+ }
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+
+ return aRet;
+}
+
+//=========================================================================
+uno::Any Content::open(
+ const ucb::OpenCommandArgument2 & rArg,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( uno::Exception )
+{
+ uno::Any aRet;
+
+ sal_Bool bOpenFolder = ( ( rArg.Mode == ucb::OpenMode::ALL ) ||
+ ( rArg.Mode == ucb::OpenMode::FOLDERS ) ||
+ ( rArg.Mode == ucb::OpenMode::DOCUMENTS ) );
+ if ( bOpenFolder )
+ {
+ if ( isFolder( xEnv ) )
+ {
+ // Open collection.
+
+ uno::Reference< ucb::XDynamicResultSet > xSet
+ = new DynamicResultSet( m_xSMgr, this, rArg, xEnv );
+ aRet <<= xSet;
+ }
+ else
+ {
+ // Error: Not a folder!
+
+ rtl::OUStringBuffer aMsg;
+ if ( getResourceType( xEnv ) == FTP )
+ {
+ // #114653#
+ aMsg.appendAscii( "FTP over HTTP proxy: resource cannot "
+ "be opened as folder! Wrong Open Mode!" );
+ }
+ else
+ {
+ aMsg.appendAscii( "Non-folder resource cannot be "
+ "opened as folder! Wrong Open Mode!" );
+ }
+
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ lang::IllegalArgumentException(
+ aMsg.makeStringAndClear(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 ) ),
+ xEnv );
+ // Unreachable
+ }
+ }
+
+ if ( rArg.Sink.is() )
+ {
+ // Open document.
+
+ if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
+ ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
+ {
+ // Currently(?) unsupported.
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ ucb::UnsupportedOpenModeException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ sal_Int16( rArg.Mode ) ) ),
+ xEnv );
+ // Unreachable
+ }
+
+ rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
+ uno::Reference< io::XOutputStream > xOut
+ = uno::Reference< io::XOutputStream >( rArg.Sink, uno::UNO_QUERY );
+ if ( xOut.is() )
+ {
+ // PUSH: write data
+ try
+ {
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+
+ xResAccess.reset(
+ new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+
+ DAVResource aResource;
+ std::vector< rtl::OUString > aHeaders;
+
+ xResAccess->GET( xOut, aHeaders, aResource, xEnv );
+ m_bDidGetOrHead = true;
+
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+
+ // cache headers.
+ if ( !m_xCachedProps.get())
+ m_xCachedProps.reset(
+ new ContentProperties( aResource ) );
+ else
+ m_xCachedProps->addProperties( aResource );
+
+ m_xResAccess.reset(
+ new DAVResourceAccess( *xResAccess.get() ) );
+ }
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, xEnv );
+ // Unreachable
+ }
+ }
+ else
+ {
+ uno::Reference< io::XActiveDataSink > xDataSink
+ = uno::Reference< io::XActiveDataSink >( rArg.Sink,
+ uno::UNO_QUERY );
+ if ( xDataSink.is() )
+ {
+ // PULL: wait for client read
+ try
+ {
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+
+ xResAccess.reset(
+ new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+
+ // fill inputsream sync; return if all data present
+ DAVResource aResource;
+ std::vector< rtl::OUString > aHeaders;
+
+ uno::Reference< io::XInputStream > xIn
+ = xResAccess->GET( aHeaders, aResource, xEnv );
+ m_bDidGetOrHead = true;
+
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+
+ // cache headers.
+ if ( !m_xCachedProps.get())
+ m_xCachedProps.reset(
+ new ContentProperties( aResource ) );
+ else
+ m_xCachedProps->addProperties(
+ aResource.properties );
+
+ m_xResAccess.reset(
+ new DAVResourceAccess( *xResAccess.get() ) );
+ }
+
+ xDataSink->setInputStream( xIn );
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, xEnv );
+ // Unreachable
+ }
+ }
+ else
+ {
+ // Note: aOpenCommand.Sink may contain an XStream
+ // implementation. Support for this type of
+ // sink is optional...
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ ucb::UnsupportedDataSinkException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ rArg.Sink ) ),
+ xEnv );
+ // Unreachable
+ }
+ }
+ }
+
+ return aRet;
+}
+
+//=========================================================================
+void Content::post(
+ const ucb::PostCommandArgument2 & rArg,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+ throw( uno::Exception )
+{
+ uno::Reference< io::XActiveDataSink > xSink( rArg.Sink, uno::UNO_QUERY );
+ if ( xSink.is() )
+ {
+ try
+ {
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+ xResAccess.reset(
+ new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+
+ uno::Reference< io::XInputStream > xResult
+ = xResAccess->POST( rArg.MediaType,
+ rArg.Referer,
+ rArg.Source,
+ xEnv );
+
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+ m_xResAccess.reset(
+ new DAVResourceAccess( *xResAccess.get() ) );
+ }
+
+ xSink->setInputStream( xResult );
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, xEnv, sal_True );
+ // Unreachable
+ }
+ }
+ else
+ {
+ uno::Reference< io::XOutputStream > xResult( rArg.Sink, uno::UNO_QUERY );
+ if ( xResult.is() )
+ {
+ try
+ {
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+ xResAccess.reset(
+ new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+
+ xResAccess->POST( rArg.MediaType,
+ rArg.Referer,
+ rArg.Source,
+ xResult,
+ xEnv );
+
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+ m_xResAccess.reset(
+ new DAVResourceAccess( *xResAccess.get() ) );
+ }
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, xEnv, sal_True );
+ // Unreachable
+ }
+ }
+ else
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ ucb::UnsupportedDataSinkException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ rArg.Sink ) ),
+ xEnv );
+ // Unreachable
+ }
+ }
+}
+
+//=========================================================================
+void Content::queryChildren( ContentRefList& rChildren )
+{
+ // Obtain a list with a snapshot of all currently instanciated contents
+ // from provider and extract the contents which are direct children
+ // of this content.
+
+ ::ucbhelper::ContentRefList aAllContents;
+ m_xProvider->queryExistingContents( aAllContents );
+
+ rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
+ sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
+
+ if ( nURLPos != ( aURL.getLength() - 1 ) )
+ {
+ // No trailing slash found. Append.
+ aURL += rtl::OUString::createFromAscii( "/" );
+ }
+
+ sal_Int32 nLen = aURL.getLength();
+
+ ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
+ ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
+
+ while ( it != end )
+ {
+ ::ucbhelper::ContentImplHelperRef xChild = (*it);
+ rtl::OUString aChildURL
+ = xChild->getIdentifier()->getContentIdentifier();
+
+ // Is aURL a prefix of aChildURL?
+ if ( ( aChildURL.getLength() > nLen ) &&
+ ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
+ {
+ sal_Int32 nPos = nLen;
+ nPos = aChildURL.indexOf( '/', nPos );
+
+ if ( ( nPos == -1 ) ||
+ ( nPos == ( aChildURL.getLength() - 1 ) ) )
+ {
+ // No further slashes / only a final slash. It's a child!
+ rChildren.push_back(
+ ::webdav_ucp::Content::ContentRef(
+ static_cast< ::webdav_ucp::Content * >(
+ xChild.get() ) ) );
+ }
+ }
+ ++it;
+ }
+}
+
+//=========================================================================
+void Content::insert(
+ const uno::Reference< io::XInputStream > & xInputStream,
+ sal_Bool bReplaceExisting,
+ const uno::Reference< ucb::XCommandEnvironment >& Environment )
+ throw( uno::Exception )
+{
+ sal_Bool bTransient, bCollection;
+ rtl::OUString aEscapedTitle;
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ bTransient = m_bTransient;
+ bCollection = m_bCollection;
+ aEscapedTitle = m_aEscapedTitle;
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+
+ // Check, if all required properties are present.
+
+ if ( aEscapedTitle.getLength() == 0 )
+ {
+ OSL_ENSURE( sal_False, "Content::insert - Title missing!" );
+
+ uno::Sequence< rtl::OUString > aProps( 1 );
+ aProps[ 0 ] = rtl::OUString::createFromAscii( "Title" );
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( ucb::MissingPropertiesException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ aProps ) ),
+ Environment );
+ // Unreachable
+ }
+
+ if ( !bReplaceExisting )
+ {
+ /* [RFC 2616] - HTTP
+
+ The PUT method requests that the enclosed entity be stored under the
+ supplied Request-URI. If the Request-URI refers to an already
+ existing resource, the enclosed entity SHOULD be considered as a
+ modified version of the one residing on the origin server.
+ */
+
+ /* [RFC 2518] - WebDAV
+
+ MKCOL creates a new collection resource at the location specified by
+ the Request-URI. If the resource identified by the Request-URI is
+ non-null then the MKCOL MUST fail.
+ */
+
+ // ==> Complain on PUT, continue on MKCOL.
+ if ( !bTransient || ( bTransient && !bCollection ) )
+ {
+ ucb::UnsupportedNameClashException aEx(
+ rtl::OUString::createFromAscii(
+ "Unable to write without overwrite!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ ucb::NameClash::ERROR );
+
+ uno::Reference< task::XInteractionHandler > xIH;
+
+ if ( Environment.is() )
+ xIH = Environment->getInteractionHandler();
+
+ if ( xIH.is() )
+ {
+ uno::Any aExAsAny( uno::makeAny( aEx ) );
+
+ rtl::Reference< ucbhelper::SimpleInteractionRequest > xRequest
+ = new ucbhelper::SimpleInteractionRequest(
+ aExAsAny,
+ ucbhelper::CONTINUATION_APPROVE
+ | ucbhelper::CONTINUATION_DISAPPROVE );
+ xIH->handle( xRequest.get() );
+
+ const sal_Int32 nResp = xRequest->getResponse();
+
+ switch ( nResp )
+ {
+ case ucbhelper::CONTINUATION_UNKNOWN:
+ // Not handled; throw.
+ throw aEx;
+// break;
+
+ case ucbhelper::CONTINUATION_APPROVE:
+ // Continue -> Overwrite.
+ bReplaceExisting = sal_True;
+ break;
+
+ case ucbhelper::CONTINUATION_DISAPPROVE:
+ // Abort.
+ throw ucb::CommandFailedException(
+ rtl::OUString(),
+ uno::Reference< uno::XInterface >(),
+ aExAsAny );
+// break;
+
+ default:
+ OSL_ENSURE( sal_False,
+ "Content::insert - "
+ "Unknown interaction selection!" );
+ throw ucb::CommandFailedException(
+ rtl::OUString::createFromAscii(
+ "Unknown interaction selection!" ),
+ uno::Reference< uno::XInterface >(),
+ aExAsAny );
+// break;
+ }
+ }
+ else
+ {
+ // No IH; throw.
+ throw aEx;
+ }
+ }
+ }
+
+ if ( bTransient )
+ {
+ // Assemble new content identifier...
+ rtl::OUString aURL = getParentURL();
+ if ( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ) )
+ aURL += rtl::OUString::createFromAscii( "/" );
+
+ aURL += aEscapedTitle;
+
+ try
+ {
+ xResAccess->setURL( aURL );
+
+ if ( bCollection )
+ xResAccess->MKCOL( Environment );
+ else
+ xResAccess->PUT( xInputStream, Environment );
+ }
+ catch ( DAVException const & except )
+ {
+ if ( bCollection )
+ {
+ if ( except.getStatus() == SC_METHOD_NOT_ALLOWED )
+ {
+ // [RFC 2518] - WebDAV
+ // 405 (Method Not Allowed) - MKCOL can only be
+ // executed on a deleted/non-existent resource.
+
+ if ( bReplaceExisting )
+ {
+ // Destroy old resource.
+ try
+ {
+ xResAccess->DESTROY( Environment );
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, Environment, sal_True );
+ // Unreachable
+ }
+
+ // Insert (recursion!).
+ insert( xInputStream, bReplaceExisting, Environment );
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset(
+ new DAVResourceAccess( *xResAccess.get() ) );
+ }
+
+ // Success!
+ return;
+ }
+ else
+ {
+ rtl::OUString aTitle;
+ try
+ {
+ NeonUri aURI( aURL );
+ aTitle = aURI.GetPathBaseNameUnescaped();
+ }
+ catch ( DAVException const & )
+ {
+ }
+
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ ucb::NameClashException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ aTitle ) ),
+ Environment );
+ // Unreachable
+ }
+ }
+ }
+
+ cancelCommandExecution( except, Environment, sal_True );
+ // Unreachable
+ }
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xIdentifier
+ = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL );
+ }
+
+ inserted();
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_bTransient = sal_False;
+ }
+ }
+ else
+ {
+ if ( !xInputStream.is() )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ ucb::MissingInputStreamException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ) ) ),
+ Environment );
+ // Unreachable
+ }
+
+ try
+ {
+ xResAccess->PUT( xInputStream, Environment );
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, Environment, sal_True );
+ // Unreachable
+ }
+ }
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+}
+
+//=========================================================================
+void Content::transfer(
+ const ucb::TransferInfo & rArgs,
+ const uno::Reference< ucb::XCommandEnvironment >& Environment )
+ throw( uno::Exception )
+{
+ uno::Reference< lang::XMultiServiceFactory > xSMgr;
+ uno::Reference< ucb::XContentIdentifier > xIdentifier;
+ uno::Reference< ucb::XContentProvider > xProvider;
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ xSMgr.set( m_xSMgr );
+ xIdentifier.set( m_xIdentifier );
+ xProvider.set( m_xProvider.get() );
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+
+ rtl::OUString aTargetURI;
+ try
+ {
+ NeonUri sourceURI( rArgs.SourceURL );
+ NeonUri targetURI( xIdentifier->getContentIdentifier() );
+ aTargetURI = targetURI.GetPathBaseNameUnescaped();
+
+ // Check source's and target's URL scheme
+ //
+ const rtl::OUString aScheme = sourceURI.GetScheme().toAsciiLowerCase();
+ if ( aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) )
+ {
+ sourceURI.SetScheme(
+ rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
+ }
+ else if ( aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( DAV_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( HTTP_URL_SCHEME ) ) &&
+ !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( HTTPS_URL_SCHEME ) ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ ucb::InteractiveBadTransferURLException(
+ rtl::OUString::createFromAscii(
+ "Unsupported URL scheme!" ),
+ static_cast< cppu::OWeakObject * >( this ) ) ),
+ Environment );
+ // Unreachable
+ }
+ }
+
+ if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) )
+ targetURI.SetScheme(
+ rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
+ else if ( targetURI.GetScheme().toAsciiLowerCase().equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) )
+ targetURI.SetScheme(
+ rtl::OUString::createFromAscii( HTTP_URL_SCHEME ) );
+
+ // @@@ This implementation of 'transfer' only works
+ // if the source and target are located at same host.
+ // (Neon does not support cross-server copy/move)
+
+ // Check for same host
+ //
+ if ( sourceURI.GetHost().getLength() &&
+ ( sourceURI.GetHost() != targetURI.GetHost() ) )
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny( ucb::InteractiveBadTransferURLException(
+ rtl::OUString::createFromAscii(
+ "Different hosts!" ),
+ static_cast< cppu::OWeakObject * >( this ) ) ),
+ Environment );
+ // Unreachable
+ }
+
+ rtl::OUString aTitle = rArgs.NewTitle;
+
+ if ( !aTitle.getLength() )
+ aTitle = sourceURI.GetPathBaseNameUnescaped();
+
+ if ( aTitle.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "/" ) ) )
+ {
+ // kso: ???
+ aTitle = rtl::OUString();
+ }
+
+ targetURI.AppendPath( aTitle );
+
+ rtl::OUString aTargetURL = xIdentifier->getContentIdentifier();
+ if ( ( aTargetURL.lastIndexOf( '/' ) + 1 )
+ != aTargetURL.getLength() )
+ aTargetURL += rtl::OUString::createFromAscii( "/" );
+
+ aTargetURL += aTitle;
+
+ uno::Reference< ucb::XContentIdentifier > xTargetId
+ = new ::ucbhelper::ContentIdentifier( xSMgr, aTargetURL );
+
+ DAVResourceAccess aSourceAccess( xSMgr,
+ xResAccess->getSessionFactory(),
+ sourceURI.GetURI() );
+
+ if ( rArgs.MoveData == sal_True )
+ {
+ uno::Reference< ucb::XContentIdentifier > xId
+ = new ::ucbhelper::ContentIdentifier( xSMgr, rArgs.SourceURL );
+
+ // Note: The static cast is okay here, because its sure that
+ // xProvider is always the WebDAVContentProvider.
+ rtl::Reference< Content > xSource
+ = static_cast< Content * >(
+ xProvider->queryContent( xId ).get() );
+
+ // [RFC 2518] - WebDAV
+ // If a resource exists at the destination and the Overwrite
+ // header is "T" then prior to performing the move the server
+ // MUST perform a DELETE with "Depth: infinity" on the
+ // destination resource. If the Overwrite header is set to
+ // "F" then the operation will fail.
+
+ aSourceAccess.MOVE( sourceURI.GetPath(),
+ targetURI.GetURI(),
+ rArgs.NameClash
+ == ucb::NameClash::OVERWRITE,
+ Environment );
+
+ if ( xSource.is() )
+ {
+ // Propagate destruction to listeners.
+ xSource->destroy( sal_True );
+ }
+
+// DAV resources store all additional props on server!
+// // Rename own and all children's Additional Core Properties.
+// renameAdditionalPropertySet( xId->getContentIdentifier(),
+// xTargetId->getContentIdentifier(),
+// sal_True );
+ }
+ else
+ {
+ // [RFC 2518] - WebDAV
+ // If a resource exists at the destination and the Overwrite
+ // header is "T" then prior to performing the copy the server
+ // MUST perform a DELETE with "Depth: infinity" on the
+ // destination resource. If the Overwrite header is set to
+ // "F" then the operation will fail.
+
+ aSourceAccess.COPY( sourceURI.GetPath(),
+ targetURI.GetURI(),
+ rArgs.NameClash
+ == ucb::NameClash::OVERWRITE,
+ Environment );
+
+// DAV resources store all additional props on server!
+// // Copy own and all children's Additional Core Properties.
+// copyAdditionalPropertySet( xId->getContentIdentifier(),
+// xTargetId->getContentIdentifier(),
+// sal_True );
+ }
+
+ // Note: The static cast is okay here, because its sure that
+ // xProvider is always the WebDAVContentProvider.
+ rtl::Reference< Content > xTarget
+ = static_cast< Content * >(
+ xProvider->queryContent( xTargetId ).get() );
+
+ // Announce transfered content in its new folder.
+ xTarget->inserted();
+ }
+ catch ( ucb::IllegalIdentifierException const & )
+ {
+ // queryContent
+ }
+ catch ( DAVException const & e )
+ {
+ // [RFC 2518] - WebDAV
+ // 412 (Precondition Failed) - The server was unable to maintain
+ // the liveness of the properties listed in the propertybehavior
+ // XML element or the Overwrite header is "F" and the state of
+ // the destination resource is non-null.
+
+ if ( e.getStatus() == SC_PRECONDITION_FAILED )
+ {
+ switch ( rArgs.NameClash )
+ {
+ case ucb::NameClash::ERROR:
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ ucb::NameClashException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ aTargetURI ) ),
+ Environment );
+ // Unreachable
+ }
+
+ case ucb::NameClash::OVERWRITE:
+ break;
+
+ case ucb::NameClash::KEEP: // deprecated
+ case ucb::NameClash::RENAME:
+ case ucb::NameClash::ASK:
+ default:
+ {
+ ucbhelper::cancelCommandExecution(
+ uno::makeAny(
+ ucb::UnsupportedNameClashException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ rArgs.NameClash ) ),
+ Environment );
+ // Unreachable
+ }
+ }
+ }
+
+ cancelCommandExecution( e, Environment, sal_True );
+ // Unreachable
+ }
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+}
+
+//=========================================================================
+void Content::destroy( sal_Bool bDeletePhysical )
+ throw( uno::Exception )
+{
+ // @@@ take care about bDeletePhysical -> trashcan support
+ rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
+
+ uno::Reference< ucb::XContent > xThis = this;
+
+ deleted();
+
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ // Process instanciated children...
+
+ ::webdav_ucp::Content::ContentRefList aChildren;
+ queryChildren( aChildren );
+
+ ContentRefList::const_iterator it = aChildren.begin();
+ ContentRefList::const_iterator end = aChildren.end();
+
+ while ( it != end )
+ {
+ (*it)->destroy( bDeletePhysical );
+ ++it;
+ }
+}
+
+//=========================================================================
+bool Content::supportsExclusiveWriteLock(
+ const uno::Reference< ucb::XCommandEnvironment >& Environment )
+{
+ if ( getResourceType( Environment ) == DAV )
+ {
+ if ( m_xCachedProps.get() )
+ {
+ uno::Sequence< ucb::LockEntry > aSupportedLocks;
+ if ( m_xCachedProps->getValue( DAVProperties::SUPPORTEDLOCK )
+ >>= aSupportedLocks )
+ {
+ for ( sal_Int32 n = 0; n < aSupportedLocks.getLength(); ++n )
+ {
+ if ( aSupportedLocks[ n ].Scope
+ == ucb::LockScope_EXCLUSIVE &&
+ aSupportedLocks[ n ].Type
+ == ucb::LockType_WRITE )
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+//=========================================================================
+void Content::lock(
+ const uno::Reference< ucb::XCommandEnvironment >& Environment )
+ throw( uno::Exception )
+{
+ try
+ {
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+
+ uno::Any aOwnerAny;
+ aOwnerAny
+ <<= rtl::OUString::createFromAscii( "http://ucb.openoffice.org" );
+
+ ucb::Lock aLock(
+ ucb::LockScope_EXCLUSIVE,
+ ucb::LockType_WRITE,
+ ucb::LockDepth_ZERO,
+ aOwnerAny,
+ 180, // lock timeout in secs
+ //-1, // infinite lock
+ uno::Sequence< ::rtl::OUString >() );
+
+ xResAccess->LOCK( aLock, Environment );
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, Environment, sal_False );
+ // Unreachable
+ }
+}
+
+//=========================================================================
+void Content::unlock(
+ const uno::Reference< ucb::XCommandEnvironment >& Environment )
+ throw( uno::Exception )
+{
+ try
+ {
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ }
+
+ xResAccess->UNLOCK( Environment );
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+ m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) );
+ }
+ }
+ catch ( DAVException const & e )
+ {
+ cancelCommandExecution( e, Environment, sal_False );
+ // Unreachable
+ }
+}
+
+//=========================================================================
+sal_Bool Content::exchangeIdentity(
+ const uno::Reference< ucb::XContentIdentifier >& xNewId )
+{
+ if ( !xNewId.is() )
+ return sal_False;
+
+ osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
+
+ uno::Reference< ucb::XContent > xThis = this;
+
+ // Already persistent?
+ if ( m_bTransient )
+ {
+ OSL_ENSURE( sal_False, "Content::exchangeIdentity - Not persistent!" );
+ return sal_False;
+ }
+
+ // Exchange own identitity.
+
+ // Fail, if a content with given id already exists.
+// if ( !hasData( xNewId ) )
+ {
+ rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
+
+ aGuard.clear();
+ if ( exchange( xNewId ) )
+ {
+ // Process instanciated children...
+
+ ContentRefList aChildren;
+ queryChildren( aChildren );
+
+ ContentRefList::const_iterator it = aChildren.begin();
+ ContentRefList::const_iterator end = aChildren.end();
+
+ while ( it != end )
+ {
+ ContentRef xChild = (*it);
+
+ // Create new content identifier for the child...
+ uno::Reference< ucb::XContentIdentifier >
+ xOldChildId = xChild->getIdentifier();
+ rtl::OUString aOldChildURL
+ = xOldChildId->getContentIdentifier();
+ rtl::OUString aNewChildURL
+ = aOldChildURL.replaceAt(
+ 0,
+ aOldURL.getLength(),
+ xNewId->getContentIdentifier() );
+ uno::Reference< ucb::XContentIdentifier > xNewChildId
+ = new ::ucbhelper::ContentIdentifier(
+ m_xSMgr, aNewChildURL );
+
+ if ( !xChild->exchangeIdentity( xNewChildId ) )
+ return sal_False;
+
+ ++it;
+ }
+ return sal_True;
+ }
+ }
+
+ OSL_ENSURE( sal_False,
+ "Content::exchangeIdentity - "
+ "Panic! Cannot exchange identity!" );
+ return sal_False;
+}
+
+//=========================================================================
+sal_Bool Content::isFolder(
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw( uno::Exception )
+{
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_bTransient )
+ return m_bCollection;
+ }
+
+ uno::Sequence< beans::Property > aProperties( 1 );
+ aProperties[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" );
+ aProperties[ 0 ].Handle = -1;
+ uno::Reference< sdbc::XRow > xRow( getPropertyValues( aProperties, xEnv ) );
+ if ( xRow.is() )
+ {
+ try
+ {
+ return xRow->getBoolean( 1 );
+ }
+ catch ( sdbc::SQLException const & )
+ {
+ }
+ }
+
+ return sal_False;
+}
+
+//=========================================================================
+uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite )
+{
+ // Map DAVException...
+ uno::Any aException;
+
+ switch ( e.getStatus() )
+ {
+ case SC_NOT_FOUND:
+ {
+ uno::Sequence< uno::Any > aArgs( 1 );
+ aArgs[ 0 ] <<= beans::PropertyValue(
+ rtl::OUString::createFromAscii("Uri"), -1,
+ uno::makeAny(m_xIdentifier->getContentIdentifier()),
+ beans::PropertyState_DIRECT_VALUE);
+
+ aException <<=
+ ucb::InteractiveAugmentedIOException(
+ rtl::OUString::createFromAscii( "Not found!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ ucb::IOErrorCode_NOT_EXISTING,
+ aArgs );
+ return aException;
+ }
+ default:
+ break;
+ }
+
+ switch ( e.getError() )
+ {
+ case DAVException::DAV_HTTP_ERROR:
+ {
+ if ( bWrite )
+ aException <<=
+ ucb::InteractiveNetworkWriteException(
+ e.getData(),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ e.getData() );
+ else
+ aException <<=
+ ucb::InteractiveNetworkReadException(
+ e.getData(),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ e.getData() );
+ break;
+ }
+
+ case DAVException::DAV_HTTP_LOOKUP:
+ aException <<=
+ ucb::InteractiveNetworkResolveNameException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ e.getData() );
+ break;
+
+// @@@ No matching InteractiveNetwork*Exception
+// case DAVException::DAV_HTTP_AUTH:
+// break;
+
+// @@@ No matching InteractiveNetwork*Exception
+// case DAVException::DAV_HTTP_AUTHPROXY:
+// break;
+
+ case DAVException::DAV_HTTP_CONNECT:
+ aException <<=
+ ucb::InteractiveNetworkConnectException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ e.getData() );
+ break;
+
+// @@@ No matching InteractiveNetwork*Exception
+// case DAVException::DAV_HTTP_TIMEOUT:
+// break;
+
+// @@@ No matching InteractiveNetwork*Exception
+// case DAVException::DAV_HTTP_REDIRECT:
+// break;
+
+// @@@ No matching InteractiveNetwork*Exception
+// case DAVException::DAV_SESSION_CREATE:
+// break;
+
+ case DAVException::DAV_INVALID_ARG:
+ aException <<=
+ lang::IllegalArgumentException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ -1 );
+ break;
+
+ case DAVException::DAV_LOCKED:
+#if 1
+ aException <<=
+ ucb::InteractiveLockingLockedException(
+ rtl::OUString::createFromAscii( "Locked!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ m_xIdentifier->getContentIdentifier(),
+ sal_True );
+#else
+ {
+ uno::Sequence< uno::Any > aArgs( 1 );
+ aArgs[ 0 ] <<= beans::PropertyValue(
+ rtl::OUString::createFromAscii("Uri"), -1,
+ uno::makeAny(m_xIdentifier->getContentIdentifier()),
+ beans::PropertyState_DIRECT_VALUE);
+
+ aException <<=
+ ucb::InteractiveAugmentedIOException(
+ rtl::OUString::createFromAscii( "Locked!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ ucb::IOErrorCode_LOCKING_VIOLATION,
+ aArgs );
+ }
+#endif
+ break;
+
+ case DAVException::DAV_LOCKED_SELF:
+ aException <<=
+ ucb::InteractiveLockingLockedException(
+ rtl::OUString::createFromAscii( "Locked (self)!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ m_xIdentifier->getContentIdentifier(),
+ sal_True );
+ break;
+
+ case DAVException::DAV_NOT_LOCKED:
+ aException <<=
+ ucb::InteractiveLockingNotLockedException(
+ rtl::OUString::createFromAscii( "Not locked!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ m_xIdentifier->getContentIdentifier() );
+ break;
+
+ case DAVException::DAV_LOCK_EXPIRED:
+ aException <<=
+ ucb::InteractiveLockingLockExpiredException(
+ rtl::OUString::createFromAscii( "Lock expired!" ),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR,
+ m_xIdentifier->getContentIdentifier() );
+ break;
+
+ default:
+ aException <<=
+ ucb::InteractiveNetworkGeneralException(
+ rtl::OUString(),
+ static_cast< cppu::OWeakObject * >( this ),
+ task::InteractionClassification_ERROR );
+ break;
+ }
+
+ return aException;
+}
+
+//=========================================================================
+// static
+bool Content::shouldAccessNetworkAfterException( const DAVException & e )
+{
+ if ( ( e.getStatus() == SC_NOT_FOUND ) ||
+ ( e.getError() == DAVException::DAV_HTTP_LOOKUP ) ||
+ ( e.getError() == DAVException::DAV_HTTP_CONNECT ) ||
+ ( e.getError() == DAVException::DAV_HTTP_AUTH ) ||
+ ( e.getError() == DAVException::DAV_HTTP_AUTHPROXY ) )
+ return false;
+
+ return true;
+}
+
+//=========================================================================
+void Content::cancelCommandExecution(
+ const DAVException & e,
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv,
+ sal_Bool bWrite /* = sal_False */ )
+ throw ( uno::Exception )
+{
+ ucbhelper::cancelCommandExecution( MapDAVException( e, bWrite ), xEnv );
+ // Unreachable
+}
+
+//=========================================================================
+const rtl::OUString
+Content::getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess )
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ // First, try to obtain value of response header "Content-Location".
+ if ( m_xCachedProps.get() )
+ {
+ rtl::OUString aLocation;
+ m_xCachedProps->getValue( rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "Content-Location" ) ) ) >>= aLocation;
+ if ( aLocation.getLength() )
+ {
+ try
+ {
+ // Do not use m_xIdentifier->getContentIdentifier() because it
+ // for example does not reflect redirects applied to requests
+ // done using the original URI but m_xResAccess' URI does.
+ return rtl::Uri::convertRelToAbs( rResAccess->getURL(),
+ aLocation );
+ }
+ catch ( rtl::MalformedUriException const & )
+ {
+ }
+ }
+ }
+
+ return rtl::OUString( rResAccess->getURL() );
+}
+
+//=========================================================================
+const Content::ResourceType & Content::getResourceType(
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv,
+ const std::auto_ptr< DAVResourceAccess > & rResAccess )
+ throw ( uno::Exception )
+{
+ if ( m_eResourceType == UNKNOWN )
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ ResourceType eResourceType;
+ eResourceType = m_eResourceType;
+
+ const rtl::OUString & rURL = rResAccess->getURL();
+ const rtl::OUString aScheme(
+ rURL.copy( 0, rURL.indexOf( ':' ) ).toAsciiLowerCase() );
+
+ if ( aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( FTP_URL_SCHEME ) ) )
+ {
+ eResourceType = FTP;
+ }
+ else
+ {
+ try
+ {
+ // Try to fetch some frequently used property value, e.g. those
+ // used when loading documents... along with identifying whether
+ // this is a DAV resource.
+ std::vector< DAVResource > resources;
+ std::vector< rtl::OUString > aPropNames;
+ uno::Sequence< beans::Property > aProperties( 5 );
+ aProperties[ 0 ].Name
+ = rtl::OUString::createFromAscii( "IsFolder" );
+ aProperties[ 1 ].Name
+ = rtl::OUString::createFromAscii( "IsDocument" );
+ aProperties[ 2 ].Name
+ = rtl::OUString::createFromAscii( "IsReadOnly" );
+ aProperties[ 3 ].Name
+ = rtl::OUString::createFromAscii( "MediaType" );
+ aProperties[ 4 ].Name
+ = DAVProperties::SUPPORTEDLOCK;
+
+ ContentProperties::UCBNamesToDAVNames(
+ aProperties, aPropNames );
+
+ rResAccess->PROPFIND(
+ DAVZERO, aPropNames, resources, xEnv );
+
+ if ( resources.size() == 1 )
+ {
+ m_xCachedProps.reset(
+ new ContentProperties( resources[ 0 ] ) );
+ m_xCachedProps->containsAllNames(
+ aProperties, m_aFailedPropNames );
+ }
+
+ eResourceType = DAV;
+ }
+ catch ( DAVException const & e )
+ {
+ rResAccess->resetUri();
+
+ if ( e.getStatus() == SC_METHOD_NOT_ALLOWED )
+ {
+ // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the
+ // resource is NON_DAV
+ eResourceType = NON_DAV;
+ }
+ }
+ }
+ m_eResourceType = eResourceType;
+ }
+ return m_eResourceType;
+}
+
+//=========================================================================
+const Content::ResourceType & Content::getResourceType(
+ const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+ throw ( uno::Exception )
+{
+ return getResourceType( xEnv, m_xResAccess );
+}
diff --git a/ucb/source/ucp/webdav/webdavcontent.hxx b/ucb/source/ucp/webdav/webdavcontent.hxx
new file mode 100644
index 000000000000..0568b2bfbb54
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavcontent.hxx
@@ -0,0 +1,299 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WEBDAV_UCP_CONTENT_HXX
+#define _WEBDAV_UCP_CONTENT_HXX
+
+#include <memory>
+#include <list>
+#include <rtl/ref.hxx>
+#include <com/sun/star/ucb/ContentCreationException.hpp>
+#include <com/sun/star/ucb/XContentCreator.hpp>
+#include <ucbhelper/contenthelper.hxx>
+#include "DAVResourceAccess.hxx"
+#include "PropertyMap.hxx"
+
+namespace com { namespace sun { namespace star { namespace beans {
+ struct Property;
+ struct PropertyValue;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace io {
+ class XInputStream;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace sdbc {
+ class XRow;
+} } } }
+
+namespace com { namespace sun { namespace star { namespace ucb {
+ struct OpenCommandArgument2;
+ struct PostCommandArgument2;
+ struct TransferInfo;
+} } } }
+
+namespace webdav_ucp
+{
+
+//=========================================================================
+
+// UNO service name for the content.
+#define WEBDAV_CONTENT_SERVICE_NAME "com.sun.star.ucb.WebDAVContent"
+
+//=========================================================================
+
+class ContentProvider;
+class ContentProperties;
+
+class Content : public ::ucbhelper::ContentImplHelper,
+ public com::sun::star::ucb::XContentCreator
+{
+ enum ResourceType
+ {
+ UNKNOWN,
+ FTP,
+ NON_DAV,
+ DAV
+ };
+
+ std::auto_ptr< DAVResourceAccess > m_xResAccess;
+ std::auto_ptr< ContentProperties > m_xCachedProps; // locally cached props
+ rtl::OUString m_aEscapedTitle;
+ ResourceType m_eResourceType;
+ ContentProvider* m_pProvider; // No need for a ref, base class holds object
+ bool m_bTransient;
+ bool m_bCollection;
+ bool m_bDidGetOrHead;
+ std::vector< rtl::OUString > m_aFailedPropNames;
+
+private:
+ virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property >
+ getProperties( const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv );
+ virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo >
+ getCommands( const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv );
+ virtual ::rtl::OUString getParentURL();
+
+ sal_Bool isFolder( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XCommandEnvironment >& xEnv )
+ throw ( ::com::sun::star::uno::Exception );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow >
+ getPropertyValues( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::Property >& rProperties,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XCommandEnvironment >& xEnv )
+ throw ( ::com::sun::star::uno::Exception );
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >
+ setPropertyValues( const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::PropertyValue >& rValues,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XCommandEnvironment >& xEnv )
+ throw ( ::com::sun::star::uno::Exception );
+
+ typedef rtl::Reference< Content > ContentRef;
+ typedef std::list< ContentRef > ContentRefList;
+ void queryChildren( ContentRefList& rChildren);
+
+ sal_Bool
+ exchangeIdentity( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XContentIdentifier >& xNewId );
+
+ const rtl::OUString
+ getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess );
+
+ const ResourceType &
+ getResourceType( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XCommandEnvironment >& xEnv )
+ throw ( ::com::sun::star::uno::Exception );
+
+ const ResourceType &
+ getResourceType( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XCommandEnvironment >& xEnv,
+ const std::auto_ptr< DAVResourceAccess > & rResAccess )
+ throw ( ::com::sun::star::uno::Exception );
+
+ // Command "open"
+ com::sun::star::uno::Any open(
+ const com::sun::star::ucb::OpenCommandArgument2 & rArg,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw( ::com::sun::star::uno::Exception );
+
+ // Command "post"
+ void post( const com::sun::star::ucb::PostCommandArgument2 & rArg,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv )
+ throw( ::com::sun::star::uno::Exception );
+
+ // Command "insert"
+ void insert( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::io::XInputStream > & xInputStream,
+ sal_Bool bReplaceExisting,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& Environment )
+ throw( ::com::sun::star::uno::Exception );
+
+ // Command "transfer"
+ void transfer( const ::com::sun::star::ucb::TransferInfo & rArgs,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& Environment )
+ throw( ::com::sun::star::uno::Exception );
+
+ // Command "delete"
+ void destroy( sal_Bool bDeletePhysical )
+ throw( ::com::sun::star::uno::Exception );
+
+ // Command "lock"
+ void lock( const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& Environment )
+ throw( ::com::sun::star::uno::Exception );
+
+ // Command "unlock"
+ void unlock( const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& Environment )
+ throw( ::com::sun::star::uno::Exception );
+
+ ::com::sun::star::uno::Any MapDAVException( const DAVException & e,
+ sal_Bool bWrite );
+ void cancelCommandExecution(
+ const DAVException & e,
+ const ::com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > & xEnv,
+ sal_Bool bWrite = sal_False )
+ throw( ::com::sun::star::uno::Exception );
+
+ static bool shouldAccessNetworkAfterException( const DAVException & e );
+
+ bool supportsExclusiveWriteLock(
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& Environment );
+
+public:
+ Content( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr,
+ ContentProvider* pProvider,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XContentIdentifier >& Identifier,
+ rtl::Reference< DAVSessionFactory > const & rSessionFactory )
+ throw ( ::com::sun::star::ucb::ContentCreationException );
+ Content( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr,
+ ContentProvider* pProvider,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XContentIdentifier >& Identifier,
+ rtl::Reference< DAVSessionFactory > const & rSessionFactory,
+ sal_Bool isCollection )
+ throw ( ::com::sun::star::ucb::ContentCreationException );
+ virtual ~Content();
+
+ // XInterface
+ XINTERFACE_DECL()
+
+ // XTypeProvider
+ XTYPEPROVIDER_DECL()
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL
+ getImplementationName()
+ throw( ::com::sun::star::uno::RuntimeException );
+
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
+ getSupportedServiceNames()
+ throw( ::com::sun::star::uno::RuntimeException );
+
+ // XContent
+ virtual rtl::OUString SAL_CALL
+ getContentType()
+ throw( com::sun::star::uno::RuntimeException );
+
+ // XCommandProcessor
+ virtual com::sun::star::uno::Any SAL_CALL
+ execute( const com::sun::star::ucb::Command& aCommand,
+ sal_Int32 CommandId,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& Environment )
+ throw( com::sun::star::uno::Exception,
+ com::sun::star::ucb::CommandAbortedException,
+ com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL
+ abort( sal_Int32 CommandId )
+ throw( com::sun::star::uno::RuntimeException );
+
+ // XPropertyContainer
+ virtual void SAL_CALL
+ addProperty( const rtl::OUString& Name,
+ sal_Int16 Attributes,
+ const com::sun::star::uno::Any& DefaultValue )
+ throw( com::sun::star::beans::PropertyExistException,
+ com::sun::star::beans::IllegalTypeException,
+ com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::uno::RuntimeException );
+
+ virtual void SAL_CALL
+ removeProperty( const rtl::OUString& Name )
+ throw( com::sun::star::beans::UnknownPropertyException,
+ com::sun::star::beans::NotRemoveableException,
+ com::sun::star::uno::RuntimeException );
+
+ //////////////////////////////////////////////////////////////////////
+ // Additional interfaces
+ //////////////////////////////////////////////////////////////////////
+
+ // XContentCreator
+ virtual com::sun::star::uno::Sequence<
+ com::sun::star::ucb::ContentInfo > SAL_CALL
+ queryCreatableContentsInfo()
+ throw( com::sun::star::uno::RuntimeException );
+ virtual com::sun::star::uno::Reference<
+ com::sun::star::ucb::XContent > SAL_CALL
+ createNewContent( const com::sun::star::ucb::ContentInfo& Info )
+ throw( com::sun::star::uno::RuntimeException );
+
+ //////////////////////////////////////////////////////////////////////
+ // Non-interface methods.
+ //////////////////////////////////////////////////////////////////////
+
+ DAVResourceAccess & getResourceAccess() { return *m_xResAccess; }
+
+ // Called from resultset data supplier.
+ static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow >
+ getPropertyValues( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& rSMgr,
+ const ::com::sun::star::uno::Sequence<
+ ::com::sun::star::beans::Property >& rProperties,
+ const ContentProperties& rData,
+ const rtl::Reference<
+ ::ucbhelper::ContentProviderImplHelper >& rProvider,
+ const ::rtl::OUString& rContentId );
+};
+
+}
+
+#endif
diff --git a/ucb/source/ucp/webdav/webdavcontentcaps.cxx b/ucb/source/ucp/webdav/webdavcontentcaps.cxx
new file mode 100644
index 000000000000..145c256010f9
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavcontentcaps.cxx
@@ -0,0 +1,672 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+
+#include <set>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/ucb/CommandInfo.hpp>
+#include <com/sun/star/ucb/ContentInfo.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/InsertCommandArgument.hpp>
+#include <com/sun/star/ucb/PostCommandArgument2.hpp>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/ucb/Link.hpp>
+#include <com/sun/star/ucb/Lock.hpp>
+#include <com/sun/star/ucb/LockEntry.hpp>
+#include "webdavcontent.hxx"
+#include "webdavprovider.hxx"
+#include "DAVSession.hxx"
+#include "ContentProperties.hxx"
+
+using namespace com::sun::star;
+using namespace webdav_ucp;
+
+//=========================================================================
+//
+// ContentProvider implementation.
+//
+//=========================================================================
+
+bool ContentProvider::getProperty(
+ const rtl::OUString & rPropName, beans::Property & rProp, bool bStrict )
+{
+ if ( !m_pProps )
+ {
+ osl::MutexGuard aGuard( m_aMutex );
+ if ( !m_pProps )
+ {
+ m_pProps = new PropertyMap;
+
+ //////////////////////////////////////////////////////////////
+ // Fill map of known properties...
+ //////////////////////////////////////////////////////////////
+
+ // Mandatory UCB properties.
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ),
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ),
+ -1,
+ getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ),
+ -1,
+ getCppuBooleanType(),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND ) );
+
+ // Optional UCB properties.
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ),
+ -1,
+ getCppuType( static_cast< const util::DateTime * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ),
+ -1,
+ getCppuType( static_cast< const util::DateTime * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ),
+ -1,
+ getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ),
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "CreatableContentsInfo" ) ),
+ -1,
+ getCppuType( static_cast<
+ const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ // Standard DAV properties.
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::CREATIONDATE,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::DISPLAYNAME,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::GETCONTENTLANGUAGE,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::GETCONTENTLENGTH,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::GETCONTENTTYPE ,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::GETETAG,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::GETLASTMODIFIED,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::LOCKDISCOVERY,
+ -1,
+ getCppuType( static_cast<
+ const uno::Sequence< ucb::Lock > * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::RESOURCETYPE,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::SOURCE,
+ -1,
+ getCppuType( static_cast<
+ const uno::Sequence< ucb::Link > * >( 0 ) ),
+ beans::PropertyAttribute::BOUND ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::SUPPORTEDLOCK,
+ -1,
+ getCppuType( static_cast<
+ const uno::Sequence<
+ ucb::LockEntry > * >( 0 ) ),
+ beans::PropertyAttribute::BOUND
+ | beans::PropertyAttribute::READONLY ) );
+
+ m_pProps->insert(
+ beans::Property(
+ DAVProperties::EXECUTABLE,
+ -1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND ) );
+ }
+ }
+
+ //////////////////////////////////////////////////////////////
+ // Lookup property.
+ //////////////////////////////////////////////////////////////
+
+ beans::Property aProp;
+ aProp.Name = rPropName;
+ const PropertyMap::const_iterator it = m_pProps->find( aProp );
+ if ( it != m_pProps->end() )
+ {
+ rProp = (*it);
+ }
+ else
+ {
+ if ( bStrict )
+ return false;
+
+ // All unknown props are treated as:
+ rProp = beans::Property(
+ rPropName,
+ - 1,
+ getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
+ beans::PropertyAttribute::BOUND );
+ }
+
+ return true;
+}
+
+//=========================================================================
+//
+// Content implementation.
+//
+//=========================================================================
+
+// virtual
+uno::Sequence< beans::Property > Content::getProperties(
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+ sal_Bool bTransient;
+ std::auto_ptr< DAVResourceAccess > xResAccess;
+ std::auto_ptr< ContentProperties > xCachedProps;
+ rtl::Reference< ContentProvider > xProvider;
+
+ {
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ bTransient = m_bTransient;
+ xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
+ if ( m_xCachedProps.get() )
+ xCachedProps.reset(
+ new ContentProperties( *m_xCachedProps.get() ) );
+ xProvider.set( m_pProvider );
+ }
+
+ typedef std::set< rtl::OUString > StringSet;
+ StringSet aPropSet;
+
+ // No server access for just created (not yet committed) objects.
+ // Only a minimal set of properties supported at this stage.
+ if ( !bTransient )
+ {
+ // Obtain all properties supported for this resource from server.
+ try
+ {
+ std::vector< DAVResourceInfo > props;
+ xResAccess->PROPFIND( DAVZERO, props, xEnv );
+
+ // Note: vector always contains exactly one resource info, because
+ // we used a depth of DAVZERO for PROPFIND.
+ aPropSet.insert( (*props.begin()).properties.begin(),
+ (*props.begin()).properties.end() );
+ }
+ catch ( DAVException const & )
+ {
+ }
+ }
+
+ // Add DAV properties, map DAV properties to UCB properties.
+ sal_Bool bHasCreationDate = sal_False; // creationdate <-> DateCreated
+ sal_Bool bHasGetLastModified = sal_False; // getlastmodified <-> DateModified
+ sal_Bool bHasGetContentType = sal_False; // getcontenttype <-> MediaType
+ sal_Bool bHasGetContentLength = sal_False; // getcontentlength <-> Size
+
+ sal_Bool bHasContentType = sal_False;
+ sal_Bool bHasIsDocument = sal_False;
+ sal_Bool bHasIsFolder = sal_False;
+ sal_Bool bHasTitle = sal_False;
+ sal_Bool bHasBaseURI = sal_False;
+ sal_Bool bHasDateCreated = sal_False;
+ sal_Bool bHasDateModified = sal_False;
+ sal_Bool bHasMediaType = sal_False;
+ sal_Bool bHasSize = sal_False;
+ sal_Bool bHasCreatableInfos = sal_False;
+
+ {
+ std::set< rtl::OUString >::const_iterator it = aPropSet.begin();
+ std::set< rtl::OUString >::const_iterator end = aPropSet.end();
+ while ( it != end )
+ {
+ if ( !bHasCreationDate &&
+ ( (*it) == DAVProperties::CREATIONDATE ) )
+ {
+ bHasCreationDate = sal_True;
+ }
+ else if ( !bHasGetLastModified &&
+ ( (*it) == DAVProperties::GETLASTMODIFIED ) )
+ {
+ bHasGetLastModified = sal_True;
+ }
+ else if ( !bHasGetContentType &&
+ ( (*it) == DAVProperties::GETCONTENTTYPE ) )
+ {
+ bHasGetContentType = sal_True;
+ }
+ else if ( !bHasGetContentLength &&
+ ( (*it) == DAVProperties::GETCONTENTLENGTH ) )
+ {
+ bHasGetContentLength = sal_True;
+ }
+ else if ( !bHasContentType &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
+ {
+ bHasContentType = sal_True;
+ }
+ else if ( !bHasIsDocument &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
+ {
+ bHasIsDocument = sal_True;
+ }
+ else if ( !bHasIsFolder &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
+ {
+ bHasIsFolder = sal_True;
+ }
+ else if ( !bHasTitle &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
+ {
+ bHasTitle = sal_True;
+ }
+ else if ( !bHasBaseURI &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "BaseURI" ) ) )
+ {
+ bHasBaseURI = sal_True;
+ }
+ else if ( !bHasDateCreated &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) )
+ {
+ bHasDateCreated = sal_True;
+ }
+ else if ( !bHasDateModified &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
+ {
+ bHasDateModified = sal_True;
+ }
+ else if ( !bHasMediaType &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
+ {
+ bHasMediaType = sal_True;
+ }
+ else if ( !bHasSize &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
+ {
+ bHasSize = sal_True;
+ }
+ else if ( !bHasCreatableInfos &&
+ (*it).equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM(
+ "CreatableContentsInfo" ) ) )
+ {
+ bHasCreatableInfos = sal_True;
+ }
+ it++;
+ }
+ }
+
+ // Add mandatory properties.
+ if ( !bHasContentType )
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ) );
+
+ if ( !bHasIsDocument )
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ) );
+
+ if ( !bHasIsFolder )
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ) );
+
+ if ( !bHasTitle )
+ {
+ // Always present since it can be calculated from content's URI.
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ) );
+ }
+
+ // Add optional properties.
+
+ if ( !bHasBaseURI )
+ {
+ // Always present since it can be calculated from content's URI.
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ) );
+ }
+
+ if ( !bHasDateCreated && bHasCreationDate )
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ) );
+
+ if ( !bHasDateModified && bHasGetLastModified )
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ) );
+
+ if ( !bHasMediaType && bHasGetContentType )
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ) );
+
+ if ( !bHasSize && bHasGetContentLength )
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ) );
+
+ if ( !bHasCreatableInfos )
+ aPropSet.insert(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "CreatableContentsInfo" ) ) );
+
+ // Add cached properties, if present and still missing.
+ if ( xCachedProps.get() )
+ {
+ const std::set< rtl::OUString >::const_iterator set_end
+ = aPropSet.end();
+
+ const std::auto_ptr< PropertyValueMap > & xProps
+ = xCachedProps->getProperties();
+
+ PropertyValueMap::const_iterator map_it = xProps->begin();
+ const PropertyValueMap::const_iterator map_end = xProps->end();
+
+ while ( map_it != map_end )
+ {
+ if ( aPropSet.find( (*map_it).first ) == set_end )
+ aPropSet.insert( (*map_it).first );
+
+ ++map_it;
+ }
+ }
+
+ // std::set -> uno::Sequence
+ sal_Int32 nCount = aPropSet.size();
+ uno::Sequence< beans::Property > aProperties( nCount );
+
+ std::set< rtl::OUString >::const_iterator it = aPropSet.begin();
+ beans::Property aProp;
+
+ for ( sal_Int32 n = 0; n < nCount; ++n, ++it )
+ {
+ xProvider->getProperty( (*it), aProp );
+ aProperties[ n ] = aProp;
+ }
+
+ return aProperties;
+}
+
+//=========================================================================
+// virtual
+uno::Sequence< ucb::CommandInfo > Content::getCommands(
+ const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+ osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+ uno::Sequence< ucb::CommandInfo > aCmdInfo( 8 );
+
+ ///////////////////////////////////////////////////////////////
+ // Mandatory commands
+ ///////////////////////////////////////////////////////////////
+
+ aCmdInfo[ 0 ] =
+ ucb::CommandInfo(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ),
+ -1,
+ getCppuVoidType() );
+ aCmdInfo[ 1 ] =
+ ucb::CommandInfo(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ),
+ -1,
+ getCppuVoidType() );
+ aCmdInfo[ 2 ] =
+ ucb::CommandInfo(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ),
+ -1,
+ getCppuType( static_cast<
+ uno::Sequence< beans::Property > * >( 0 ) ) );
+ aCmdInfo[ 3 ] =
+ ucb::CommandInfo(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
+ -1,
+ getCppuType( static_cast<
+ uno::Sequence< beans::PropertyValue > * >( 0 ) ) );
+
+ ///////////////////////////////////////////////////////////////
+ // Optional standard commands
+ ///////////////////////////////////////////////////////////////
+
+ aCmdInfo[ 4 ] =
+ ucb::CommandInfo(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ),
+ -1,
+ getCppuBooleanType() );
+ aCmdInfo[ 5 ] =
+ ucb::CommandInfo(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
+ -1,
+ getCppuType( static_cast<
+ ucb::InsertCommandArgument * >( 0 ) ) );
+ aCmdInfo[ 6 ] =
+ ucb::CommandInfo(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ),
+ -1,
+ getCppuType( static_cast<
+ ucb::OpenCommandArgument2 * >( 0 ) ) );
+
+ ///////////////////////////////////////////////////////////////
+ // New commands
+ ///////////////////////////////////////////////////////////////
+
+ aCmdInfo[ 7 ] =
+ ucb::CommandInfo(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "post" ) ),
+ -1,
+ getCppuType( static_cast<
+ ucb::PostCommandArgument2 * >( 0 ) ) );
+
+ sal_Bool bFolder = sal_False;
+
+ try
+ {
+ bFolder = isFolder( xEnv );
+ }
+ catch ( uno::Exception const & )
+ {
+ return aCmdInfo;
+ }
+
+ sal_Bool bSupportsLocking = supportsExclusiveWriteLock( xEnv );
+
+ sal_Int32 nPos = aCmdInfo.getLength();
+ sal_Int32 nMoreCmds = ( bFolder ? 2 : 0 ) + ( bSupportsLocking ? 2 : 0 );
+ if ( nMoreCmds )
+ aCmdInfo.realloc( nPos + nMoreCmds );
+ else
+ return aCmdInfo;
+
+ if ( bFolder )
+ {
+ ///////////////////////////////////////////////////////////////
+ // Optional standard commands
+ ///////////////////////////////////////////////////////////////
+
+ aCmdInfo[ nPos ] =
+ ucb::CommandInfo(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ),
+ -1,
+ getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) );
+ nPos++;
+ aCmdInfo[ nPos ] =
+ ucb::CommandInfo(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "createNewContent" ) ),
+ -1,
+ getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) );
+ nPos++;
+ }
+ else
+ {
+ // no document-only commands at the moment.
+ }
+
+ if ( bSupportsLocking )
+ {
+ aCmdInfo[ nPos ] =
+ ucb::CommandInfo(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "lock" ) ),
+ -1,
+ getCppuVoidType() );
+ nPos++;
+ aCmdInfo[ nPos ] =
+ ucb::CommandInfo(
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unlock" ) ),
+ -1,
+ getCppuVoidType() );
+ nPos++;
+ }
+ return aCmdInfo;
+}
diff --git a/ucb/source/ucp/webdav/webdavdatasupplier.cxx b/ucb/source/ucp/webdav/webdavdatasupplier.cxx
new file mode 100644
index 000000000000..8d2683939f0d
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavdatasupplier.cxx
@@ -0,0 +1,512 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+#include <osl/diagnose.h>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <ucbhelper/contentidentifier.hxx>
+#include <ucbhelper/providerhelper.hxx>
+#include "webdavdatasupplier.hxx"
+#include "webdavcontent.hxx"
+#include "ContentProperties.hxx"
+#ifndef _WEBDAV_SESSION_HXX
+#include "DAVSession.hxx"
+#endif
+#include "NeonUri.hxx"
+
+using namespace com::sun::star;
+using namespace webdav_ucp;
+
+namespace webdav_ucp
+{
+
+//=========================================================================
+//
+// struct ResultListEntry.
+//
+//=========================================================================
+
+struct ResultListEntry
+{
+ rtl::OUString aId;
+ uno::Reference< ucb::XContentIdentifier > xId;
+ uno::Reference< ucb::XContent > xContent;
+ uno::Reference< sdbc::XRow > xRow;
+ const ContentProperties* pData;
+
+ ResultListEntry( const ContentProperties* pEntry ) : pData( pEntry ) {};
+ ~ResultListEntry() { delete pData; }
+};
+
+//=========================================================================
+//
+// ResultList.
+//
+//=========================================================================
+
+typedef std::vector< ResultListEntry* > ResultList;
+
+//=========================================================================
+//
+// struct DataSupplier_Impl.
+//
+//=========================================================================
+
+struct DataSupplier_Impl
+{
+ osl::Mutex m_aMutex;
+ ResultList m_aResults;
+ rtl::Reference< Content > m_xContent;
+ uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
+ sal_Int32 m_nOpenMode;
+ sal_Bool m_bCountFinal;
+ sal_Bool m_bThrowException;
+
+ DataSupplier_Impl(
+ const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
+ const rtl::Reference< Content >& rContent,
+ sal_Int32 nOpenMode )
+ : m_xContent( rContent ), m_xSMgr( rxSMgr ), m_nOpenMode( nOpenMode ),
+ m_bCountFinal( sal_False ), m_bThrowException( sal_False ) {}
+ ~DataSupplier_Impl();
+};
+
+//=========================================================================
+DataSupplier_Impl::~DataSupplier_Impl()
+{
+ ResultList::const_iterator it = m_aResults.begin();
+ ResultList::const_iterator end = m_aResults.end();
+
+ while ( it != end )
+ {
+ delete (*it);
+ it++;
+ }
+}
+
+}
+
+//=========================================================================
+//=========================================================================
+//
+// DataSupplier Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+DataSupplier::DataSupplier(
+ const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
+ const rtl::Reference< Content >& rContent,
+ sal_Int32 nOpenMode )
+: m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) )
+{
+}
+
+//=========================================================================
+// virtual
+DataSupplier::~DataSupplier()
+{
+ delete m_pImpl;
+}
+
+//=========================================================================
+// virtual
+rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( nIndex < m_pImpl->m_aResults.size() )
+ {
+ rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
+ if ( aId.getLength() )
+ {
+ // Already cached.
+ return aId;
+ }
+ }
+
+ if ( getResult( nIndex ) )
+ {
+ rtl::OUString aId = m_pImpl->m_xContent->getResourceAccess().getURL();
+
+ const ContentProperties& props
+ = *( m_pImpl->m_aResults[ nIndex ]->pData );
+
+ if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
+ aId += rtl::OUString::createFromAscii( "/" );
+
+ aId += props.getEscapedTitle();
+
+ if ( props.isTrailingSlash() )
+ aId += rtl::OUString::createFromAscii( "/" );
+
+ m_pImpl->m_aResults[ nIndex ]->aId = aId;
+ return aId;
+ }
+ return rtl::OUString();
+}
+
+//=========================================================================
+// virtual
+uno::Reference< ucb::XContentIdentifier >
+DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( nIndex < m_pImpl->m_aResults.size() )
+ {
+ uno::Reference< ucb::XContentIdentifier > xId
+ = m_pImpl->m_aResults[ nIndex ]->xId;
+ if ( xId.is() )
+ {
+ // Already cached.
+ return xId;
+ }
+ }
+
+ rtl::OUString aId = queryContentIdentifierString( nIndex );
+ if ( aId.getLength() )
+ {
+ uno::Reference< ucb::XContentIdentifier > xId
+ = new ::ucbhelper::ContentIdentifier( aId );
+ m_pImpl->m_aResults[ nIndex ]->xId = xId;
+ return xId;
+ }
+ return uno::Reference< ucb::XContentIdentifier >();
+}
+
+//=========================================================================
+// virtual
+uno::Reference< ucb::XContent >
+DataSupplier::queryContent( sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( nIndex < m_pImpl->m_aResults.size() )
+ {
+ uno::Reference< ucb::XContent > xContent
+ = m_pImpl->m_aResults[ nIndex ]->xContent;
+ if ( xContent.is() )
+ {
+ // Already cached.
+ return xContent;
+ }
+ }
+
+ uno::Reference< ucb::XContentIdentifier > xId
+ = queryContentIdentifier( nIndex );
+ if ( xId.is() )
+ {
+ try
+ {
+ uno::Reference< ucb::XContent > xContent
+ = m_pImpl->m_xContent->getProvider()->queryContent( xId );
+ m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
+ return xContent;
+
+ }
+ catch ( ucb::IllegalIdentifierException& )
+ {
+ }
+ }
+ return uno::Reference< ucb::XContent >();
+}
+
+//=========================================================================
+// virtual
+sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( m_pImpl->m_aResults.size() > nIndex )
+ {
+ // Result already present.
+ return sal_True;
+ }
+
+ // Obtain values...
+ if ( getData() )
+ {
+ if ( m_pImpl->m_aResults.size() > nIndex )
+ {
+ // Result already present.
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+//=========================================================================
+// virtual
+sal_uInt32 DataSupplier::totalCount()
+{
+ // Obtain values...
+ getData();
+
+ return m_pImpl->m_aResults.size();
+}
+
+//=========================================================================
+// virtual
+sal_uInt32 DataSupplier::currentCount()
+{
+ return m_pImpl->m_aResults.size();
+}
+
+//=========================================================================
+// virtual
+sal_Bool DataSupplier::isCountFinal()
+{
+ return m_pImpl->m_bCountFinal;
+}
+
+//=========================================================================
+// virtual
+uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
+ sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( nIndex < m_pImpl->m_aResults.size() )
+ {
+ uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
+ if ( xRow.is() )
+ {
+ // Already cached.
+ return xRow;
+ }
+ }
+
+ if ( getResult( nIndex ) )
+ {
+ uno::Reference< sdbc::XRow > xRow
+ = Content::getPropertyValues(
+ m_pImpl->m_xSMgr,
+ getResultSet()->getProperties(),
+ *(m_pImpl->m_aResults[ nIndex ]->pData),
+ rtl::Reference< ::ucbhelper::ContentProviderImplHelper >(
+ m_pImpl->m_xContent->getProvider().get() ),
+ queryContentIdentifierString( nIndex ) );
+ m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
+ return xRow;
+ }
+
+ return uno::Reference< sdbc::XRow >();
+}
+
+//=========================================================================
+// virtual
+void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
+{
+ osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( nIndex < m_pImpl->m_aResults.size() )
+ m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
+}
+
+//=========================================================================
+// virtual
+void DataSupplier::close()
+{
+}
+
+//=========================================================================
+// virtual
+void DataSupplier::validate()
+ throw( ucb::ResultSetException )
+{
+ if ( m_pImpl->m_bThrowException )
+ throw ucb::ResultSetException();
+}
+
+//=========================================================================
+sal_Bool DataSupplier::getData()
+{
+ osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
+
+ if ( !m_pImpl->m_bCountFinal )
+ {
+ std::vector< rtl::OUString > propertyNames;
+ ContentProperties::UCBNamesToDAVNames(
+ getResultSet()->getProperties(), propertyNames );
+
+ // Append "resourcetype", if not already present. It's value is
+ // needed to get a valid ContentProperties::pIsFolder value, which
+ // is needed for OpenMode handling.
+
+ std::vector< rtl::OUString >::const_iterator it
+ = propertyNames.begin();
+ std::vector< rtl::OUString >::const_iterator end
+ = propertyNames.end();
+
+ while ( it != end )
+ {
+ if ( (*it).equals( DAVProperties::RESOURCETYPE ) )
+ break;
+
+ it++;
+ }
+
+ if ( it == end )
+ propertyNames.push_back( DAVProperties::RESOURCETYPE );
+
+ std::vector< DAVResource > resources;
+ try
+ {
+ // propfind depth 1, get property values for parent AND for each
+ // child
+ m_pImpl->m_xContent->getResourceAccess()
+ .PROPFIND( DAVONE,
+ propertyNames,
+ resources,
+ getResultSet()->getEnvironment() );
+ }
+ catch ( DAVException & )
+ {
+// OSL_ENSURE( sal_False, "PROPFIND : DAVException" );
+ m_pImpl->m_bThrowException = sal_True;
+ }
+
+ if ( !m_pImpl->m_bThrowException )
+ {
+ try
+ {
+ NeonUri aURI(
+ m_pImpl->m_xContent->getResourceAccess().getURL() );
+ rtl::OUString aPath = aURI.GetPath();
+
+ if ( aPath.getStr()[ aPath.getLength() - 1 ]
+ == sal_Unicode( '/' ) )
+ aPath = aPath.copy( 0, aPath.getLength() - 1 );
+
+ aPath = NeonUri::unescape( aPath );
+ bool bFoundParent = false;
+
+ for ( sal_uInt32 n = 0; n < resources.size(); ++n )
+ {
+ const DAVResource & rRes = resources[ n ];
+
+ // Filter parent, which is contained somewhere(!) in
+ // the vector.
+ if ( !bFoundParent )
+ {
+ try
+ {
+ NeonUri aCurrURI( rRes.uri );
+ rtl::OUString aCurrPath = aCurrURI.GetPath();
+ if ( aCurrPath.getStr()[
+ aCurrPath.getLength() - 1 ]
+ == sal_Unicode( '/' ) )
+ aCurrPath
+ = aCurrPath.copy(
+ 0,
+ aCurrPath.getLength() - 1 );
+
+ aCurrPath = NeonUri::unescape( aCurrPath );
+ if ( aPath == aCurrPath )
+ {
+ bFoundParent = true;
+ continue;
+ }
+ }
+ catch ( DAVException const & )
+ {
+ // do nothing, ignore error. continue.
+ }
+ }
+
+ ContentProperties* pContentProperties
+ = new ContentProperties( rRes );
+
+ // Check resource against open mode.
+ switch ( m_pImpl->m_nOpenMode )
+ {
+ case ucb::OpenMode::FOLDERS:
+ {
+ sal_Bool bFolder = sal_False;
+
+ const uno::Any & rValue
+ = pContentProperties->getValue(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "IsFolder" ) ) );
+ rValue >>= bFolder;
+
+ if ( !bFolder )
+ continue;
+
+ break;
+ }
+
+ case ucb::OpenMode::DOCUMENTS:
+ {
+ sal_Bool bDocument = sal_False;
+
+ const uno::Any & rValue
+ = pContentProperties->getValue(
+ rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "IsDocument" ) ) );
+ rValue >>= bDocument;
+
+ if ( !bDocument )
+ continue;
+
+ break;
+ }
+
+ case ucb::OpenMode::ALL:
+ default:
+ break;
+ }
+
+ m_pImpl->m_aResults.push_back(
+ new ResultListEntry( pContentProperties ) );
+ }
+ }
+ catch ( DAVException const & )
+ {
+ }
+ }
+
+ m_pImpl->m_bCountFinal = sal_True;
+
+ // Callback possible, because listeners may be informed!
+ aGuard.clear();
+ getResultSet()->rowCountFinal();
+ }
+ return !m_pImpl->m_bThrowException;
+}
+
diff --git a/ucb/source/ucp/webdav/webdavdatasupplier.hxx b/ucb/source/ucp/webdav/webdavdatasupplier.hxx
new file mode 100644
index 000000000000..b28263df0201
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavdatasupplier.hxx
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WEBDAV_UCP_DATASUPPLIER_HXX
+#define _WEBDAV_UCP_DATASUPPLIER_HXX
+
+#include <vector>
+#include <rtl/ref.hxx>
+#include <ucbhelper/resultset.hxx>
+
+namespace webdav_ucp {
+
+struct DataSupplier_Impl;
+class Content;
+struct DAVResource;
+class ContentProperties;
+
+class DataSupplier : public ucbhelper::ResultSetDataSupplier
+{
+ DataSupplier_Impl* m_pImpl;
+
+private:
+ sal_Bool getData();
+
+public:
+ DataSupplier( const com::sun::star::uno::Reference<
+ com::sun::star::lang::XMultiServiceFactory >& rxSMgr,
+ const rtl::Reference< Content >& rContent,
+ sal_Int32 nOpenMode);
+
+ virtual ~DataSupplier();
+
+ virtual rtl::OUString queryContentIdentifierString( sal_uInt32 nIndex );
+ virtual com::sun::star::uno::Reference<
+ com::sun::star::ucb::XContentIdentifier >
+ queryContentIdentifier( sal_uInt32 nIndex );
+ virtual com::sun::star::uno::Reference< com::sun::star::ucb::XContent >
+ queryContent( sal_uInt32 nIndex );
+
+ virtual sal_Bool getResult( sal_uInt32 nIndex );
+
+ virtual sal_uInt32 totalCount();
+ virtual sal_uInt32 currentCount();
+ virtual sal_Bool isCountFinal();
+
+ virtual com::sun::star::uno::Reference< com::sun::star::sdbc::XRow >
+ queryPropertyValues( sal_uInt32 nIndex );
+ virtual void releasePropertyValues( sal_uInt32 nIndex );
+
+ virtual void close();
+
+ virtual void validate()
+ throw( com::sun::star::ucb::ResultSetException );
+};
+
+}
+
+#endif
diff --git a/ucb/source/ucp/webdav/webdavprovider.cxx b/ucb/source/ucp/webdav/webdavprovider.cxx
new file mode 100644
index 000000000000..cc9c69a15e25
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavprovider.cxx
@@ -0,0 +1,232 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ *************************************************************************/
+#include <ucbhelper/contentidentifier.hxx>
+#include "webdavprovider.hxx"
+#include "webdavcontent.hxx"
+
+#include "osl/mutex.hxx"
+
+using namespace com::sun::star;
+using namespace webdav_ucp;
+
+//=========================================================================
+//=========================================================================
+//
+// ContentProvider Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+ContentProvider::ContentProvider(
+ const uno::Reference< lang::XMultiServiceFactory >& rSMgr )
+: ::ucbhelper::ContentProviderImplHelper( rSMgr ),
+ m_xDAVSessionFactory( new DAVSessionFactory() ),
+ m_pProps( 0 )
+{
+}
+
+//=========================================================================
+// virtual
+ContentProvider::~ContentProvider()
+{
+ delete m_pProps;
+}
+
+//=========================================================================
+//
+// XInterface methods.
+//
+//=========================================================================
+
+XINTERFACE_IMPL_3( ContentProvider,
+ lang::XTypeProvider,
+ lang::XServiceInfo,
+ ucb::XContentProvider );
+
+//=========================================================================
+//
+// XTypeProvider methods.
+//
+//=========================================================================
+
+XTYPEPROVIDER_IMPL_3( ContentProvider,
+ lang::XTypeProvider,
+ lang::XServiceInfo,
+ ucb::XContentProvider );
+
+//=========================================================================
+//
+// XServiceInfo methods.
+//
+//=========================================================================
+
+XSERVICEINFO_IMPL_1( ContentProvider,
+ rtl::OUString::createFromAscii(
+ "com.sun.star.comp.WebDAVContentProvider" ),
+ rtl::OUString::createFromAscii(
+ WEBDAV_CONTENT_PROVIDER_SERVICE_NAME ) );
+
+//=========================================================================
+//
+// Service factory implementation.
+//
+//=========================================================================
+
+ONE_INSTANCE_SERVICE_FACTORY_IMPL( ContentProvider );
+
+//=========================================================================
+//
+// XContentProvider methods.
+//
+//=========================================================================
+
+// virtual
+uno::Reference< ucb::XContent > SAL_CALL
+ContentProvider::queryContent(
+ const uno::Reference<
+ ucb::XContentIdentifier >& Identifier )
+ throw( ucb::IllegalIdentifierException,
+ uno::RuntimeException )
+{
+ // Check URL scheme...
+
+ const rtl::OUString aScheme
+ = Identifier->getContentProviderScheme().toAsciiLowerCase();
+ if ( !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( HTTP_URL_SCHEME ) ) &&
+ !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( HTTPS_URL_SCHEME ) ) &&
+ !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) &&
+ !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( DAV_URL_SCHEME ) ) &&
+ !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( DAVS_URL_SCHEME ) ) &&
+ !aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( FTP_URL_SCHEME ) ) )
+ throw ucb::IllegalIdentifierException();
+
+ // Normalize URL and create new Id, if nessacary.
+ rtl::OUString aURL = Identifier->getContentIdentifier();
+
+ // At least: <scheme> + "://"
+ if ( aURL.getLength() < ( aScheme.getLength() + 3 ) )
+ throw ucb::IllegalIdentifierException();
+
+ if ( ( aURL.getStr()[ aScheme.getLength() ] != sal_Unicode( ':' ) ) ||
+ ( aURL.getStr()[ aScheme.getLength() + 1 ] != sal_Unicode( '/' ) ) ||
+ ( aURL.getStr()[ aScheme.getLength() + 2 ] != sal_Unicode( '/' ) ) )
+ throw ucb::IllegalIdentifierException();
+
+ uno::Reference< ucb::XContentIdentifier > xCanonicId;
+
+ bool bNewId = false;
+ if ( aScheme.equalsAsciiL(
+ RTL_CONSTASCII_STRINGPARAM( WEBDAV_URL_SCHEME ) ) )
+ {
+ 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;
+ }
+
+ sal_Int32 nPos = aURL.lastIndexOf( '/' );
+ if ( nPos != aURL.getLength() - 1 )
+ {
+ // Find second slash in URL.
+ nPos = aURL.indexOf( '/', aURL.indexOf( '/' ) + 1 );
+ if ( nPos == -1 )
+ throw ucb::IllegalIdentifierException();
+
+ nPos = aURL.indexOf( '/', nPos + 1 );
+ if ( nPos == -1 )
+ {
+ aURL += rtl::OUString::createFromAscii( "/" );
+ bNewId = true;
+ }
+ }
+
+ if ( bNewId )
+ xCanonicId = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL );
+ else
+ xCanonicId = Identifier;
+
+ osl::MutexGuard aGuard( m_aMutex );
+
+ // Check, if a content with given id already exists...
+ uno::Reference< ucb::XContent > xContent
+ = queryExistingContent( xCanonicId ).get();
+ if ( xContent.is() )
+ return xContent;
+
+ // Create a new content.
+
+ try
+ {
+ xContent = new ::webdav_ucp::Content(
+ m_xSMgr, this, xCanonicId, m_xDAVSessionFactory );
+ registerNewContent( xContent );
+ }
+ catch ( ucb::ContentCreationException const & )
+ {
+ throw ucb::IllegalIdentifierException();
+ }
+
+ if ( !xContent->getIdentifier().is() )
+ throw ucb::IllegalIdentifierException();
+
+ return xContent;
+}
+
diff --git a/ucb/source/ucp/webdav/webdavprovider.hxx b/ucb/source/ucp/webdav/webdavprovider.hxx
new file mode 100644
index 000000000000..286f2e474c16
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavprovider.hxx
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WEBDAV_UCP_PROVIDER_HXX
+#define _WEBDAV_UCP_PROVIDER_HXX
+
+#include <rtl/ref.hxx>
+#include <com/sun/star/beans/Property.hpp>
+#include "DAVSessionFactory.hxx"
+#include <ucbhelper/providerhelper.hxx>
+#include "PropertyMap.hxx"
+
+namespace webdav_ucp {
+
+//=========================================================================
+
+// UNO service name for the provider. This name will be used by the UCB to
+// create instances of the provider.
+#define WEBDAV_CONTENT_PROVIDER_SERVICE_NAME \
+ "com.sun.star.ucb.WebDAVContentProvider"
+#define WEBDAV_CONTENT_PROVIDER_SERVICE_NAME_LENGTH 38
+
+// URL scheme. This is the scheme the provider will be able to create
+// contents for. The UCB will select the provider ( i.e. in order to create
+// 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
+
+#define DAVS_URL_SCHEME "davs"
+#define DAVS_URL_SCHEME_LENGTH 4
+
+
+
+#define FTP_URL_SCHEME "ftp"
+
+#define HTTP_CONTENT_TYPE \
+ "application/" HTTP_URL_SCHEME "-content"
+
+#define WEBDAV_CONTENT_TYPE HTTP_CONTENT_TYPE
+#define WEBDAV_COLLECTION_TYPE \
+ "application/" WEBDAV_URL_SCHEME "-collection"
+
+//=========================================================================
+
+class ContentProvider : public ::ucbhelper::ContentProviderImplHelper
+{
+ rtl::Reference< DAVSessionFactory > m_xDAVSessionFactory;
+ PropertyMap * m_pProps;
+
+public:
+ ContentProvider( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& rSMgr );
+ virtual ~ContentProvider();
+
+ // XInterface
+ XINTERFACE_DECL()
+
+ // XTypeProvider
+ XTYPEPROVIDER_DECL()
+
+ // XServiceInfo
+ XSERVICEINFO_DECL()
+
+ // XContentProvider
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XContent > SAL_CALL
+ queryContent( const ::com::sun::star::uno::Reference<
+ ::com::sun::star::ucb::XContentIdentifier >& Identifier )
+ throw( ::com::sun::star::ucb::IllegalIdentifierException,
+ ::com::sun::star::uno::RuntimeException );
+
+ //////////////////////////////////////////////////////////////////////
+ // Additional interfaces
+ //////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////
+ // Non-interface methods.
+ //////////////////////////////////////////////////////////////////////
+
+ rtl::Reference< DAVSessionFactory > getDAVSessionFactory()
+ { return m_xDAVSessionFactory; }
+
+ bool getProperty( const ::rtl::OUString & rPropName,
+ ::com::sun::star::beans::Property & rProp,
+ bool bStrict = false );
+};
+
+}
+
+#endif
diff --git a/ucb/source/ucp/webdav/webdavresultset.cxx b/ucb/source/ucp/webdav/webdavresultset.cxx
new file mode 100644
index 000000000000..cf4cc88fd12f
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavresultset.cxx
@@ -0,0 +1,95 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+
+/**************************************************************************
+ TODO
+ **************************************************************************
+
+ - This implementation is not a dynamic result set!!! It only implements
+ the necessary interfaces, but never recognizes/notifies changes!!!
+
+ *************************************************************************/
+#include "webdavresultset.hxx"
+#ifndef _WEBDAV_SESSION_HXX
+#include "DAVSession.hxx"
+#endif
+
+using namespace com::sun::star;
+using namespace webdav_ucp;
+
+//=========================================================================
+//=========================================================================
+//
+// DynamicResultSet Implementation.
+//
+//=========================================================================
+//=========================================================================
+
+DynamicResultSet::DynamicResultSet(
+ const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
+ const rtl::Reference< Content >& rxContent,
+ const ucb::OpenCommandArgument2& rCommand,
+ const uno::Reference< ucb::XCommandEnvironment >& rxEnv )
+: ResultSetImplHelper( rxSMgr, rCommand ),
+ m_xContent( rxContent ),
+ m_xEnv( rxEnv )
+{
+}
+
+//=========================================================================
+//
+// Non-interface methods.
+//
+//=========================================================================
+
+void DynamicResultSet::initStatic()
+{
+ m_xResultSet1
+ = new ::ucbhelper::ResultSet( m_xSMgr,
+ m_aCommand.Properties,
+ new DataSupplier( m_xSMgr,
+ m_xContent,
+ m_aCommand.Mode ),
+ m_xEnv );
+}
+
+//=========================================================================
+void DynamicResultSet::initDynamic()
+{
+ m_xResultSet1
+ = new ::ucbhelper::ResultSet( m_xSMgr,
+ m_aCommand.Properties,
+ new DataSupplier( m_xSMgr,
+ m_xContent,
+ m_aCommand.Mode ),
+ m_xEnv );
+ m_xResultSet2 = m_xResultSet1;
+}
+
diff --git a/ucb/source/ucp/webdav/webdavresultset.hxx b/ucb/source/ucp/webdav/webdavresultset.hxx
new file mode 100644
index 000000000000..a438cc208e09
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavresultset.hxx
@@ -0,0 +1,59 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WEBDAV_UCP_RESULTSET_HXX
+#define _WEBDAV_UCP_RESULTSET_HXX
+
+#include <rtl/ref.hxx>
+#include <ucbhelper/resultsethelper.hxx>
+#include "webdavcontent.hxx"
+#include "webdavdatasupplier.hxx"
+
+namespace webdav_ucp {
+
+class DynamicResultSet : public ::ucbhelper::ResultSetImplHelper
+{
+ rtl::Reference< Content > m_xContent;
+ com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment > m_xEnv;
+
+private:
+ virtual void initStatic();
+ virtual void initDynamic();
+
+public:
+ DynamicResultSet( const com::sun::star::uno::Reference<
+ com::sun::star::lang::XMultiServiceFactory >& rxSMgr,
+ const rtl::Reference< Content >& rxContent,
+ const com::sun::star::ucb::OpenCommandArgument2& rCommand,
+ const com::sun::star::uno::Reference<
+ com::sun::star::ucb::XCommandEnvironment >& rxEnv );
+};
+
+}
+
+#endif
diff --git a/ucb/source/ucp/webdav/webdavservices.cxx b/ucb/source/ucp/webdav/webdavservices.cxx
new file mode 100644
index 000000000000..7a38636e9dc7
--- /dev/null
+++ b/ucb/source/ucp/webdav/webdavservices.cxx
@@ -0,0 +1,76 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_ucb.hxx"
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/registry/XRegistryKey.hpp>
+#include "webdavprovider.hxx"
+
+using namespace com::sun::star;
+
+//=========================================================================
+extern "C" void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+//=========================================================================
+extern "C" void * SAL_CALL component_getFactory(
+ const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
+{
+ void * pRet = 0;
+
+ uno::Reference< lang::XMultiServiceFactory > xSMgr(
+ reinterpret_cast< lang::XMultiServiceFactory * >(
+ pServiceManager ) );
+ uno::Reference< lang::XSingleServiceFactory > xFactory;
+
+ //////////////////////////////////////////////////////////////////////
+ // WebDAV Content Provider.
+ //////////////////////////////////////////////////////////////////////
+
+ if ( ::webdav_ucp::ContentProvider::getImplementationName_Static().
+ compareToAscii( pImplName ) == 0 )
+ {
+ xFactory = ::webdav_ucp::ContentProvider::createServiceFactory( xSMgr );
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ if ( xFactory.is() )
+ {
+ xFactory->acquire();
+ pRet = xFactory.get();
+ }
+
+ return pRet;
+}
+
+