ucb/source/ucp/webdav-curl/CurlSession.cxx       |   17 +++++++++++++++--
 ucb/source/ucp/webdav-curl/CurlSession.hxx       |    6 +++++-
 ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx |   11 +++++++++--
 ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx |    5 +++++
 ucb/source/ucp/webdav-curl/DAVSession.hxx        |    7 ++++++-
 ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx |    7 ++++---
 ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx |   12 +++++++++---
 ucb/source/ucp/webdav-curl/webdavcontent.cxx     |   21 +++++++++++++++++----
 ucb/source/ucp/webdav-curl/webdavcontent.hxx     |    4 ++--
 9 files changed, 72 insertions(+), 18 deletions(-)

New commits:
commit d80ad1370b65987505fd5aedd3ac17ff8b1ee0ed
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Oct 6 15:40:57 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Nov 1 18:20:33 2021 +0100

    ucb: webdav-curl: add OpenCommandArg3 "KeepAlive" support
    
    This is based on the following commits, which conflict everywhere,
    except the code in CurlSession.* is new.
    
    commit 09954fc863c8ee900f157cab4458e1dcf51493d3
    Author:     Thorsten Behrens <tbehr...@suse.com>
    AuthorDate: Tue Jan 17 04:59:56 2012 +0100
    
        Fix UpdateCheck clog up server by keeping connection alive
    
        The update check protocol uses the webdav ucp, which uses neon,
        which in turn defaults to keeping the connection alive. this is nice
        for webdav, but disastrous for millions of clients phoning home to
        the same server.
    
        Using neon directly in updatefeed.cxx is not an option, due to the
        thread safety problems around that (see e.g. rhbz#544619) - so we
        had to extend it to accept connection options, and reuse the
        existing webdav provider.
    
    commit 29bd62fdc2792e215999e9dd0ec9a4bf1102201d
    Author:     Thorsten Behrens <tbehr...@suse.com>
    AuthorDate: Tue Jan 17 11:41:14 2012 +0100
    
        Switch flag sequence of OpenCommandArg3 to NamedValue.
    
        Based on feedback for 09954fc863c8ee900f157cab4458e1dcf51493d3,
        using the less-bulky NamedValue type instead of PropertyValue.
    
    Change-Id: I48e07dd4c3f189eb4445ed95a67011131d7b49f9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123174
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx 
b/ucb/source/ucp/webdav-curl/CurlSession.cxx
index 2374ccbc26f2..6605ffc4f9ac 100644
--- a/ucb/source/ucp/webdav-curl/CurlSession.cxx
+++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx
@@ -18,6 +18,7 @@
 
 #include <officecfg/Inet.hxx>
 
+#include <com/sun/star/beans/NamedValue.hpp>
 #include <com/sun/star/io/Pipe.hpp>
 #include <com/sun/star/io/SequenceInputStream.hpp>
 #include <com/sun/star/io/SequenceOutputStream.hpp>
@@ -433,9 +434,11 @@ static auto ExtractRealm(ResponseHeaders const& rHeaders, 
char const* const pAut
 
 CurlSession::CurlSession(uno::Reference<uno::XComponentContext> const& 
xContext,
                          ::rtl::Reference<DAVSessionFactory> const& rpFactory, 
OUString const& rURI,
+                         uno::Sequence<beans::NamedValue> const& rFlags,
                          ::ucbhelper::InternetProxyDecider const& 
rProxyDecider)
     : DAVSession(rpFactory)
     , m_xContext(xContext)
+    , m_Flags(rFlags)
     , m_URI(rURI)
     , m_Proxy(rProxyDecider.getProxy(m_URI.GetScheme(), m_URI.GetHost(), 
m_URI.GetPort()))
 {
@@ -533,18 +536,28 @@ 
CurlSession::CurlSession(uno::Reference<uno::XComponentContext> const& xContext,
         rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_PROXYAUTH, CURLAUTH_ANY);
         assert(rc == CURLE_OK); // ANY is always available
     }
+    auto const it(::std::find_if(m_Flags.begin(), m_Flags.end(),
+                                 [](auto const& rFlag) { return rFlag.Name == 
"KeepAlive"; }));
+    if (it != m_Flags.end() && it->Value.get<bool>())
+    {
+        // neon would close the connection from ne_end_request(), this seems
+        // to be the equivalent and not CURLOPT_TCP_KEEPALIVE
+        rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_FORBID_REUSE, 1L);
+        assert(rc == CURLE_OK);
+    }
 }
 
 CurlSession::~CurlSession() {}
 
