ucb/source/ucp/webdav-curl/CurlSession.cxx |   57 +++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

New commits:
commit 27fb4efea57881d49e9598e84b4a1df6a6e8719a
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Oct 19 14:27:04 2022 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Mar 8 16:24:36 2024 +0100

    ucb: webdav-curl: add a shared cookie store
    
    Change-Id: I8796aa7de6335c57818aa570a55fdc64d85bd9f9
    (cherry picked from commit 7e8b26560020ae2819cfd621b5790e51083b7e92)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164552
    Tested-by: Jenkins
    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 342ba3669699..61c54cba2df8 100644
--- a/ucb/source/ucp/webdav-curl/CurlSession.cxx
+++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx
@@ -49,6 +49,9 @@ using namespace ::com::sun::star;
 
 namespace
 {
+void lock_cb(CURL*, curl_lock_data, curl_lock_access, void*);
+void unlock_cb(CURL*, curl_lock_data, curl_lock_access, void*);
+
 /// globals container
 struct Init
 {
@@ -56,17 +59,69 @@ struct Init
     ///       so don't call LockStore with m_Mutex held to prevent deadlock.
     ::http_dav_ucp::SerfLockStore LockStore;
 
+    /// libcurl shared data - to store cookies beyond one connection
+    ::std::mutex ShareLock[CURL_LOCK_DATA_LAST];
+    ::std::unique_ptr<CURLSH, http_dav_ucp::deleter_from_fn<CURLSH, 
curl_share_cleanup>> pShare;
+
     Init()
     {
         if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
         {
             assert(!"curl_global_init failed");
+            ::std::abort(); // can't handle error here
+        }
+        pShare.reset(curl_share_init());
+        if (!pShare)
+        {
+            assert(!"curl_share_init failed");
+            ::std::abort(); // can't handle error here
+        }
+        CURLSHcode sh = curl_share_setopt(pShare.get(), CURLSHOPT_LOCKFUNC, 
lock_cb);
+        if (sh != CURLSHE_OK)
+        {
+            assert(!"curl_share_setopt failed");
+            ::std::abort(); // can't handle error here
+        }
+        sh = curl_share_setopt(pShare.get(), CURLSHOPT_UNLOCKFUNC, unlock_cb);
+        if (sh != CURLSHE_OK)
+        {
+            assert(!"curl_share_setopt failed");
+            ::std::abort(); // can't handle error here
+        }
+        sh = curl_share_setopt(pShare.get(), CURLSHOPT_SHARE, 
CURL_LOCK_DATA_COOKIE);
+        if (sh != CURLSHE_OK)
+        {
+            assert(!"curl_share_setopt failed");
+            ::std::abort(); // can't handle error here
         }
     }
     // do not call curl_global_cleanup() - this is not the only client of curl
 };
 Init g_Init;
 
+// global callbacks
+
+void lock_cb(CURL* /*handle*/, curl_lock_data const data, curl_lock_access 
/*access*/,
+             void* /*userptr*/)
+{
+    assert(0 <= data && data < CURL_LOCK_DATA_LAST);
+    try
+    {
+        g_Init.ShareLock[data].lock();
+    }
+    catch (std::exception const&)
+    {
+        ::std::abort();
+    }
+}
+
+void unlock_cb(CURL* /*handle*/, curl_lock_data const data, curl_lock_access 
/*access*/,
+               void* /*userptr*/)
+{
+    assert(0 <= data && data < CURL_LOCK_DATA_LAST);
+    g_Init.ShareLock[data].unlock();
+}
+
 struct ResponseHeaders
 {
     ::std::vector<::std::pair<::std::vector<OString>, ::std::optional<long>>> 
HeaderFields;
@@ -673,6 +728,8 @@ 
CurlSession::CurlSession(uno::Reference<uno::XComponentContext> xContext,
         assert(rc == CURLE_OK);
 #endif
     }
+    rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_SHARE, g_Init.pShare.get());
+    assert(rc == CURLE_OK);
     // set this initially, may be overwritten during authentication
     rc = curl_easy_setopt(m_pCurl.get(), CURLOPT_HTTPAUTH, CURLAUTH_ANY);
     assert(rc == CURLE_OK); // ANY is always available

Reply via email to