[Libreoffice-commits] core.git: Branch 'feature/mar-updater' - 2 commits - desktop/source

Markus Mohrhard markus.mohrhard at googlemail.com
Mon Apr 24 22:13:26 UTC 2017


 desktop/source/app/updater.cxx |  113 +++++++++++++++++++++++++++++++++--------
 1 file changed, 92 insertions(+), 21 deletions(-)

New commits:
commit 899754caa036a31dc45e9b79225c0dd882242054
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon Apr 24 23:57:22 2017 +0200

    actually abort the update process if the update file is invalid
    
    Change-Id: I724e50d1e74228f0be00b9b6376c3d074db5c9ed

diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index b4cc9430cfed..dc3a8be802d8 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -287,6 +287,40 @@ class invalid_update_info : public std::exception
 {
 };
 
+class invalid_hash : public std::exception
+{
+    OString maMessage;
+public:
+
+    invalid_hash(const OUString& rExpectedHash, const OUString& rReceivedHash)
+    {
+        OUString aMsg = "Invalid hash found.\nExpected: " + rExpectedHash + ";\nReceived: " + rReceivedHash;
+        maMessage = OUStringToOString(aMsg, RTL_TEXTENCODING_UTF8);
+    }
+
+    const char* what() const noexcept override
+    {
+        return maMessage.getStr();
+    }
+};
+
+class invalid_size : public std::exception
+{
+    OString maMessage;
+public:
+
+    invalid_size(const size_t nExpectedSize, const size_t nReceivedSize)
+    {
+        OUString aMsg = "Invalid file size found.\nExpected: " + OUString::number(nExpectedSize) + ";\nReceived: " + OUString::number(nReceivedSize);
+        maMessage = OUStringToOString(aMsg, RTL_TEXTENCODING_UTF8);
+    }
+
+    const char* what() const noexcept override
+    {
+        return maMessage.getStr();
+    }
+};
+
 OUString toOUString(const std::string& rStr)
 {
     return OUString::fromUtf8(rStr.c_str());
@@ -540,11 +574,13 @@ void download_file(const OUString& rURL, size_t nFileSize, const OUString& rHash
     if (nSize != nFileSize)
     {
         SAL_WARN("desktop.updater", "File sizes don't match. File might be corrupted.");
+        throw invalid_size(nFileSize, nSize);
     }
 
     if (aHash != rHash)
     {
         SAL_WARN("desktop.updater", "File hash don't match. File might be corrupted.");
+        throw invalid_hash(rHash, aHash);
     }
 
     OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/");
@@ -602,6 +638,14 @@ void update_checker()
     {
         SAL_WARN("desktop.updater", "error during the update check");
     }
+    catch (const invalid_size& e)
+    {
+        SAL_WARN("desktop.updater", e.what());
+    }
+    catch (const invalid_hash& e)
+    {
+        SAL_WARN("desktop.updater", e.what());
+    }
     catch (...)
     {
         SAL_WARN("desktop.updater", "unknown error during the update check");
commit ce2401e71108865f587dd11fe0d0a4085d67cb76
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Mon Apr 24 23:25:44 2017 +0200

    actually check the hash of the update files
    
    Change-Id: I98a5f8904a35cb167e87d6c5c11bcf133115cbc1

diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index e1b29d1402ec..b4cc9430cfed 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -31,6 +31,7 @@
 #include <orcus/json_document_tree.hpp>
 #include <orcus/config.hpp>
 #include <orcus/pstring.hpp>
+#include <comphelper/hash.hxx>
 
 namespace {
 
@@ -280,18 +281,6 @@ static size_t WriteCallback(void *ptr, size_t size,
   return real_size;
 }
 
-// Callback to get the response data from server to a file.
-static size_t WriteCallbackFile(void *ptr, size_t size,
-                            size_t nmemb, void *userp)
-{
-  if (!userp)
-    return 0;
-
-  SvStream* response = static_cast<SvStream *>(userp);
-  size_t real_size = size * nmemb;
-  response->WriteBytes(static_cast<char *>(ptr), real_size);
-  return real_size;
-}
 
 
 class invalid_update_info : public std::exception
@@ -408,7 +397,45 @@ update_info parse_response(const std::string& rResponse)
     return aUpdateInfo;
 }
 
-std::string download_content(const OString& rURL, bool bFile)
+struct WriteDataFile
+{
+    comphelper::Hash maHash;
+    SvStream* mpStream;
+
+    WriteDataFile(SvStream* pStream):
+        maHash(comphelper::HashType::SHA512),
+        mpStream(pStream)
+    {
+    }
+
+    OUString getHash()
+    {
+        auto final_hash = maHash.finalize();
+        std::stringstream aStrm;
+        for (auto& i: final_hash)
+        {
+            aStrm << std::setw(2) << std::setfill('0') << std::hex << (int)i;
+        }
+
+        return toOUString(aStrm.str());
+    }
+};
+
+// Callback to get the response data from server to a file.
+size_t WriteCallbackFile(void *ptr, size_t size,
+                            size_t nmemb, void *userp)
+{
+  if (!userp)
+    return 0;
+
+  WriteDataFile* response = static_cast<WriteDataFile *>(userp);
+  size_t real_size = size * nmemb;
+  response->mpStream->WriteBytes(static_cast<char *>(ptr), real_size);
+  response->maHash.update(static_cast<const unsigned char*>(ptr), real_size);
+  return real_size;
+}
+
+std::string download_content(const OString& rURL, bool bFile, OUString& rHash)
 {
     CURL* curl = curl_easy_init();
 
@@ -434,6 +461,7 @@ std::string download_content(const OString& rURL, bool bFile)
 
     std::string response_body;
     utl::TempFile aTempFile;
+    WriteDataFile aFile(aTempFile.GetStream(StreamMode::WRITE));
     if (!bFile)
     {
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
@@ -452,7 +480,7 @@ std::string download_content(const OString& rURL, bool bFile)
 
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallbackFile);
         curl_easy_setopt(curl, CURLOPT_WRITEDATA,
-                static_cast<void *>(aTempFile.GetStream(StreamMode::WRITE)));
+                static_cast<void *>(&aFile));
     }
 
     // Fail if 400+ is returned from the web server.
@@ -475,12 +503,10 @@ std::string download_content(const OString& rURL, bool bFile)
         throw error_updater();
     }
 
-    return response_body;
-}
+    if (bFile)
+        rHash = aFile.getHash();
 
