solenv/clang-format/excludelist                      |   30 
 ucb/Library_ucpdav1.mk                               |   25 
 ucb/source/ucp/webdav-curl/ContentProperties.cxx     |  593 +++
 ucb/source/ucp/webdav-curl/ContentProperties.hxx     |  181 +
 ucb/source/ucp/webdav-curl/DAVAuthListener.hxx       |   43 
 ucb/source/ucp/webdav-curl/DAVAuthListenerImpl.hxx   |   61 
 ucb/source/ucp/webdav-curl/DAVException.hxx          |  165 
 ucb/source/ucp/webdav-curl/DAVProperties.cxx         |  222 +
 ucb/source/ucp/webdav-curl/DAVProperties.hxx         |   57 
 ucb/source/ucp/webdav-curl/DAVRequestEnvironment.hxx |   54 
 ucb/source/ucp/webdav-curl/DAVResource.hxx           |   59 
 ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx     | 1116 ++++++
 ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx     |  207 +
 ucb/source/ucp/webdav-curl/DAVSession.hxx            |  202 +
 ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx     |   86 
 ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx     |   68 
 ucb/source/ucp/webdav-curl/DAVTypes.hxx              |   77 
 ucb/source/ucp/webdav-curl/DateTimeHelper.cxx        |  258 +
 ucb/source/ucp/webdav-curl/DateTimeHelper.hxx        |   55 
 ucb/source/ucp/webdav-curl/PropertyMap.hxx           |   55 
 ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx  |  526 +++
 ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx  |   57 
 ucb/source/ucp/webdav-curl/ucpdav1.component         |   26 
 ucb/source/ucp/webdav-curl/webdavcontent.cxx         | 3292 +++++++++++++++++++
 ucb/source/ucp/webdav-curl/webdavcontent.hxx         |  266 +
 ucb/source/ucp/webdav-curl/webdavcontentcaps.cxx     |  602 +++
 ucb/source/ucp/webdav-curl/webdavdatasupplier.cxx    |  467 ++
 ucb/source/ucp/webdav-curl/webdavdatasupplier.hxx    |   73 
 ucb/source/ucp/webdav-curl/webdavprovider.cxx        |  177 +
 ucb/source/ucp/webdav-curl/webdavprovider.hxx        |  101 
 ucb/source/ucp/webdav-curl/webdavresponseparser.cxx  |  897 +++++
 ucb/source/ucp/webdav-curl/webdavresponseparser.hxx  |   38 
 ucb/source/ucp/webdav-curl/webdavresultset.cxx       |   76 
 ucb/source/ucp/webdav-curl/webdavresultset.hxx       |   48 
 34 files changed, 10260 insertions(+)

New commits:
commit 3afa1858a8a3d00ab6e03367f8cdf6cef2b511b2
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Sep 10 14:29:23 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Nov 1 18:14:49 2021 +0100

    ucb: copy upper level code of serf webdav ucp to webdav-curl
    
    Change-Id: Ia621e504d234d0904b40c7cd9aba49849c2ee859
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122044
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index c771d6abfc37..42ae6cd2921f 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -13988,6 +13988,36 @@ ucb/source/ucp/tdoc/tdoc_storage.cxx
 ucb/source/ucp/tdoc/tdoc_storage.hxx
 ucb/source/ucp/tdoc/tdoc_uri.cxx
 ucb/source/ucp/tdoc/tdoc_uri.hxx
+ucb/source/ucp/webdav-curl/ContentProperties.cxx
+ucb/source/ucp/webdav-curl/ContentProperties.hxx
+ucb/source/ucp/webdav-curl/DAVAuthListener.hxx
+ucb/source/ucp/webdav-curl/DAVAuthListenerImpl.hxx
+ucb/source/ucp/webdav-curl/DAVException.hxx
+ucb/source/ucp/webdav-curl/DAVProperties.cxx
+ucb/source/ucp/webdav-curl/DAVProperties.hxx
+ucb/source/ucp/webdav-curl/DAVRequestEnvironment.hxx
+ucb/source/ucp/webdav-curl/DAVResource.hxx
+ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
+ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
+ucb/source/ucp/webdav-curl/DAVSession.hxx
+ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx
+ucb/source/ucp/webdav-curl/DAVTypes.hxx
+ucb/source/ucp/webdav-curl/DateTimeHelper.cxx
+ucb/source/ucp/webdav-curl/DateTimeHelper.hxx
+ucb/source/ucp/webdav-curl/PropertyMap.hxx
+ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.cxx
+ucb/source/ucp/webdav-curl/UCBDeadPropertyValue.hxx
+ucb/source/ucp/webdav-curl/webdavcontent.cxx
+ucb/source/ucp/webdav-curl/webdavcontent.hxx
+ucb/source/ucp/webdav-curl/webdavcontentcaps.cxx
+ucb/source/ucp/webdav-curl/webdavdatasupplier.cxx
+ucb/source/ucp/webdav-curl/webdavdatasupplier.hxx
+ucb/source/ucp/webdav-curl/webdavprovider.cxx
+ucb/source/ucp/webdav-curl/webdavprovider.hxx
+ucb/source/ucp/webdav-curl/webdavresponseparser.cxx
+ucb/source/ucp/webdav-curl/webdavresultset.cxx
+ucb/source/ucp/webdav-curl/webdavresultset.hxx
+ucb/source/ucp/webdav-curl/webdavservices.cxx
 ucb/source/ucp/webdav-neon/ContentProperties.cxx
 ucb/source/ucp/webdav-neon/ContentProperties.hxx
 ucb/source/ucp/webdav-neon/DAVAuthListener.hxx
diff --git a/ucb/Library_ucpdav1.mk b/ucb/Library_ucpdav1.mk
index 127d046eb72b..6d66bce7d89a 100644
--- a/ucb/Library_ucpdav1.mk
+++ b/ucb/Library_ucpdav1.mk
@@ -27,6 +27,30 @@ $(eval $(call gb_Library_use_libraries,ucpdav1,\
        tl \
 ))
 
+ifeq ($(WITH_WEBDAV),curl)
+
+$(eval $(call 
gb_Library_set_componentfile,ucpdav1,ucb/source/ucp/webdav-curl/ucpdav1))
+
+$(eval $(call gb_Library_use_externals,ucpdav1,\
+       curl \
+))
+
+$(eval $(call gb_Library_add_exception_objects,ucpdav1,\
+       ucb/source/ucp/webdav-curl/ContentProperties \
+       ucb/source/ucp/webdav-curl/DAVProperties \
+       ucb/source/ucp/webdav-curl/DAVResourceAccess \
+       ucb/source/ucp/webdav-curl/DAVSessionFactory \
+       ucb/source/ucp/webdav-curl/DateTimeHelper \
+       ucb/source/ucp/webdav-curl/UCBDeadPropertyValue \
+       ucb/source/ucp/webdav-curl/webdavcontent \
+       ucb/source/ucp/webdav-curl/webdavcontentcaps \
+       ucb/source/ucp/webdav-curl/webdavdatasupplier \
+       ucb/source/ucp/webdav-curl/webdavprovider \
+       ucb/source/ucp/webdav-curl/webdavresponseparser \
+       ucb/source/ucp/webdav-curl/webdavresultset \
+))
+
+else
 ifeq ($(WITH_WEBDAV),neon)
 
 $(eval $(call 
gb_Library_set_componentfile,ucpdav1,ucb/source/ucp/webdav-neon/ucpdav1))
@@ -115,6 +139,7 @@ $(eval $(call gb_Library_add_exception_objects,ucpdav1,\
  ))
 
 endif # WITH_WEBDAV
