lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx |  235 
++++------
 lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx |   10 
 2 files changed, 110 insertions(+), 135 deletions(-)

New commits:
commit e35905c1b295ff4f1f03e845e8849bc8400cd952
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Mar 4 19:47:42 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Mar 4 17:59:56 2023 +0000

    Set useragent for requests to LanguageTool server
    
    Use the same string that is used in CurlSession
    
    Change-Id: Ia383f2490cf484715f429df09ec80603ca3f9387
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148251
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx 
b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
index 510539966e2e..4ad7c1388ea7 100644
--- a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
+++ b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
@@ -17,6 +17,10 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <sal/config.h>
+
+#include <config_version.h>
+
 #include <cppuhelper/factory.hxx>
 #include <cppuhelper/supportsservice.hxx>
 #include <cppuhelper/weak.hxx>
@@ -120,6 +124,15 @@ std::string makeHttpRequest_impl(std::string_view aURL, 
HTTP_METHOD method,
     if (!curl)
         return {}; // empty string
 
+    // Same useragent string as in CurlSession 
(ucp/webdav-curl/CurlSession.cxx)
+    curl_version_info_data const* const 
pVersion(curl_version_info(CURLVERSION_NOW));
+    assert(pVersion);
+    OString const useragent(
+        OString::Concat("LibreOffice " LIBO_VERSION_DOTTED " 
denylistedbackend/")
+        + ::std::string_view(pVersion->version, strlen(pVersion->version)) + " 
"
+        + pVersion->ssl_version);
+    (void)curl_easy_setopt(curl.get(), CURLOPT_USERAGENT, useragent.getStr());
+
     (void)curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, pHttpHeader);
     (void)curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L);
     (void)curl_easy_setopt(curl.get(), CURLOPT_URL, aURL.data());
commit 5a87ff41ef784d6390da0df49b60186c21047112
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Mar 4 19:44:50 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Mar 4 17:59:49 2023 +0000

    Restructure and deduplicate the code
    
    Change-Id: Ib8701cbfbe0a025e19c34f0b52e0f67bf728f636
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148250
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx 
b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
index a153e7ac5ef0..510539966e2e 100644
--- a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
+++ b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
@@ -92,6 +92,102 @@ OString encodeTextForLanguageTool(const OUString& text)
         rtl::Uri::encode(text, myCharClass.data(), rtl_UriEncodeStrict, 
RTL_TEXTENCODING_UTF8),
         RTL_TEXTENCODING_ASCII_US);
 }
+
+// Callback to get the response data from server.
+size_t WriteCallback(void* ptr, size_t size, size_t nmemb, void* userp)
+{
+    if (!userp)
+        return 0;
+
+    std::string* response = static_cast<std::string*>(userp);
+    size_t real_size = size * nmemb;
+    response->append(static_cast<char*>(ptr), real_size);
+    return real_size;
+}
+
+enum class HTTP_METHOD
+{
+    HTTP_GET,
+    HTTP_POST
+};
+
+std::string makeHttpRequest_impl(std::string_view aURL, HTTP_METHOD method,
+                                 const OString& aPostData, curl_slist* 
pHttpHeader,
+                                 tools::Long& nStatusCode)
+{
+    std::unique_ptr<CURL, std::function<void(CURL*)>> curl(curl_easy_init(),
+                                                           [](CURL* p) { 
curl_easy_cleanup(p); });
+    if (!curl)
+        return {}; // empty string
+
+    (void)curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, pHttpHeader);
+    (void)curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L);
+    (void)curl_easy_setopt(curl.get(), CURLOPT_URL, aURL.data());
+    (void)curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, CURL_TIMEOUT);
+    // (void)curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 1L);
+
+    std::string response_body;
+    (void)curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteCallback);
+    (void)curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response_body);
+
+    SvxLanguageToolOptions& rLanguageOpts = SvxLanguageToolOptions::Get();
+    // allow unknown or self-signed certificates
+    if (rLanguageOpts.getSSLVerification() == false)
+    {
+        (void)curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
+        (void)curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, false);
+    }
+
+    if (method == HTTP_METHOD::HTTP_POST)
+    {
+        (void)curl_easy_setopt(curl.get(), CURLOPT_POST, 1L);
+        (void)curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, 
aPostData.getStr());
+    }
+
+    CURLcode cc = curl_easy_perform(curl.get());
+    if (cc != CURLE_OK)
+    {
+        SAL_WARN("languagetool",
+                 "CURL request returned with error: " << 
static_cast<sal_Int32>(cc));
+    }
+
+    curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &nStatusCode);
+    return response_body;
+}
+
+std::string makeDudenHttpRequest(std::string_view aURL, const OString& 
aPostData,
+                                 tools::Long& nStatusCode)
+{
+    struct curl_slist* pList = nullptr;
+    SvxLanguageToolOptions& rLanguageOpts = SvxLanguageToolOptions::Get();
+    OString sAccessToken = OUStringToOString(rLanguageOpts.getApiKey(), 
RTL_TEXTENCODING_UTF8);
+
+    pList = curl_slist_append(pList, "Cache-Control: no-cache");
+    pList = curl_slist_append(pList, "Content-Type: application/json");
+    if (!sAccessToken.isEmpty())
+    {
+        sAccessToken = "access_token: " + sAccessToken;
+        pList = curl_slist_append(pList, sAccessToken.getStr());
+    }
+
+    return makeHttpRequest_impl(aURL, HTTP_METHOD::HTTP_POST, aPostData, 
pList, nStatusCode);
+}
+
+std::string makeHttpRequest(std::string_view aURL, HTTP_METHOD method, const 
OString& aPostData,
+                            tools::Long& nStatusCode)
+{
+    OString realPostData(aPostData);
+    if (method == HTTP_METHOD::HTTP_POST)
+    {
+        SvxLanguageToolOptions& rLanguageOpts = SvxLanguageToolOptions::Get();
+        OString apiKey = OUStringToOString(rLanguageOpts.getApiKey(), 
RTL_TEXTENCODING_UTF8);
+        OString username = OUStringToOString(rLanguageOpts.getUsername(), 
RTL_TEXTENCODING_UTF8);
+        if (!apiKey.isEmpty() && !username.isEmpty())
+            realPostData += "&username=" + username + "&apiKey=" + apiKey;
+    }
+
+    return makeHttpRequest_impl(aURL, method, realPostData, nullptr, 
nStatusCode);
+}
 }
 
 LanguageToolGrammarChecker::LanguageToolGrammarChecker()
