cui/source/options/optlanguagetool.cxx                            |    3 
 cui/source/options/optlanguagetool.hxx                            |    3 
 cui/uiconfig/ui/langtoolconfigpage.ui                             |   38 ++++
 lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx |   78 
+++++++++-
 lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx |    3 
 5 files changed, 119 insertions(+), 6 deletions(-)

New commits:
commit 5cd71035842776fec05f1423b9cc1acf33f12a13
Author:     Henry Castro <hcas...@collabora.com>
AuthorDate: Mon Nov 21 21:34:24 2022 -0400
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Sat Jan 28 09:23:18 2023 +0000

    lingucomponent: implement custom request http rest protocol
    
    Request:
    
    POST /api/check HTTP/1.1
    Host: localhost:8099
    Content-Type: application/json
    Cache-Control: no-cache
    
    {
    "dictionaries": [
    "daily",
    "jungblutt"
    ],
    "text-language": "en-DE",
    "property-sets": [
    "base", "daily",
    "culture"
    ],
    "hyphenation": true,
    "spellchecking-level": 1,
    "correction-proposals": true,
    "single-word-mode": false,
    "message-language": "fr-LU",
    "message-level": 1,
    "text": "This is a final throw for the interface to the Duden server."
    }
    
    Signed-off-by: Henry Castro <hcas...@collabora.com>
    Change-Id: I2a288a7c573014d42df03f7cc12c57a7f788750e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143107
    Reviewed-by: Ashod Nakashian <a...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145607
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Tested-by: Andras Timar <andras.ti...@collabora.com>

diff --git a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx 
b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
index 1dce1845fc43..12d39ef8af93 100644
--- a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
+++ b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx
@@ -55,6 +55,8 @@ using namespace linguistic;
 
 #define COL_ORANGE Color(0xD1, 0x68, 0x20)
 
+constexpr OUStringLiteral sDuden = u"duden";
+
 namespace
 {
 Sequence<PropertyValue> lcl_GetLineColorPropertyFromErrorId(const std::string& 
rErrorId)
@@ -226,11 +228,28 @@ ProofreadingResult SAL_CALL 
LanguageToolGrammarChecker::doProofreading(
     }
 
     tools::Long http_code = 0;
+    std::string response_body;
     OUString langTag(aLocale.Language + "-" + aLocale.Country);
-    OString postData(OUStringToOString(Concat2View("text=" + aText + 
"&language=" + langTag),
-                                       RTL_TEXTENCODING_UTF8));
-    const std::string response_body
-        = makeHttpRequest(checkerURL, HTTP_METHOD::HTTP_POST, postData, 
http_code);
+
+    if (rLanguageOpts.getRestProtocol() == sDuden)
+    {
+        std::stringstream aStream;
+        boost::property_tree::ptree aTree;
+        aTree.put("text-language", langTag.toUtf8().getStr());
+        aTree.put("text", aText.toUtf8().getStr());
+        aTree.put("hyphenation", false);
+        aTree.put("spellchecking-level", 3);
+        aTree.put("correction-proposals", true);
+        boost::property_tree::write_json(aStream, aTree);
+        response_body = makeDudenHttpRequest(checkerURL, 
HTTP_METHOD::HTTP_POST,
+                                             aStream.str().c_str(), http_code);
+    }
+    else
+    {
+        OString postData(OUStringToOString(Concat2View("text=" + aText + 
"&language=" + langTag),
+                                           RTL_TEXTENCODING_UTF8));
+        response_body = makeHttpRequest(checkerURL, HTTP_METHOD::HTTP_POST, 
postData, http_code);
+    }
 
     if (http_code != 200)
     {
@@ -317,6 +336,57 @@ 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("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());
+
+    curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, pList);
+    curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L);
+    curl_easy_setopt(curl.get(), CURLOPT_URL, aURL.data());
+    curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, CURL_TIMEOUT);
+    curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, WriteCallback);
+    curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, 
static_cast<void*>(&sResponseBody));
+
+    // allow unknown or self-signed certificates
+    if (rLanguageOpts.getSSLVerification() == false)
+    {
+        curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYPEER, false);
+        curl_easy_setopt(curl.get(), CURLOPT_SSL_VERIFYHOST, false);
+    }
+
+    if (method == HTTP_METHOD::HTTP_POST)
+    {
+        curl_easy_setopt(curl.get(), CURLOPT_POST, 1L);
+        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)
diff --git a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx 
b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx
index 0262be896cd6..c3b79c95a43c 100644
--- a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx
+++ b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx
@@ -53,6 +53,9 @@ class LanguageToolGrammarChecker
     LanguageToolGrammarChecker& operator=(const LanguageToolGrammarChecker&) = 
delete;
     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);
 