+endif # WITH_WEBDAV
 
 ifeq ($(OS),WNT)
 $(eval $(call gb_Library_use_system_win32_libs,ucpdav1,\
diff --git a/ucb/source/ucp/webdav-curl/ContentProperties.cxx 
b/ucb/source/ucp/webdav-curl/ContentProperties.cxx
new file mode 100644
index 000000000000..85406e680972
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/ContentProperties.cxx
@@ -0,0 +1,593 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <com/sun/star/util/DateTime.hpp>
+#include "SerfUri.hxx"
+#include "DAVResource.hxx"
+#include "DAVProperties.hxx"
+#include "DateTimeHelper.hxx"
+#include "webdavprovider.hxx"
+#include "ContentProperties.hxx"
+
+#include <sal/log.hxx>
+
+using namespace com::sun::star;
+using namespace http_dav_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 )
+{
+    SAL_WARN_IF( !rResource.uri.getLength(), "ucb.ucp.webdav",
+                "ContentProperties ctor - Empty resource URI!" );
+
+    // Title
+    try
+    {
+        SerfUri aURI( rResource.uri );
+        m_aEscapedTitle = aURI.GetPathBaseName();
+
+        (*m_xProps)[ OUString( "Title" ) ]
+            = PropertyValue(
+                uno::makeAny( aURI.GetPathBaseNameUnescaped() ), true );
+    }
+    catch ( DAVException const & )
+    {
+        (*m_xProps)[ OUString( "Title" ) ]
+            = PropertyValue(
+                uno::makeAny(
+                    OUString( "*** unknown ***" ) ),
+                true );
+    }
+
+    for ( const auto& rProp : rResource.properties )
+    {
+        addProperty( rProp );
+    }
+
+    if ( rResource.uri.endsWith("/") )
+        m_bTrailingSlash = true;
+}
+
+
+ContentProperties::ContentProperties(
+                        const OUString & rTitle, bool bFolder )
+: m_xProps( new PropertyValueMap ),
+  m_bTrailingSlash( false )
+{
+    (*m_xProps)[ OUString( "Title" ) ]
+        = PropertyValue( uno::makeAny( rTitle ), true );
+    (*m_xProps)[ OUString( "IsFolder" ) ]
+        = PropertyValue( uno::makeAny( bFolder ), true );
+    (*m_xProps)[ OUString( "IsDocument" ) ]
+        = PropertyValue( uno::makeAny( bool( !bFolder ) ), true );
+}
+
+
+ContentProperties::ContentProperties( const OUString & rTitle )
+: m_xProps( new PropertyValueMap ),
+  m_bTrailingSlash( false )
+{
+    (*m_xProps)[ OUString( "Title" ) ]
+        = PropertyValue( uno::makeAny( rTitle ), true );
+}
+
+
+ContentProperties::ContentProperties()
+: m_xProps( new PropertyValueMap ),
+  m_bTrailingSlash( false )
+{
+}
+
+
+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 OUString & rName ) const
+{
+    if ( get( rName ) )
+        return true;
+    else
+        return false;
+}
+
+
+const uno::Any & ContentProperties::getValue(
+                                    const OUString & rName ) const
+{
+    const PropertyValue * pProp = get( rName );
+    if ( pProp )
+        return pProp->value();
+    else
+        return m_aEmptyAny;
+}
+
+
+const PropertyValue * ContentProperties::get(
+                                    const OUString & rName ) const
+{
+    PropertyValueMap::const_iterator it = m_xProps->find( rName );
+    const PropertyValueMap::const_iterator end = m_xProps->end();
+
+    if ( it == end )
+    {
+        it = std::find_if(m_xProps->cbegin(), end,
+            [&rName](const PropertyValueMap::value_type& rEntry) {
+                return rEntry.first.equalsIgnoreAsciiCase( rName );
+            });
+        if ( it != end )
+            return &(*it).second;
+
+        return nullptr;
+    }
+    else
+        return &(*it).second;
+}
+
+
+// static
+void ContentProperties::UCBNamesToDAVNames(
+                            const uno::Sequence< beans::Property > & rProps,
+                            std::vector< 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
+
+    bool bCreationDate  = false;
+    bool bLastModified  = false;
+    bool bContentType   = false;
+    bool bContentLength = false;
+    bool bResourceType  = false;
+
+    sal_Int32 nCount = rProps.getLength();
+    for ( sal_Int32 n = 0; n < nCount; ++n )
+    {
+        const beans::Property & rProp = rProps[ n ];
+
+        if ( rProp.Name == "Title" )
+        {
+            // Title is always obtained from resource's URI.
+            continue;
+        }
+        else if ( rProp.Name == "DateCreated" ||
+                  ( rProp.Name == DAVProperties::CREATIONDATE ) )
+        {
+            if ( !bCreationDate )
+            {
+                propertyNames.push_back( DAVProperties::CREATIONDATE );
+                bCreationDate = true;
+            }
+        }
+        else if ( rProp.Name == "DateModified" ||
+                  ( rProp.Name == DAVProperties::GETLASTMODIFIED ) )
+        {
+            if ( !bLastModified )
+            {
+                propertyNames.push_back(
+                    DAVProperties::GETLASTMODIFIED );
+                bLastModified = true;
+            }
+        }
+        else if ( rProp.Name == "MediaType" ||
+                  ( rProp.Name == DAVProperties::GETCONTENTTYPE ) )
+        {
+            if ( !bContentType )
+            {
+                propertyNames.push_back(
+                        DAVProperties::GETCONTENTTYPE );
+                bContentType = true;
+            }
+        }
+        else if ( rProp.Name == "Size" ||
+                  ( rProp.Name == DAVProperties::GETCONTENTLENGTH ) )
+        {
+            if ( !bContentLength )
+            {
+                propertyNames.push_back(
+                    DAVProperties::GETCONTENTLENGTH );
+                bContentLength = true;
+            }
+        }
+        else if ( rProp.Name == "ContentType" ||
+                  rProp.Name == "IsDocument" ||
+                  rProp.Name == "IsFolder" ||
+                  ( rProp.Name == DAVProperties::RESOURCETYPE ) )
+        {
+            if ( !bResourceType )
+            {
+                propertyNames.push_back( DAVProperties::RESOURCETYPE );
+                bResourceType = true;
+            }
+        }
+        else
+        {
+            if ( bIncludeUnmatched )
+                propertyNames.push_back( rProp.Name );
+        }
+    }
+}
+
+
+// static
+void ContentProperties::UCBNamesToHTTPNames(
+                            const uno::Sequence< beans::Property > & rProps,
+                            std::vector< 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 == "DateModified" )
+        {
+            propertyNames.push_back( OUString( "Last-Modified" ) );
+        }
+        else if ( rProp.Name == "MediaType" )
+        {
+            propertyNames.push_back( OUString( "Content-Type" ) );
+        }
+        else if ( rProp.Name == "Size" )
+        {
+            propertyNames.push_back( OUString( "Content-Length" ) );
+        }
+        else
+        {
+            if ( bIncludeUnmatched )
+                propertyNames.push_back( rProp.Name );
+        }
+    }
+}
+
+
+bool ContentProperties::containsAllNames(
+                    const uno::Sequence< beans::Property >& rProps,
+                    std::vector< OUString > & rNamesNotContained ) const
+{
+    rNamesNotContained.clear();
+
+    sal_Int32 nCount = rProps.getLength();
+    for ( sal_Int32 n = 0; n < nCount; ++n )
+    {
+        const OUString & rName = rProps[ n ].Name;
+        if ( !contains( rName ) )
+        {
+            // Not found.
+            rNamesNotContained.push_back( rName );
+        }
+    }
+
+    return ( rNamesNotContained.size() == 0 );
+}
+
+
+void ContentProperties::addProperties(
+                                const std::vector< OUString > & rProps,
+                                const ContentProperties & rContentProps )
+{
+    for ( const OUString & rName : rProps )
+    {
+        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 );
+            }
+        }
+    }
+}
+
+
+void ContentProperties::addProperties( const ContentProperties & rProps )
+{
+    for ( const auto& rProp : *rProps.m_xProps )
+    {
+        addProperty(
+            rProp.first, rProp.second.value(), rProp.second.isCaseSensitive() 
);
+    }
+}
+
+
+void ContentProperties::addProperties(
+    const std::vector< DAVPropertyValue > & rProps )
+{
+    for ( const auto& rProp : rProps )
+    {
+        addProperty( rProp );
+    }
+}
+
+
+void ContentProperties::addProperty( const DAVPropertyValue & rProp )
+{
+    addProperty( rProp.Name, rProp.Value, rProp.IsCaseSensitive );
+}
+
+
+void ContentProperties::addProperty( const OUString & rName,
+                                     const css::uno::Any & rValue,
+                                     bool bIsCaseSensitive )
+{
+    if ( rName == DAVProperties::CREATIONDATE )
+    {
+        // Map DAV:creationdate to UCP:DateCreated
+        OUString aValue;
+        rValue >>= aValue;
+        util::DateTime aDate;
+        DateTimeHelper::convert( aValue, aDate );
+
+        (*m_xProps)[ OUString( "DateCreated" ) ]
+            = PropertyValue( uno::makeAny( aDate ), true );
+    }
+    //  else if ( rName.equals( DAVProperties::DISPLAYNAME ) )
+    //  {
+    //  }
+    //  else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
+    //  {
+    //  }
+    else if ( rName == DAVProperties::GETCONTENTLENGTH )
+    {
+        // Map DAV:getcontentlength to UCP:Size
+        OUString aValue;
+        rValue >>= aValue;
+
+        (*m_xProps)[ OUString( "Size" ) ]
+            = PropertyValue( uno::makeAny( aValue.toInt64() ), true );
+    }
+    else if ( rName == "Content-Length" )
+    {
+        // Do NOT map Content-Length entity header to DAV:getcontentlength!
+        // Only DAV resources have this property.
+
+        // Map Content-Length entity header to UCP:Size
+        OUString aValue;
+        rValue >>= aValue;
+
+        (*m_xProps)[ OUString( "Size" ) ]
+            = PropertyValue( uno::makeAny( aValue.toInt64() ), true );
+    }
+    else if ( rName == DAVProperties::GETCONTENTTYPE )
+    {
+        // Map DAV:getcontenttype to UCP:MediaType (1:1)
+        (*m_xProps)[ OUString( "MediaType" ) ]
+            = PropertyValue( rValue, true );
+    }
+    else if ( rName == "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)[ OUString( "MediaType" ) ]
+            = PropertyValue( rValue, true );
+    }
+    //  else if ( rName.equals( DAVProperties::GETETAG ) )
+    //  {
+    //  }
+    else if ( rName == DAVProperties::GETLASTMODIFIED )
+    {
+        // Map the DAV:getlastmodified entity header to UCP:DateModified
+        OUString aValue;
+        rValue >>= aValue;
+        util::DateTime aDate;
+        DateTimeHelper::convert( aValue, aDate );
+
+        (*m_xProps)[ OUString( "DateModified" ) ]
+            = PropertyValue( uno::makeAny( aDate ), true );
+    }
+    else if ( rName == "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
+        OUString aValue;
+        rValue >>= aValue;
+        util::DateTime aDate;
+        DateTimeHelper::convert( aValue, aDate );
+
+        (*m_xProps)[ OUString( "DateModified" ) ]
+            = PropertyValue( uno::makeAny( aDate ), true );
+    }
+    //  else if ( rName.equals( DAVProperties::LOCKDISCOVERY ) )
+    //  {
+    //  }
+    else if ( rName == DAVProperties::RESOURCETYPE )
+    {
+        OUString aValue;
+        rValue >>= aValue;
+
+        // Map DAV:resourcetype to UCP:IsFolder, UCP:IsDocument, 
UCP:ContentType
+        bool bFolder =
+            aValue.equalsIgnoreAsciiCase( "collection" );
+
+        (*m_xProps)[ OUString( "IsFolder" ) ]
+            = PropertyValue( uno::makeAny( bFolder ), true );
+        (*m_xProps)[ OUString( "IsDocument" ) ]
+            = PropertyValue( uno::makeAny( bool( !bFolder ) ), true );
+        (*m_xProps)[ OUString( "ContentType" ) ]
+            = PropertyValue( uno::makeAny( bFolder
+                ? OUString( WEBDAV_COLLECTION_TYPE )
+                : OUString( WEBDAV_CONTENT_TYPE ) ), true );
+    }
+    //  else if ( rName.equals( DAVProperties::SUPPORTEDLOCK ) )
+    //  {
+    //  }
+
+    // Save property.
+    (*m_xProps)[ rName ] = PropertyValue( rValue, bIsCaseSensitive );
+}
+
+
+// CachableContentProperties Implementation.
+
+
+namespace
+{
+    bool isCachable( OUString const & rName,
+                     bool isCaseSensitive )
+    {
+        const OUString aNonCachableProps [] =
+        {
+            DAVProperties::LOCKDISCOVERY,
+
+            DAVProperties::GETETAG,
+            OUString( "ETag" ),
+
+            OUString( "DateModified" ),
+            OUString( "Last-Modified" ),
+            DAVProperties::GETLASTMODIFIED,
+
+            OUString( "Size" ),
+            OUString( "Content-Length" ),
+            DAVProperties::GETCONTENTLENGTH,
+
+            OUString( "Date" )
+        };
+
+        for ( sal_uInt32 n = 0;
+              n <  ( sizeof( aNonCachableProps )
+                     / sizeof( aNonCachableProps[ 0 ] ) );
+              ++n )
+        {
+            if ( isCaseSensitive )
+            {
+                if ( rName.equals( aNonCachableProps[ n ] ) )
+                    return false;
+            }
+            else
+                if ( rName.equalsIgnoreAsciiCase( aNonCachableProps[ n ] ) )
+                    return false;
+        }
+        return true;
+    }
+
+} // namespace
+
+
+CachableContentProperties::CachableContentProperties(
+    const ContentProperties & rProps )
+{
+    addProperties( rProps );
+}
+
+
+void CachableContentProperties::addProperties(
+    const ContentProperties & rProps )
+{
+    const std::unique_ptr< PropertyValueMap > & props = rProps.getProperties();
+
+    for ( const auto& rProp : *props )
+    {
+        if ( isCachable( rProp.first, rProp.second.isCaseSensitive() ) )
+            m_aProps.addProperty( rProp.first,
+                                  rProp.second.value(),
+                                  rProp.second.isCaseSensitive() );
+    }
+}
+
+
+void CachableContentProperties::addProperties(
+    const std::vector< DAVPropertyValue > & rProps )
+{
+    for ( const auto& rProp : rProps )
+    {
+        if ( isCachable( rProp.Name, rProp.IsCaseSensitive ) )
+            m_aProps.addProperty( rProp );
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/ContentProperties.hxx 
b/ucb/source/ucp/webdav-curl/ContentProperties.hxx
new file mode 100644
index 000000000000..0f1bc0a52c7e
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/ContentProperties.hxx
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include "DAVResource.hxx"
+
+namespace com::sun::star::beans {
+    struct Property;
+}
+
+namespace http_dav_ucp
+{
+
+struct DAVResource;
+
+// PropertyValueMap.
+class PropertyValue
+{
+private:
+    css::uno::Any   m_aValue;
+    bool            m_bIsCaseSensitive;
+
+public:
+    PropertyValue()
+    : m_bIsCaseSensitive( true ) {}
+
+    explicit PropertyValue( const css::uno::Any & rValue,
+                   bool bIsCaseSensitive )
+    : m_aValue( rValue),
+      m_bIsCaseSensitive( bIsCaseSensitive ) {}
+
+    bool isCaseSensitive() const { return m_bIsCaseSensitive; }
+    const css::uno::Any & value() const { return m_aValue; }
+
+};
+
+typedef std::unordered_map< OUString, PropertyValue > PropertyValueMap;
+
+class ContentProperties
+{
+public:
+    ContentProperties();
+
+    explicit ContentProperties( const DAVResource& rResource );
+
+    // Mini props for transient contents.
+    ContentProperties( const OUString & rTitle, bool bFolder );
+
+    // Micro props for non-existing contents.
+    explicit ContentProperties( const OUString & rTitle );
+
+    ContentProperties( const ContentProperties & rOther );
+
+    bool contains( const OUString & rName ) const;
+
+    const css::uno::Any& getValue( const 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 filled 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 css::uno::Sequence< 
css::beans::Property > & rProps,
+                                    std::vector< 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 filled 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 css::uno::Sequence< 
css::beans::Property > & rProps,
+                                    std::vector< OUString > & resources,
+                                    bool bIncludeUnmatched = true );
+
+    // return true, if all properties contained in rProps are contained in
+    // this ContentProperties instance. Otherwise, false will be returned.
+    // rNamesNotContained contain the missing names.
+    bool containsAllNames(
+                    const css::uno::Sequence< css::beans::Property >& rProps,
+                    std::vector< 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< 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 OUString & rName,
+                     const css::uno::Any & rValue,
+                     bool bIsCaseSensitive );
+
+    // overwrites probably existing entry.
+    void addProperty( const DAVPropertyValue & rProp );
+
+    bool isTrailingSlash() const { return m_bTrailingSlash; }
+
+    const OUString & getEscapedTitle() const { return m_aEscapedTitle; }
+
+    // Not good to expose implementation details, but this is actually an
+    // internal class.
+    const std::unique_ptr< PropertyValueMap > & getProperties() const
+    { return m_xProps; }
+
+private:
+    OUString m_aEscapedTitle;
+    std::unique_ptr< PropertyValueMap > m_xProps;
+    bool m_bTrailingSlash;
+
+    static css::uno::Any m_aEmptyAny;
+
+    ContentProperties & operator=( const ContentProperties & ); // n.i.
+
+    const PropertyValue * get( const OUString & rName ) const;
+};
+
+class CachableContentProperties
+{
+private:
+    ContentProperties m_aProps;
+
+    CachableContentProperties & operator=( const CachableContentProperties & 
); // n.i.
+    CachableContentProperties( const CachableContentProperties & ); // n.i.
+
+public:
+    explicit CachableContentProperties( const ContentProperties & rProps );
+
+    void addProperties( const ContentProperties & rProps );
+
+    void addProperties( const std::vector< DAVPropertyValue > & rProps );
+
+    bool containsAllNames(
+                    const css::uno::Sequence< css::beans::Property >& rProps,
+                    std::vector< OUString > & rNamesNotContained ) const
+    { return m_aProps.containsAllNames( rProps, rNamesNotContained ); }
+
+    const css::uno::Any &
+    getValue( const OUString & rName ) const
+    { return m_aProps.getValue( rName ); }
+
+    operator const ContentProperties & () const { return m_aProps; }
+};
+
+} // namespace http_dav_ucp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVAuthListener.hxx 
b/ucb/source/ucp/webdav-curl/DAVAuthListener.hxx
new file mode 100644
index 000000000000..c3d643bc7d82
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVAuthListener.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#include <salhelper/simplereferenceobject.hxx>
+#include <rtl/ustring.hxx>
+
+namespace http_dav_ucp
+{
+
+class DAVAuthListener : public salhelper::SimpleReferenceObject
+{
+    public:
+        virtual int authenticate(
+            const OUString & inRealm,
+            const OUString & inHostName,
+            OUString & inoutUserName,
+            OUString & outPassWord,
+            bool bCanUseSystemCredentials,
+            bool bUsePreviousCredentials = true ) = 0;
+};
+
+} // namespace http_dav_ucp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVAuthListenerImpl.hxx 
b/ucb/source/ucp/webdav-curl/DAVAuthListenerImpl.hxx
new file mode 100644
index 000000000000..219a6490689b
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVAuthListenerImpl.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#include "DAVAuthListener.hxx"
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+
+
+namespace http_dav_ucp
+{
+
+
+
+
+    class DAVAuthListener_Impl : public DAVAuthListener
+    {
+    public:
+
+        DAVAuthListener_Impl(
+            const css::uno::Reference<css::ucb::XCommandEnvironment>& xEnv,
+            const OUString & inURL )
+            : m_xEnv( xEnv ), m_aURL( inURL )
+        {
+        }
+
+        virtual int authenticate( const OUString & inRealm,
+                                  const OUString & inHostName,
+                                  OUString & inoutUserName,
+                                  OUString & outPassWord,
+                                  bool bCanUseSystemCredentials,
+                                  bool bUsePreviousCredentials = true ) 
override;
+    private:
+
+        const css::uno::Reference< css::ucb::XCommandEnvironment > m_xEnv;
+        const OUString m_aURL;
+
+        OUString m_aPrevPassword;
+        OUString m_aPrevUsername;
+    };
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVException.hxx 
b/ucb/source/ucp/webdav-curl/DAVException.hxx
new file mode 100644
index 000000000000..ba121efa21c9
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVException.hxx
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+namespace http_dav_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 std::exception
+{
+    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_NOAUTH,    // No User authentication data provided - 
e.g., user aborts corresponding dialog
+                                // 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;
+        OUString   mData;
+        sal_uInt16      mStatusCode;
+
+    public:
+         explicit DAVException( ExceptionCode inExceptionCode )
+             : mExceptionCode( inExceptionCode )
+             , mData()
+             , mStatusCode( SC_NONE )
+         {};
+         DAVException( ExceptionCode inExceptionCode,
+                       const OUString & rData )
+             : mExceptionCode( inExceptionCode )
+             , mData( rData )
+             , mStatusCode( SC_NONE )
+         {};
+         DAVException( ExceptionCode inExceptionCode,
+                       const OUString & rData,
+                       sal_uInt16 nStatusCode )
+            : mExceptionCode( inExceptionCode )
+            , mData( rData )
+            , mStatusCode( nStatusCode )
+         {};
+
+    const ExceptionCode & getError() const { return mExceptionCode; }
+    const OUString & getData() const  { return mData; }
+    sal_uInt16 getStatus() const { return mStatusCode; }
+};
+
+} // namespace http_dav_ucp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVProperties.cxx 
b/ucb/source/ucp/webdav-curl/DAVProperties.cxx
new file mode 100644
index 000000000000..a08a8488da15
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVProperties.cxx
@@ -0,0 +1,222 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <string.h>
+#include "DAVProperties.hxx"
+#include <rtl/ustrbuf.hxx>
+
+using namespace http_dav_ucp;
+
+const OUString DAVProperties::CREATIONDATE =
+                OUString( "DAV:creationdate" );
+const OUString DAVProperties::DISPLAYNAME =
+                OUString( "DAV:displayname" );
+const OUString DAVProperties::GETCONTENTLANGUAGE =
+                OUString( "DAV:getcontentlanguage" );
+const OUString DAVProperties::GETCONTENTLENGTH =
+                OUString( "DAV:getcontentlength" );
+const OUString DAVProperties::GETCONTENTTYPE =
+                OUString( "DAV:getcontenttype" );
+const OUString DAVProperties::GETETAG =
+                OUString( "DAV:getetag" );
+const OUString DAVProperties::GETLASTMODIFIED =
+                OUString( "DAV:getlastmodified" );
+const OUString DAVProperties::LOCKDISCOVERY =
+                OUString( "DAV:lockdiscovery" );
+const OUString DAVProperties::RESOURCETYPE =
+                OUString( "DAV:resourcetype" );
+const OUString DAVProperties::SUPPORTEDLOCK =
+                OUString( "DAV:supportedlock" );
+
+const OUString DAVProperties::EXECUTABLE =
+                OUString( "http://apache.org/dav/props/executable"; );
+
+
+// static
+void DAVProperties::createSerfPropName( const OUString & rFullName,
+                                        SerfPropName & rName )
+{
+    if ( rFullName.startsWith( "DAV:" ) )
+    {
+        rName.nspace = "DAV:";
+        rName.name
+            = strdup( OUStringToOString(
+                        rFullName.copy( RTL_CONSTASCII_LENGTH( "DAV:" ) ),
+                                        RTL_TEXTENCODING_UTF8 ).getStr() );
+    }
+    else if ( rFullName.startsWith( "http://apache.org/dav/props/"; ) )
+    {
+        rName.nspace = "http://apache.org/dav/props/";;
+        rName.name
+            = strdup( OUStringToOString(
+                        rFullName.copy(
+                            RTL_CONSTASCII_LENGTH(
+                                "http://apache.org/dav/props/"; ) ),
+                            RTL_TEXTENCODING_UTF8 ).getStr() );
+    }
+    else if ( rFullName.startsWith( "http://ucb.openoffice.org/dav/props/"; ) )
+    {
+        rName.nspace = "http://ucb.openoffice.org/dav/props/";;
+        rName.name
+            = strdup( OUStringToOString(
+                        rFullName.copy(
+                            RTL_CONSTASCII_LENGTH(
+                                "http://ucb.openoffice.org/dav/props/"; ) ),
+                            RTL_TEXTENCODING_UTF8 ).getStr() );
+    }
+    else if ( rFullName.startsWith( "<prop:" ) )
+    {
+        // Support for 3rd party namespaces/props
+
+        OString aFullName
+            = 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 ).getStr() );
+
+        nStart = aFullName.indexOf( '=', nStart + nLen ) + 2; // after ="
+        nLen = aFullName.getLength() - RTL_CONSTASCII_LENGTH( "\">" ) - nStart;
+        rName.nspace = strdup( aFullName.copy( nStart, nLen ).getStr() );
+    }
+    else
+    {
+        // Add our namespace to our own properties.
+        rName.nspace = "http://ucb.openoffice.org/dav/props/";;
+        rName.name
+            = strdup( OUStringToOString( rFullName,
+                                              RTL_TEXTENCODING_UTF8 ).getStr() 
);
+    }
+}
+
+
+// static
+void DAVProperties::createUCBPropName( const char * nspace,
+                                       const char * name,
+                                       OUString & rFullName )
+{
+    OUString aNameSpace
+        = OStringToOUString( nspace, RTL_TEXTENCODING_UTF8 );
+    OUString aName
+        = 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 ) )
+        {
+            aNameSpace = "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.startsWith( "DAV:" ) )
+    {
+        // Okay, Just concat strings.
+    }
+    else if ( rFullName.startsWith( "http://apache.org/dav/props/"; ) )
+    {
+        // Okay, Just concat strings.
+    }
+    else if ( rFullName.startsWith( "http://ucb.openoffice.org/dav/props/"; ) )
+    {
+        // 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  = "<prop:";
+        rFullName += aName;
+        rFullName += " xmlns:prop=\"";
+        rFullName += aNameSpace;
+        rFullName += "\">";
+    }
+}
+
+
+// static
+bool DAVProperties::isUCBDeadProperty( const SerfPropName & rName )
+{
+    return ( rName.nspace &&
+             ( rtl_str_compareIgnoreAsciiCase(
+                 rName.nspace, "http://ucb.openoffice.org/dav/props/"; )
+               == 0 ) );
+}
+
+bool DAVProperties::isUCBSpecialProperty(const OUString& rFullName, OUString& 
rParsedName)
+{
+    sal_Int32 nLen = rFullName.getLength();
+    if ( nLen <= 0 ||
+            !rFullName.startsWith( "<prop:" ) ||
+            !rFullName.endsWith( "\">" ) )
+        return false;
+
+    sal_Int32 nStart = RTL_CONSTASCII_LENGTH( "<prop:" );
+    sal_Int32 nEnd = rFullName.indexOf( ' ', nStart );
+    if ( nEnd == -1 )
+        return false;
+
+    OUString sPropName = rFullName.copy( nStart, nEnd - nStart );
+    if ( !sPropName.getLength() )
+        return false;
+
+    // TODO skip whitespaces?
+    if ( !rFullName.match( "xmlns:prop=\"", ++nEnd ) )
+        return false;
+
+    nStart = nEnd + RTL_CONSTASCII_LENGTH( "xmlns:prop=\"" );
+    nEnd = rFullName.indexOf( '"', nStart );
+    if ( nEnd != nLen - RTL_CONSTASCII_LENGTH( "\">" ) )
+        return false;
+
+    OUString sNamesp = rFullName.copy( nStart, nEnd - nStart );
+    if ( !( nLen = sNamesp.getLength() ) )
+        return false;
+
+    OUStringBuffer aBuff( sNamesp );
+    if ( sNamesp[nLen - 1] != '/' )
+        aBuff.append( '/' );
+    aBuff.append( sPropName );
+    rParsedName = aBuff.makeStringAndClear();
+
+    return rParsedName.getLength();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVProperties.hxx 
b/ucb/source/ucp/webdav-curl/DAVProperties.hxx
new file mode 100644
index 000000000000..5bc9a1b0c8f4
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVProperties.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+namespace http_dav_ucp
+{
+
+typedef struct { const char *nspace, *name; } SerfPropName;
+
+struct DAVProperties
+{
+    static const OUString CREATIONDATE;
+    static const OUString DISPLAYNAME;
+    static const OUString GETCONTENTLANGUAGE;
+    static const OUString GETCONTENTLENGTH;
+    static const OUString GETCONTENTTYPE;
+    static const OUString GETETAG;
+    static const OUString GETLASTMODIFIED;
+    static const OUString LOCKDISCOVERY;
+    static const OUString RESOURCETYPE;
+    static const OUString SUPPORTEDLOCK;
+    static const OUString EXECUTABLE;
+
+    static void createSerfPropName( const OUString & rFullName,
+                                    SerfPropName & rName );
+    static void createUCBPropName ( const char * nspace,
+                                    const char * name,
+                                    OUString & rFullName );
+
+    static bool isUCBDeadProperty( const SerfPropName & rName );
+    static bool isUCBSpecialProperty( const OUString & rFullName,
+                                      OUString & rParsedName );
+};
+
+} // namespace http_dav_ucp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVRequestEnvironment.hxx 
b/ucb/source/ucp/webdav-curl/DAVRequestEnvironment.hxx
new file mode 100644
index 000000000000..a489b43092c8
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVRequestEnvironment.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#include <vector>
+#include <rtl/ref.hxx>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include "DAVAuthListener.hxx"
+
+namespace http_dav_ucp
+{
+    typedef std::pair< OUString, OUString > DAVRequestHeader;
+    typedef std::vector< DAVRequestHeader > DAVRequestHeaders;
+
+struct DAVRequestEnvironment
+{
+    OUString m_aRequestURI;
+    rtl::Reference< DAVAuthListener >     m_xAuthListener;
+    DAVRequestHeaders                     m_aRequestHeaders;
+    css::uno::Reference< css::ucb::XCommandEnvironment > m_xEnv;
+
+DAVRequestEnvironment( const OUString & rRequestURI,
+                       const rtl::Reference< DAVAuthListener > & xListener,
+                       const DAVRequestHeaders & rRequestHeaders,
+                       const css::uno::Reference< 
css::ucb::XCommandEnvironment > & xEnv)
+    : m_aRequestURI( rRequestURI ),
+      m_xAuthListener( xListener ),
+      m_aRequestHeaders( rRequestHeaders ),
+      m_xEnv( xEnv ){}
+
+    DAVRequestEnvironment() {}
+};
+
+} // namespace http_dav_ucp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVResource.hxx 
b/ucb/source/ucp/webdav-curl/DAVResource.hxx
new file mode 100644
index 000000000000..15359719d880
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVResource.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#include <vector>
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Any.hxx>
+
+namespace http_dav_ucp
+{
+
+struct DAVPropertyValue
+{
+    OUString            Name;
+    css::uno::Any       Value;
+    bool                IsCaseSensitive;
+
+    DAVPropertyValue() : IsCaseSensitive( true ) {}
+};
+
+struct DAVResource
+{
+    OUString uri;
+    std::vector< DAVPropertyValue > properties;
+
+    DAVResource() {}
+    explicit DAVResource( const OUString & inUri ) : uri( inUri ) {}
+};
+
+struct DAVResourceInfo
+{
+    OUString uri;
+    std::vector < OUString > properties;
+
+    explicit DAVResourceInfo( const OUString & inUri ) : uri( inUri ) {}
+};
+
+} // namespace http_dav_ucp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx 
b/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
new file mode 100644
index 000000000000..90001a818645
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
@@ -0,0 +1,1116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/task/XInteractionAbort.hpp>
+#include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
+
+#include <ucbhelper/simpleauthenticationrequest.hxx>
+#include <comphelper/seekableinput.hxx>
+#include <sal/log.hxx>
+
+#include "DAVAuthListenerImpl.hxx"
+#include "DAVResourceAccess.hxx"
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/io/IOException.hpp>
+
+using namespace http_dav_ucp;
+using namespace com::sun::star;
+
+
+// DAVAuthListener_Impl Implementation.
+
+
+// virtual
+int DAVAuthListener_Impl::authenticate(
+    const OUString & inRealm,
+    const OUString & inHostName,
+    OUString & inoutUserName,
+    OUString & outPassWord,
+    bool bCanUseSystemCredentials,
+    bool bUsePreviousCredentials )
+{
+    if ( m_xEnv.is() )
+    {
+        uno::Reference< task::XInteractionHandler > xIH
+            = m_xEnv->getInteractionHandler();
+
+        if ( xIH.is() )
+        {
+            // Providing previously retrieved credentials will cause the 
password
+            // container to reject these. Thus, the credential input dialog 
will be shown again.
+            // #102871# - Supply username and password from previous try.
+            // Password container service depends on this!
+            if ( inoutUserName.isEmpty() && bUsePreviousCredentials )
+                inoutUserName = m_aPrevUsername;
+
+            if ( outPassWord.isEmpty() && bUsePreviousCredentials )
+                outPassWord = m_aPrevPassword;
+
+            rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
+                = new ucbhelper::SimpleAuthenticationRequest(
+                    m_aURL, inHostName, inRealm, inoutUserName,
+                    outPassWord,
+                    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();
+
+                    bool bUseSystemCredentials = false;
+
+                    if ( bCanUseSystemCredentials )
+                        bUseSystemCredentials
+                            = xSupp->getUseSystemCredentials();
+
+                    if ( bUseSystemCredentials )
+                    {
+                        // This is the (strange) way to tell neon to use
+                        // system credentials.
+                        inoutUserName.clear();
+                        outPassWord.clear();
+                    }
+                    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< uno::XComponentContext > & rContext,
+    rtl::Reference< DAVSessionFactory > const & rSessionFactory,
+    const OUString & rURL )
+: m_aURL( rURL ),
+  m_xSessionFactory( rSessionFactory ),
+  m_xContext( rContext )
+{
+}
+
+
+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_xContext( rOther.m_xContext ),
+  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_xContext           = rOther.m_xContext;
+    m_aRedirectURIs   = rOther.m_aRedirectURIs;
+
+    return *this;
+}
+
+
+void DAVResourceAccess::PROPFIND(
+    const Depth nDepth,
+    const std::vector< OUString > & rPropertyNames,
+    std::vector< DAVResource > & rResources,
+    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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< OUString > & rHeaderNames,
+    DAVResource & rResource,
+    const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 )
+{
+    initialize();
+
+    uno::Reference< io::XInputStream > xStream;
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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< OUString > & rHeaderNames,
+    DAVResource & rResource,
+    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+    initialize();
+
+    uno::Reference< io::XInputStream > xStream;
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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;
+}
+
+
+uno::Reference< io::XInputStream > DAVResourceAccess::GET(
+    DAVRequestHeaders &rRequestHeaders,
+    const std::vector< OUString > & rHeaderNames,
+    DAVResource & rResource,
+    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+    initialize();
+
+    uno::Reference< io::XInputStream > xStream;
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_GET,
+                                   rRequestHeaders );
+
+            xStream = m_xSession->GET( getRequestURI(),
+                                       rHeaderNames,
+                                       rResource,
+                                       DAVRequestEnvironment(
+                                           getRequestURI(),
+                                           new DAVAuthListener_Impl(
+                                               xEnv, m_aURL ),
+                                           rRequestHeaders, 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< OUString > & rHeaderNames,
+    DAVResource & rResource,
+    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+    initialize();
+
+    bool bRetry;
+    int errorCount = 0;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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()
+{
+    // 17.11.09 (tkr): abort currently disabled caused by issue i106766
+    // initialize();
+    // m_xSession->abort();
+    SAL_INFO("ucb.ucp.webdav",  "Not implemented. -> #i106766#" );
+}
+
+
+namespace {
+
+    /// @throws DAVException
+    void resetInputStream( const uno::Reference< io::XInputStream > & rStream )
+    {
+        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 )
+{
+    initialize();
+
+    // Make stream seekable, if it not. Needed, if request must be retried.
+    uno::Reference< io::XInputStream > xSeekableStream
+        = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
+            rStream, m_xContext );
+
+    int errorCount = 0;
+    bool bRetry = false;
+    do
+    {
+        if ( bRetry )
+            resetInputStream( xSeekableStream );
+
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 OUString & rContentType,
+    const OUString & rReferer,
+    const uno::Reference< io::XInputStream > & rInputStream,
+    const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+{
+    initialize();
+
+    // Make stream seekable, if it not. Needed, if request must be retried.
+    uno::Reference< io::XInputStream > xSeekableStream
+        = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
+            rInputStream, m_xContext );
+
+    uno::Reference< io::XInputStream > xStream;
+    int errorCount = 0;
+    bool bRetry = false;
+    do
+    {
+        if ( bRetry )
+        {
+            resetInputStream( xSeekableStream );
+            bRetry = false;
+        }
+
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 OUString & rContentType,
+    const OUString & rReferer,
+    const uno::Reference< io::XInputStream > & rInputStream,
+    uno::Reference< io::XOutputStream > & rOutputStream,
+    const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+{
+    initialize();
+
+    // Make stream seekable, if it not. Needed, if request must be retried.
+    uno::Reference< io::XInputStream > xSeekableStream
+        = comphelper::OSeekableInputWrapper::CheckSeekableCanWrap(
+            rInputStream, m_xContext );
+
+    int errorCount = 0;
+    bool bRetry  = false;
+    do
+    {
+        if ( bRetry )
+        {
+            resetInputStream( xSeekableStream );
+            bRetry = false;
+        }
+
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 OUString & rSourcePath,
+    const OUString & rDestinationURI,
+    bool bOverwrite,
+    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 OUString & rSourcePath,
+    const OUString & rDestinationURI,
+    bool bOverwrite,
+    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_DELETE,
+                                   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 )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 );
+}
+
+void DAVResourceAccess::UNLOCK(
+    const uno::Reference< ucb::XCommandEnvironment > & xEnv )
+{
+    initialize();
+
+    int errorCount = 0;
+    bool bRetry;
+    do
+    {
+        bRetry = false;
+        try
+        {
+            DAVRequestHeaders aHeaders;
+            getUserRequestHeaders( xEnv,
+                                   getRequestURI(),
+                                   ucb::WebDAVHTTPMethod_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 OUString & rNewURL )
+{
+    osl::Guard< osl::Mutex > aGuard( m_aMutex );
+    m_aURL  = rNewURL;
+    m_aPath.clear(); // Next initialize() will create new session.
+}
+
+
+// init dav session and path
+void DAVResourceAccess::initialize()
+{
+    osl::Guard< osl::Mutex > aGuard( m_aMutex );
+    if ( m_aPath.isEmpty() )
+    {
+        SerfUri aURI( m_aURL );
+        OUString aPath( aURI.GetPath() );
+
+        /* #134089# - Check URI */
+        if ( aPath.isEmpty() )
+            throw DAVException( DAVException::DAV_INVALID_ARG );
+
+        /* #134089# - Check URI */
+        if ( aURI.GetHost().isEmpty() )
+            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_xContext );
+
+            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 OUString & DAVResourceAccess::getRequestURI() const
+{
+    SAL_WARN_IF( !m_xSession.is(), "ucb.ucp.webdav",
+                "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 OUString & rURI,
+    ucb::WebDAVHTTPMethod eMethod,
+    DAVRequestHeaders & rRequestHeaders )
+{
+    if ( !xEnv.is() )
+        return;
+
+    uno::Reference< ucb::XWebDAVCommandEnvironment > xDAVEnv(
+        xEnv, uno::UNO_QUERY );
+
+    if ( !xDAVEnv.is() )
+        return;
+
+    uno::Sequence< beans::StringPair > aRequestHeaders
+        = xDAVEnv->getUserRequestHeaders( rURI, eMethod );
+
+    for ( sal_Int32 n = 0; n < aRequestHeaders.getLength(); ++n )
+    {
+        rRequestHeaders.push_back(
+            DAVRequestHeader( aRequestHeaders[ n ].First,
+                              aRequestHeaders[ n ].Second ) );
+    }
+}
+
+
+bool DAVResourceAccess::detectRedirectCycle(
+                                const OUString& rRedirectURL )
+{
+    osl::Guard< osl::Mutex > aGuard( m_aMutex );
+
+    SerfUri aUri( rRedirectURL );
+
+    return std::any_of(m_aRedirectURIs.begin(), m_aRedirectURIs.end(),
+        [&aUri](const SerfUri& rUri) { return aUri == rUri; });
+}
+
+
+void DAVResourceAccess::resetUri()
+{
+    osl::Guard< osl::Mutex > aGuard( m_aMutex );
+    if ( ! m_aRedirectURIs.empty() )
+    {
+        std::vector< SerfUri >::const_iterator it  = m_aRedirectURIs.begin();
+
+        SerfUri aUri( *it );
+        m_aRedirectURIs.clear();
+        setURL ( aUri.GetURI() );
+        initialize();
+    }
+}
+
+
+bool DAVResourceAccess::handleException( DAVException & e, int errorCount )
+{
+    switch ( e.getError() )
+    {
+    case DAVException::DAV_HTTP_REDIRECT:
+        if ( !detectRedirectCycle( e.getData() ) )
+        {
+            // set new URL and path.
+            setURL( e.getData() );
+            initialize();
+            return true;
+        }
+        return 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 ||
+               e.getStatus() == 413 ) &&
+             errorCount < 3 )
+        {
+            return true;
+        }
+        return false;
+    // <--
+    // --> tkr: if connection has said retry then retry!
+    case DAVException::DAV_HTTP_RETRY:
+        return true;
+    // <--
+    default:
+        return false; // Abort
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx 
b/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
new file mode 100644
index 000000000000..b5c521fb414e
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#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 <com/sun/star/ucb/WebDAVHTTPMethod.hpp>
+#include "DAVAuthListener.hxx"
+#include "DAVException.hxx"
+#include "DAVSession.hxx"
+#include "DAVResource.hxx"
+#include "DAVTypes.hxx"
+#include "SerfUri.hxx"
+
+namespace http_dav_ucp
+{
+
+class DAVSessionFactory;
+
+class DAVResourceAccess
+{
+    osl::Mutex    m_aMutex;
+    OUString m_aURL;
+    OUString m_aPath;
+    rtl::Reference< DAVSession > m_xSession;
+    rtl::Reference< DAVSessionFactory > m_xSessionFactory;
+    css::uno::Reference< css::uno::XComponentContext > m_xContext;
+    std::vector< SerfUri > m_aRedirectURIs;
+
+public:
+    DAVResourceAccess() = default;
+    DAVResourceAccess( const css::uno::Reference< css::uno::XComponentContext 
> & rContext,
+                       rtl::Reference< DAVSessionFactory > const & 
rSessionFactory,
+                       const OUString & rURL );
+    DAVResourceAccess( const DAVResourceAccess & rOther );
+
+    DAVResourceAccess & operator=( const DAVResourceAccess & rOther );
+
+    /// @throws DAVException
+    void setURL( const OUString & rNewURL );
+
+    void resetUri();
+
+    const OUString & getURL() const { return m_aURL; }
+
+    rtl::Reference< DAVSessionFactory > getSessionFactory() const
+    { return m_xSessionFactory; }
+
+    // DAV methods
+
+
+    // allprop & named
+    /// @throws DAVException
+    void
+    PROPFIND( const Depth nDepth,
+              const std::vector< OUString > & rPropertyNames,
+              std::vector< DAVResource > & rResources,
+              const css::uno::Reference< css::ucb::XCommandEnvironment > & 
xEnv );
+
+    // propnames
+    /// @throws DAVException
+    void
+    PROPFIND( const Depth nDepth,
+              std::vector< DAVResourceInfo > & rResInfo,
+              const css::uno::Reference< css::ucb::XCommandEnvironment > & 
xEnv );
+
+    /// @throws DAVException
+    void
+    PROPPATCH( const std::vector< ProppatchValue > & rValues,
+               const css::uno::Reference< css::ucb::XCommandEnvironment >& 
xEnv );
+
+    /// @throws DAVException
+    void
+    HEAD( const std::vector< OUString > & rHeaderNames, // empty == 'all'
+          DAVResource & rResource,
+          const css::uno::Reference< css::ucb::XCommandEnvironment >& xEnv );
+
+    /// @throws DAVException
+    css::uno::Reference< css::io::XInputStream >
+    GET( const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    void
+    GET( css::uno::Reference< css::io::XOutputStream > & rStream,
+         const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    css::uno::Reference< css::io::XInputStream >
+    GET( const std::vector< OUString > & rHeaderNames, // empty == 'all'
+         DAVResource & rResource,
+         const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    css::uno::Reference< css::io::XInputStream >
+    GET( DAVRequestHeaders & rRequestHeaders,
+         const std::vector< OUString > & rHeaderNames, // empty == 'all'
+         DAVResource & rResource,
+         const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    void
+    GET( css::uno::Reference< css::io::XOutputStream > & rStream,
+         const std::vector< OUString > & rHeaderNames, // empty == 'all'
+         DAVResource & rResource,
+         const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    void
+    PUT( const css::uno::Reference< css::io::XInputStream > & rStream,
+         const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    css::uno::Reference< css::io::XInputStream >
+    POST( const OUString & rContentType,
+          const OUString & rReferer,
+          const css::uno::Reference< css::io::XInputStream > & rInputStream,
+          const css::uno::Reference< css::ucb::XCommandEnvironment >& xEnv );
+
+    /// @throws DAVException
+    void
+    POST( const OUString & rContentType,
+          const OUString & rReferer,
+          const css::uno::Reference< css::io::XInputStream > & rInputStream,
+          css::uno::Reference< css::io::XOutputStream > & rOutputStream,
+          const css::uno::Reference< css::ucb::XCommandEnvironment >& xEnv );
+
+    /// @throws DAVException
+    void
+    MKCOL( const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    void
+    COPY( const OUString & rSourcePath,
+          const OUString & rDestinationURI,
+          bool bOverwrite,
+          const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    void
+    MOVE( const OUString & rSourcePath,
+          const OUString & rDestinationURI,
+          bool bOverwrite,
+          const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    void
+    DESTROY( const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv 
);
+
+    // set new lock.
+    /// @throws DAVException
+    void
+    LOCK( css::ucb::Lock & inLock,
+          const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv );
+
+    /// @throws DAVException
+    void
+    UNLOCK( const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv 
);
+
+    /// @throws DAVException
+    void
+    static abort();
+
+    // helper
+    static void
+    getUserRequestHeaders(
+        const css::uno::Reference< css::ucb::XCommandEnvironment > & xEnv,
+        const OUString & rURI,
+        css::ucb::WebDAVHTTPMethod eMethod,
+        DAVRequestHeaders & rRequestHeaders );
+
+private:
+    const OUString & getRequestURI() const;
+    /// @throws DAVException
+    bool detectRedirectCycle( const OUString& rRedirectURL );
+    /// @throws DAVException
+    bool handleException( DAVException & e, int errorCount );
+    /// @throws DAVException
+    void initialize();
+};
+
+} // namespace http_dav_ucp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ucb/source/ucp/webdav-curl/DAVSession.hxx 
b/ucb/source/ucp/webdav-curl/DAVSession.hxx
new file mode 100644
index 000000000000..8289d052dc90
--- /dev/null
+++ b/ucb/source/ucp/webdav-curl/DAVSession.hxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#pragma once
+
+#include <memory>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include "DAVResource.hxx"
+#include "DAVSessionFactory.hxx"
+#include "DAVTypes.hxx"
+#include "DAVRequestEnvironment.hxx"
+
+namespace com::sun::star::ucb {
+    struct Lock;
+}
+
+namespace http_dav_ucp
+{
+
+class DAVAuthListener;
+
+class DAVSession
+{
+public:
+    void acquire()
+    {
+        osl_atomic_increment( &m_nRefCount );
+    }
+
+    void release()
+    {
+        if ( osl_atomic_decrement( &m_nRefCount ) == 0 )
+        {
+            m_xFactory->releaseElement( this );
+            delete this;
+        }
+    }
+
+    virtual bool CanUse( const OUString & inPath ) = 0;
+
+    virtual bool UsesProxy() = 0;
+
+    // DAV methods
+
+
+    // NOT USED
+    /*
+    virtual void OPTIONS( const OUString & inPath,
+                          DAVCapabilities & outCapabilities,
+                          const DAVRequestEnvironment & rEnv )
+        throw( DAVException ) = 0;
+    */
+
+    // allprop & named
+    /// @throws DAVException
+    virtual void PROPFIND( const OUString & inPath,
+                           const Depth inDepth,
+                           const std::vector< OUString > & inPropertyNames,
+                           std::vector< DAVResource > & ioResources,

... etc. - the rest is truncated

Reply via email to