@@ -165,18 +261,6 @@ Sequence<Locale> SAL_CALL 
LanguageToolGrammarChecker::getLocales()
     return m_aSuppLocales;
 }
 
-// Callback to get the response data from server.
-static size_t WriteCallback(void* ptr, size_t size, size_t nmemb, void* userp)
-{
-    if (!userp)
-        return 0;
-
-    std::string* response = static_cast<std::string*>(userp);
-    size_t real_size = size * nmemb;
-    response->append(static_cast<char*>(ptr), real_size);
-    return real_size;
-}
-
 ProofreadingResult SAL_CALL LanguageToolGrammarChecker::doProofreading(
     const OUString& aDocumentIdentifier, const OUString& aText, const Locale& 
aLocale,
     sal_Int32 nStartOfSentencePosition, sal_Int32 
nSuggestedBehindEndOfSentencePosition,
@@ -267,8 +351,7 @@ ProofreadingResult SAL_CALL 
LanguageToolGrammarChecker::doProofreading(
     tools::Long http_code = 0;
     std::string response_body;
     if (rLanguageOpts.getRestProtocol() == sDuden)
-        response_body
-            = makeDudenHttpRequest(checkerURL, HTTP_METHOD::HTTP_POST, 
postData, http_code);
+        response_body = makeDudenHttpRequest(checkerURL, postData, http_code);
     else
         response_body = makeHttpRequest(checkerURL, HTTP_METHOD::HTTP_POST, 
postData, http_code);
 
@@ -421,117 +504,6 @@ void 
LanguageToolGrammarChecker::parseProofreadingJSONResponse(ProofreadingResul
     rResult.aErrors = aErrors;
 }
 
-std::string LanguageToolGrammarChecker::makeDudenHttpRequest(std::string_view 
aURL,
-                                                             HTTP_METHOD 
method,
-                                                             const OString& 
aData,
-                                                             tools::Long& 
nCode)
-{
-    std::unique_ptr<CURL, std::function<void(CURL*)>> curl(curl_easy_init(),
-                                                           [](CURL* p) { 
curl_easy_cleanup(p); });
-    if (!curl)
-        return {}; // empty string
-
-    std::string sResponseBody;
-    struct curl_slist* pList = nullptr;
-    SvxLanguageToolOptions& rLanguageOpts = SvxLanguageToolOptions::Get();
-    OString sAccessToken = OString::Concat("access_token: ")
-                           + OUStringToOString(rLanguageOpts.getApiKey(), 
RTL_TEXTENCODING_UTF8);
-
-    pList = curl_slist_append(pList, "Cache-Control: no-cache");
-    pList = curl_slist_append(pList, "Content-Type: application/json");
-    if (!sAccessToken.isEmpty())
-        pList = curl_slist_append(pList, sAccessToken.getStr());
-
-    (void)curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, pList);
-    (void)curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L);
-    (void)curl_easy_setopt(curl.get(), CURLOPT_URL, aURL.data());
-    (void)curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, CURL_TIMEOUT);
-    (void)curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteCallback);
-    (void)curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, 
static_cast<void*>(&sResponseBody));
-
-    // allow unknown or self-signed certificates
-    if (rLanguageOpts.getSSLVerification() == false)
-    {
-        (void)curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
-        (void)curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, false);
-    }
-
-    if (method == HTTP_METHOD::HTTP_POST)
-    {
-        (void)curl_easy_setopt(curl.get(), CURLOPT_POST, 1L);
-        (void)curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, aData.getStr());
-    }
-
-    CURLcode cc = curl_easy_perform(curl.get());
-    if (cc != CURLE_OK)
-    {
-        SAL_WARN("languagetool",
-                 "CURL request returned with error: " << 
static_cast<sal_Int32>(cc));
-    }
-
-    curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &nCode);
-    return sResponseBody;
-}
-
-std::string LanguageToolGrammarChecker::makeHttpRequest(std::string_view aURL, 
HTTP_METHOD method,
-                                                        const OString& 
aPostData,
-                                                        tools::Long& 
nStatusCode)
-{
-    std::unique_ptr<CURL, std::function<void(CURL*)>> curl(curl_easy_init(),
-                                                           [](CURL* p) { 
curl_easy_cleanup(p); });
-    if (!curl)
-        return {}; // empty string
-
-    bool isPremium = false;
-    SvxLanguageToolOptions& rLanguageOpts = SvxLanguageToolOptions::Get();
-    OString apiKey = OUStringToOString(rLanguageOpts.getApiKey(), 
RTL_TEXTENCODING_UTF8);
-    OString username = OUStringToOString(rLanguageOpts.getUsername(), 
RTL_TEXTENCODING_UTF8);
-    OString premiumPostData;
-    if (!apiKey.isEmpty() && !username.isEmpty())
-    {
-        isPremium = true;
-    }
-
-    std::string response_body;
-    (void)curl_easy_setopt(curl.get(), CURLOPT_URL, aURL.data());
-
-    (void)curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L);
-    // (void)curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 1L);
-
-    (void)curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteCallback);
-    (void)curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, 
static_cast<void*>(&response_body));
-    // allow unknown or self-signed certificates
-    if (rLanguageOpts.getSSLVerification() == false)
-    {
-        (void)curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
-        (void)curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, false);
-    }
-    (void)curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, CURL_TIMEOUT);
-
-    if (method == HTTP_METHOD::HTTP_POST)
-    {
-        (void)curl_easy_setopt(curl.get(), CURLOPT_POST, 1L);
-        if (isPremium == false)
-        {
-            (void)curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, 
aPostData.getStr());
-        }
-        else
-        {
-            premiumPostData = aPostData + "&username=" + username + "&apiKey=" 
+ apiKey;
-            (void)curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, 
premiumPostData.getStr());
-        }
-    }
-
-    CURLcode cc = curl_easy_perform(curl.get());
-    if (cc != CURLE_OK)
-    {
-        SAL_WARN("languagetool",
-                 "CURL request returned with error: " << 
static_cast<sal_Int32>(cc));
-    }
-    curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &nStatusCode);
-    return response_body;
-}
-
 void SAL_CALL LanguageToolGrammarChecker::ignoreRule(const OUString& 
/*aRuleIdentifier*/,
                                                      const Locale& /*aLocale*/
 )
diff --git a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx 
b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx
index 0fc5edf877f0..fd2909d57ae2 100644
--- a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx
+++ b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx
@@ -36,12 +36,6 @@
 #define PROOFREADING_ERROR 2
 #define CURL_TIMEOUT 10L
 
-enum class HTTP_METHOD
-{
-    HTTP_GET,
-    HTTP_POST
-};
-
 class LanguageToolGrammarChecker
     : public cppu::WeakImplHelper<css::linguistic2::XProofreader, 
css::lang::XInitialization,
                                   css::lang::XServiceInfo, 
css::lang::XServiceDisplayName>
@@ -55,10 +49,6 @@ class LanguageToolGrammarChecker
                                    std::string_view aJSONBody);
     static void 
parseProofreadingJSONResponse(css::linguistic2::ProofreadingResult& rResult,
                                               std::string_view aJSONBody);
-    static std::string makeDudenHttpRequest(std::string_view aURL, HTTP_METHOD 
method,
-                                            const OString& aPostData, 
tools::Long& nStatusCode);
-    static std::string makeHttpRequest(std::string_view aURL, HTTP_METHOD 
method,
-                                       const OString& aPostData, tools::Long& 
nStatusCode);
 
 public:
     LanguageToolGrammarChecker();

Reply via email to