commit 7e2ef33d31eba98ded508b749799ce42b5e4f42c
Author:     Henry Castro <hcas...@collabora.com>
AuthorDate: Mon Nov 21 21:30:02 2022 -0400
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Sat Jan 28 09:23:04 2023 +0000

    cui: add entry "RestProtocol" to language tool dialog
    
    Signed-off-by: Henry Castro <hcas...@collabora.com>
    Change-Id: I6511fc2b353c47b1ff537c42d3484b3a42c1b121
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143106
    Reviewed-by: Ashod Nakashian <a...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145606
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>
    Tested-by: Andras Timar <andras.ti...@collabora.com>

diff --git a/cui/source/options/optlanguagetool.cxx 
b/cui/source/options/optlanguagetool.cxx
index f0006d1dd0e0..7a087b09e8c0 100644
--- a/cui/source/options/optlanguagetool.cxx
+++ b/cui/source/options/optlanguagetool.cxx
@@ -30,6 +30,7 @@ 
OptLanguageToolTabPage::OptLanguageToolTabPage(weld::Container* pPage,
     , m_xBaseURLED(m_xBuilder->weld_entry("baseurl"))
     , m_xUsernameED(m_xBuilder->weld_entry("username"))
     , m_xApiKeyED(m_xBuilder->weld_entry("apikey"))
+    , m_xRestProtocol(m_xBuilder->weld_entry("restprotocol"))
     , m_xActivateBox(m_xBuilder->weld_check_button("activate"))
     , m_xSSLDisableVerificationBox(m_xBuilder->weld_check_button("verifyssl"))
     , m_xApiSettingsFrame(m_xBuilder->weld_frame("apisettings"))
@@ -73,6 +74,7 @@ void OptLanguageToolTabPage::Reset(const SfxItemSet*)
 
     m_xUsernameED->set_text(rLanguageOpts.getUsername());
     m_xApiKeyED->set_text(rLanguageOpts.getApiKey());
+    m_xRestProtocol->set_text(rLanguageOpts.getRestProtocol());
     
m_xSSLDisableVerificationBox->set_active(rLanguageOpts.getSSLVerification() != 
true);
 }
 
@@ -89,6 +91,7 @@ bool OptLanguageToolTabPage::FillItemSet(SfxItemSet*)
 
     rLanguageOpts.setUsername(m_xUsernameED->get_text());
     rLanguageOpts.setApiKey(m_xApiKeyED->get_text());
+    rLanguageOpts.setRestProtocol(m_xRestProtocol->get_text());
     
rLanguageOpts.setSSLVerification(m_xSSLDisableVerificationBox->get_active() != 
true);
     return false;
 }
diff --git a/cui/source/options/optlanguagetool.hxx 
b/cui/source/options/optlanguagetool.hxx
index 666512804c62..141d88f63bb4 100644
--- a/cui/source/options/optlanguagetool.hxx
+++ b/cui/source/options/optlanguagetool.hxx
@@ -38,6 +38,7 @@ private:
     std::unique_ptr<weld::Entry> m_xBaseURLED;
     std::unique_ptr<weld::Entry> m_xUsernameED;
     std::unique_ptr<weld::Entry> m_xApiKeyED;
+    std::unique_ptr<weld::Entry> m_xRestProtocol;
     std::unique_ptr<weld::CheckButton> m_xActivateBox;
     std::unique_ptr<weld::CheckButton> m_xSSLDisableVerificationBox;
     std::unique_ptr<weld::Frame> m_xApiSettingsFrame;
@@ -45,4 +46,4 @@ private:
     void EnableControls(bool bEnable);
 
     DECL_LINK(CheckHdl, weld::Toggleable&, void);
-};
\ No newline at end of file
+};
diff --git a/cui/uiconfig/ui/langtoolconfigpage.ui 
b/cui/uiconfig/ui/langtoolconfigpage.ui
index 237040fa76b7..1d7452161998 100644
--- a/cui/uiconfig/ui/langtoolconfigpage.ui
+++ b/cui/uiconfig/ui/langtoolconfigpage.ui
@@ -80,7 +80,7 @@
                       <object class="GtkGrid" id="grid2">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="row_spacing">5</property>
+                        <property name="row_spacing">6</property>
                         <property name="column_spacing">12</property>
                         <child>
                           <object class="GtkLabel" id="base">
@@ -191,6 +191,42 @@
                             <property name="top_attach">5</property>
                           </packing>
                         </child>
+                        <child>
+                          <object class="GtkLabel" id="restlbl">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes" 
context="langtoolconfigpage|restlbl">REST protocol:</property>
+                            <property name="use_underline">True</property>
+                            <property 
name="mnemonic_widget">restprotocol</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">6</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="restprotocol">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">6</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="restdesc">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes" 
context="langtoolconfigpage|restdesc">Your LanguageTool REST API protocol for 
usage.</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">7</property>
+                          </packing>
+                        </child>
                         <child>
                           <placeholder/>
                         </child>

Reply via email to