-OUString generateHash(const OUString& /*rURL*/)
-{
-    return OUString();
+    return response_body;
 }
 
 void handle_file_error(osl::FileBase::RC eError)
@@ -498,7 +524,8 @@ void handle_file_error(osl::FileBase::RC eError)
 void download_file(const OUString& rURL, size_t nFileSize, const OUString& rHash, const OUString& aFileName)
 {
     OString aURL = OUStringToOString(rURL, RTL_TEXTENCODING_UTF8);
-    std::string temp_file = download_content(aURL, true);
+    OUString aHash;
+    std::string temp_file = download_content(aURL, true, aHash);
     if (temp_file.empty())
         throw error_updater();
 
@@ -515,7 +542,6 @@ void download_file(const OUString& rURL, size_t nFileSize, const OUString& rHash
         SAL_WARN("desktop.updater", "File sizes don't match. File might be corrupted.");
     }
 
-    OUString aHash = generateHash(aTempFile);
     if (aHash != rHash)
     {
         SAL_WARN("desktop.updater", "File hash don't match. File might be corrupted.");
@@ -550,7 +576,8 @@ void update_checker()
 
     try
     {
-        std::string response_body = download_content(aURL, false);
+        OUString aHash;
+        std::string response_body = download_content(aURL, false, aHash);
         if (!response_body.empty())
         {
             update_info aUpdateInfo = parse_response(response_body);


More information about the Libreoffice-commits mailing list