-auto CurlSession::CanUse(OUString const& rURI) -> bool
+auto CurlSession::CanUse(OUString const& rURI, 
uno::Sequence<beans::NamedValue> const& rFlags)
+    -> bool
 {
     try
     {
         CurlUri const uri(rURI);
 
         return m_URI.GetScheme() == uri.GetScheme() && m_URI.GetHost() == 
uri.GetHost()
-               && m_URI.GetPort() == uri.GetPort();
+               && m_URI.GetPort() == uri.GetPort() && m_Flags == rFlags;
     }
     catch (DAVException const&)
     {
diff --git a/ucb/source/ucp/webdav-curl/CurlSession.hxx 
b/ucb/source/ucp/webdav-curl/CurlSession.hxx
index 4c33c795d940..e7e566c0fe99 100644
--- a/ucb/source/ucp/webdav-curl/CurlSession.hxx
+++ b/ucb/source/ucp/webdav-curl/CurlSession.hxx
@@ -25,6 +25,8 @@ private:
     /// mutex required to access all other non-const members
     ::std::mutex m_Mutex;
     css::uno::Reference<css::uno::XComponentContext> const m_xContext;
+    /// flags may be passed to constructor, e.g. "KeepAlive"
+    css::uno::Sequence<css::beans::NamedValue> const m_Flags;
     CurlUri const m_URI;
     /// buffer for libcurl detailed error messages
     char m_ErrorBuffer[CURL_ERROR_SIZE];
@@ -43,10 +45,12 @@ private:
 public:
     explicit CurlSession(css::uno::Reference<css::uno::XComponentContext> 
const& xContext,
                          ::rtl::Reference<DAVSessionFactory> const& rpFactory, 
OUString const& rURI,
+                         css::uno::Sequence<css::beans::NamedValue> const& 
rFlags,
                          ::ucbhelper::InternetProxyDecider const& 
rProxyDecider);
     virtual ~CurlSession() override;
 
-    virtual auto CanUse(OUString const& rURI) -> bool override;
+    virtual auto CanUse(OUString const& rURI,
+                        css::uno::Sequence<css::beans::NamedValue> const& 
rFlags) -> bool override;
 
     virtual auto UsesProxy() -> bool override;
 
diff --git a/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx 
b/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
index 3ac379c9da70..34c3429f3bf3 100644
--- a/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
+++ b/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
@@ -136,6 +136,7 @@ DAVResourceAccess::DAVResourceAccess(
 DAVResourceAccess::DAVResourceAccess( const DAVResourceAccess & rOther )
 : m_aURL( rOther.m_aURL ),
   m_aPath( rOther.m_aPath ),
+  m_aFlags( rOther.m_aFlags ),
   m_xSession( rOther.m_xSession ),
   m_xSessionFactory( rOther.m_xSessionFactory ),
   m_xContext( rOther.m_xContext ),
@@ -149,6 +150,7 @@ DAVResourceAccess & DAVResourceAccess::operator=(
 {
     m_aURL            = rOther.m_aURL;
     m_aPath           = rOther.m_aPath;
+    m_aFlags          = rOther.m_aFlags;
     m_xSession        = rOther.m_xSession;
     m_xSessionFactory = rOther.m_xSessionFactory;
     m_xContext           = rOther.m_xContext;
@@ -960,6 +962,11 @@ void DAVResourceAccess::UNLOCK(
     while ( bRetry );
 }
 
+void DAVResourceAccess::setFlags( const uno::Sequence< beans::NamedValue >& 
rFlags )
+{
+    osl::Guard< osl::Mutex > aGuard( m_aMutex );
+    m_aFlags = rFlags;
+}
 
 void DAVResourceAccess::setURL( const OUString & rNewURL )
 {
@@ -986,13 +993,13 @@ void DAVResourceAccess::initialize()
         if ( aURI.GetHost().isEmpty() )
             throw DAVException( DAVException::DAV_INVALID_ARG );
 
-        if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL ) )
+        if ( !m_xSession.is() || !m_xSession->CanUse( m_aURL, m_aFlags ) )
         {
             m_xSession.clear();
 
             // create new webdav session
             m_xSession
-                = m_xSessionFactory->createDAVSession( m_aURL, m_xContext );
+                = m_xSessionFactory->createDAVSession( m_aURL, m_aFlags, 
m_xContext );
 
             if ( !m_xSession.is() )
                 return;
diff --git a/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx 
b/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
index 639e22e29611..1fce8d1377dd 100644
--- a/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
+++ b/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
@@ -26,6 +26,7 @@
 #include <osl/mutex.hxx>
 #include <com/sun/star/io/XInputStream.hpp>
 #include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
 #include <com/sun/star/ucb/Lock.hpp>
 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
 #include <com/sun/star/ucb/WebDAVHTTPMethod.hpp>
@@ -46,6 +47,7 @@ class DAVResourceAccess
     osl::Mutex    m_aMutex;
     OUString m_aURL;
     OUString m_aPath;
+    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > 
m_aFlags;
     rtl::Reference< DAVSession > m_xSession;
     rtl::Reference< DAVSessionFactory > m_xSessionFactory;
     css::uno::Reference< css::uno::XComponentContext > m_xContext;
@@ -60,6 +62,9 @@ public:
 
     DAVResourceAccess & operator=( const DAVResourceAccess & rOther );
 
+    /// @throws DAVException
+    void setFlags( const ::com::sun::star::uno::Sequence< 
::com::sun::star::beans::NamedValue >& rFlags );
+
     /// @throws DAVException
     void setURL( const OUString & rNewURL );
 
diff --git a/ucb/source/ucp/webdav-curl/DAVSession.hxx 
b/ucb/source/ucp/webdav-curl/DAVSession.hxx
index d5e8e4ad0a57..88a41ab3153f 100644
--- a/ucb/source/ucp/webdav-curl/DAVSession.hxx
+++ b/ucb/source/ucp/webdav-curl/DAVSession.hxx
@@ -29,6 +29,10 @@
 #include "DAVTypes.hxx"
 #include "DAVRequestEnvironment.hxx"
 
+namespace com { namespace sun { namespace star { namespace beans {
+    struct NamedValue;
+} } } }
+
 namespace com::sun::star::ucb {
     struct Lock;
 }
@@ -55,7 +59,8 @@ public:
         }
     }
 
-    virtual bool CanUse( const OUString & rURI ) = 0;
+    virtual bool CanUse( const OUString & rURI,
+            const 
::com::sun::star::uno::Sequence<::com::sun::star::beans::NamedValue>& rFlags ) 
= 0;
 
     virtual bool UsesProxy() = 0;
 
diff --git a/ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx 
b/ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx
index 25113e2eb2a7..bbb7a48bcf0a 100644
--- a/ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx
+++ b/ucb/source/ucp/webdav-curl/DAVSessionFactory.cxx
@@ -31,6 +31,7 @@ DAVSessionFactory::~DAVSessionFactory()
 
 rtl::Reference< DAVSession > DAVSessionFactory::createDAVSession(
                 const OUString & inUri,
+                const uno::Sequence< beans::NamedValue >& rFlags,
                 const uno::Reference< uno::XComponentContext > & rxContext )
 {
     osl::MutexGuard aGuard( m_aMutex );
@@ -39,14 +40,14 @@ rtl::Reference< DAVSession > 
DAVSessionFactory::createDAVSession(
         m_xProxyDecider.reset( new ucbhelper::InternetProxyDecider( rxContext 
) );
 
     Map::iterator aIt = std::find_if(m_aMap.begin(), m_aMap.end(),
-        [&inUri](const Map::value_type& rEntry) { return 
rEntry.second->CanUse( inUri ); });
+        [&inUri, &rFlags](const Map::value_type& rEntry) { return 
rEntry.second->CanUse( inUri, rFlags ); });
 
     if ( aIt == m_aMap.end() )
     {
         CurlUri const aURI( inUri );
 
         std::unique_ptr< DAVSession > xElement(
-            new CurlSession(rxContext, this, inUri, *m_xProxyDecider) );
+            new CurlSession(rxContext, this, inUri, rFlags, *m_xProxyDecider) 
);
 
         aIt = m_aMap.emplace(  inUri, xElement.get() ).first;
         aIt->second->m_aContainerIt = aIt;
@@ -69,7 +70,7 @@ rtl::Reference< DAVSession > 
DAVSessionFactory::createDAVSession(
         // call a little:
         CurlUri const aURI( inUri );
 
-        aIt->second = new CurlSession(rxContext, this, inUri, 
*m_xProxyDecider);
+        aIt->second = new CurlSession(rxContext, this, inUri, rFlags, 
*m_xProxyDecider);
         aIt->second->m_aContainerIt = aIt;
         return aIt->second;
     }
diff --git a/ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx 
b/ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx
index 4b932ea6d2f4..b0d426f43bf3 100644
--- a/ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx
+++ b/ucb/source/ucp/webdav-curl/DAVSessionFactory.hxx
@@ -32,6 +32,11 @@
 
 using namespace com::sun::star;
 
+namespace com::sun::star::beans
+{
+struct NamedValue;
+}
+
 namespace com::sun::star::lang
 {
 class XMultiServiceFactory;
@@ -47,9 +52,10 @@ public:
     virtual ~DAVSessionFactory() override;
 
     /// @throws DAVException
-    rtl::Reference<DAVSession>
-    createDAVSession(const OUString& inUri,
-                     const css::uno::Reference<css::uno::XComponentContext>& 
rxContext);
+    rtl::Reference<DAVSession> createDAVSession(
+        const OUString& inUri,
+        const 
::com::sun::star::uno::Sequence<::com::sun::star::beans::NamedValue>& rFlags,
+        const css::uno::Reference<css::uno::XComponentContext>& rxContext);
 
 private:
     typedef std::map<OUString, DAVSession*> Map;
diff --git a/ucb/source/ucp/webdav-curl/webdavcontent.cxx 
b/ucb/source/ucp/webdav-curl/webdavcontent.cxx
index 058a22646c1f..f001c442ab4c 100644
--- a/ucb/source/ucp/webdav-curl/webdavcontent.cxx
+++ b/ucb/source/ucp/webdav-curl/webdavcontent.cxx
@@ -60,7 +60,7 @@
 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
 #include <com/sun/star/ucb/NameClash.hpp>
 #include <com/sun/star/ucb/NameClashException.hpp>
-#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument3.hpp>
 #include <com/sun/star/ucb/OpenMode.hpp>
 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
 #include <com/sun/star/ucb/PropertyCommandArgument.hpp>
@@ -514,8 +514,9 @@ uno::Any SAL_CALL Content::execute(
         // open
 
 
-        ucb::OpenCommandArgument2 aOpenCommand;
-        if ( !( aCommand.Argument >>= aOpenCommand ) )
+        ucb::OpenCommandArgument3 aOpenCommand;
+        ucb::OpenCommandArgument2 aTmp;
+        if ( !( aCommand.Argument >>= aTmp ) )
         {
             ucbhelper::cancelCommandExecution(
                 uno::makeAny( lang::IllegalArgumentException(
@@ -525,6 +526,15 @@ uno::Any SAL_CALL Content::execute(
                 Environment );
             // Unreachable
         }
+        if ( !( aCommand.Argument >>= aOpenCommand ) )
+        {
+            // compat mode, extract Arg2 info into newer structure
+            aOpenCommand.Mode = aTmp.Mode;
+            aOpenCommand.Priority = aTmp.Priority;
+            aOpenCommand.Sink = aTmp.Sink;
+            aOpenCommand.Properties = aTmp.Properties;
+            aOpenCommand.SortingInfo = aTmp.SortingInfo;
+        }
 
         aRet = open( aOpenCommand, Environment );
 
@@ -1964,7 +1974,7 @@ uno::Sequence< uno::Any > Content::setPropertyValues(
 
 
 uno::Any Content::open(
-                const ucb::OpenCommandArgument2 & rArg,
+                const ucb::OpenCommandArgument3 & rArg,
                 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
 {
     uno::Any aRet;
@@ -2030,6 +2040,7 @@ uno::Any Content::open(
                         new DAVResourceAccess( *m_xResAccess ) );
                 }
 
+                xResAccess->setFlags( rArg.OpeningFlags );
                 DAVResource aResource;
                 std::vector< OUString > aHeaders;
 
@@ -2072,6 +2083,8 @@ uno::Any Content::open(
                             new DAVResourceAccess( *m_xResAccess ) );
                     }
 
+                    xResAccess->setFlags( rArg.OpeningFlags );
+
                     // fill inputstream sync; return if all data present
                     DAVResource aResource;
                     std::vector< OUString > aHeaders;
diff --git a/ucb/source/ucp/webdav-curl/webdavcontent.hxx 
b/ucb/source/ucp/webdav-curl/webdavcontent.hxx
index 5aabca16522f..dc1a93cbac97 100644
--- a/ucb/source/ucp/webdav-curl/webdavcontent.hxx
+++ b/ucb/source/ucp/webdav-curl/webdavcontent.hxx
@@ -43,7 +43,7 @@ namespace com::sun::star::sdbc {
 }
 
 namespace com::sun::star::ucb {
-    struct OpenCommandArgument2;
+    struct OpenCommandArgument3;
     struct PropertyCommandArgument;
     struct PostCommandArgument2;
     struct TransferInfo;
@@ -125,7 +125,7 @@ private:
     // Command "open"
     /// @throws css::uno::Exception
     css::uno::Any open(
-                const css::ucb::OpenCommandArgument2 & rArg,
+                const css::ucb::OpenCommandArgument3 & rArg,
                 const css::uno::Reference<
                     css::ucb::XCommandEnvironment > & xEnv );
 

Reply via email to