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