summaryrefslogtreecommitdiffstats
path: root/desktop/source/app/updater.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/source/app/updater.cxx')
-rw-r--r--desktop/source/app/updater.cxx88
1 files changed, 59 insertions, 29 deletions
diff --git a/desktop/source/app/updater.cxx b/desktop/source/app/updater.cxx
index 2748373e5f62..12bb4969a68c 100644
--- a/desktop/source/app/updater.cxx
+++ b/desktop/source/app/updater.cxx
@@ -28,15 +28,18 @@
#include <rtl/ustring.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/configmgr.hxx>
+#include <o3tl/char16_t2wchar_t.hxx>
#include <osl/file.hxx>
#include <rtl/process.h>
#include <sal/log.hxx>
+#include <tools/stream.hxx>
#include <curl/curl.h>
#include <orcus/json_document_tree.hpp>
#include <orcus/config.hpp>
-#include <orcus/pstring.hpp>
+
+#include <systools/curlinit.hxx>
#include <comphelper/hash.hxx>
#include <com/sun/star/container/XNameAccess.hpp>
@@ -46,6 +49,7 @@
#include <functional>
#include <memory>
#include <set>
+#include <string_view>
namespace {
@@ -83,7 +87,12 @@ const char* pSofficeExeName = "soffice.exe";
OUString normalizePath(const OUString& rPath)
{
- OUString aPath = rPath.replaceAll("//", "/");
+ OUString aPath = rPath;
+#if defined WNT
+ aPath = aPath.replace('\\', '/');
+#endif
+
+ aPath = aPath.replaceAll("//", "/");
// remove final /
if (aPath.endsWith("/"))
@@ -105,7 +114,10 @@ OUString normalizePath(const OUString& rPath)
aPath = aTempPath.copy(0, i) + aPath.copy(nIndex + 3);
}
- return aPath.replaceAll("\\", "/");
+#if defined WNT
+ aPath = aPath.replace('/', '\\');
+#endif
+ return aPath;
}
void CopyFileToDir(const OUString& rTempDirURL, const OUString & rFileName, const OUString& rOldDir)
@@ -133,14 +145,17 @@ void CopyUpdaterToTempDir(const OUString& rInstallDirURL, const OUString& rTempD
{
OUString aUpdaterName = OUString::fromUtf8(pUpdaterName);
CopyFileToDir(rTempDirURL, aUpdaterName, rInstallDirURL);
+ CopyFileToDir(rTempDirURL, u"updater.ini"_ustr, rInstallDirURL);
}
#ifdef UNX
typedef char CharT;
#define tstrncpy std::strncpy
+char const * toStream(char const * s) { return s; }
#elif defined(_WIN32)
typedef wchar_t CharT;
#define tstrncpy std::wcsncpy
+OUString toStream(wchar_t const * s) { return OUString(o3tl::toU(s)); }
#else
#error "Need an implementation"
#endif
@@ -160,17 +175,14 @@ void createStr(const OUString& rStr, CharT** pArgs, size_t i)
pArgs[i] = pStr;
}
-CharT** createCommandLine()
+CharT** createCommandLine(OUString const & argv0, int * argc)
{
OUString aInstallDir = Updater::getInstallationPath();
size_t nCommandLineArgs = rtl_getAppCommandArgCount();
size_t nArgs = 8 + nCommandLineArgs;
CharT** pArgs = new CharT*[nArgs];
- {
- OUString aUpdaterName = OUString::fromUtf8(pUpdaterName);
- createStr(aUpdaterName, pArgs, 0);
- }
+ createStr(argv0, pArgs, 0);
{
// directory with the patch log
OUString aPatchDir = Updater::getPatchDirURL();
@@ -226,6 +238,7 @@ CharT** createCommandLine()
pArgs[nArgs - 1] = nullptr;
+ *argc = nArgs - 1;
return pArgs;
}
@@ -285,14 +298,15 @@ bool isUserWritable(const OUString& rFileURL)
bool update()
{
- utl::TempFile aTempDir(nullptr, true);
+ utl::TempFileNamed aTempDir(nullptr, true);
OUString aTempDirURL = aTempDir.GetURL();
CopyUpdaterToTempDir(Updater::getExecutableDirURL(), aTempDirURL);
OUString aUpdaterPath = getPathFromURL(aTempDirURL + "/" + OUString::fromUtf8(pUpdaterName));
Updater::log("Calling the updater with parameters: ");
- CharT** pArgs = createCommandLine();
+ int argc;
+ CharT** pArgs = createCommandLine(aUpdaterPath, &argc);
bool bSuccess = true;
const char* pUpdaterTestReplace = std::getenv("LIBO_UPDATER_TEST_REPLACE");
@@ -306,7 +320,7 @@ bool update()
bSuccess = false;
}
#elif defined(_WIN32)
- bSuccess = WinLaunchChild((wchar_t*)aUpdaterPath.getStr(), 8, pArgs);
+ bSuccess = WinLaunchChild((wchar_t*)aUpdaterPath.getStr(), argc, pArgs);
#endif
}
else
@@ -314,7 +328,7 @@ bool update()
SAL_WARN("desktop.updater", "Updater executable path: " << aUpdaterPath);
for (size_t i = 0; i < 8 + rtl_getAppCommandArgCount(); ++i)
{
- SAL_WARN("desktop.updater", pArgs[i]);
+ SAL_WARN("desktop.updater", toStream(pArgs[i]));
}
bSuccess = false;
}
@@ -389,9 +403,9 @@ public:
}
};
-OUString toOUString(const std::string& rStr)
+OUString toOUString(const std::string_view& rStr)
{
- return OUString::fromUtf8(rStr.c_str());
+ return OUString::fromUtf8(rStr);
}
update_file parse_update_file(orcus::json::node& rNode)
@@ -420,12 +434,12 @@ update_file parse_update_file(orcus::json::node& rNode)
}
update_file aUpdateFile;
- aUpdateFile.aURL = toOUString(aURLNode.string_value().str());
+ aUpdateFile.aURL = toOUString(aURLNode.string_value());
if (aUpdateFile.aURL.isEmpty())
throw invalid_update_info();
- aUpdateFile.aHash = toOUString(aHashNode.string_value().str());
+ aUpdateFile.aHash = toOUString(aHashNode.string_value());
aUpdateFile.nSize = static_cast<sal_uInt32>(aSizeNode.numeric_value());
return aUpdateFile;
}
@@ -452,7 +466,7 @@ update_info parse_response(const std::string& rResponse)
{
update_info aUpdateInfo;
auto aMsgNode = aDocumentRoot.child("response");
- aUpdateInfo.aMessage = toOUString(aMsgNode.string_value().str());
+ aUpdateInfo.aMessage = toOUString(aMsgNode.string_value());
return aUpdateInfo;
}
@@ -475,23 +489,23 @@ update_info parse_response(const std::string& rResponse)
}
orcus::json::node aLanguageNode = aDocumentRoot.child("languages");
- if (aUpdateNode.type() != orcus::json::node_t::object)
+ if (aLanguageNode.type() != orcus::json::node_t::object)
{
throw invalid_update_info();
}
update_info aUpdateInfo;
- aUpdateInfo.aFromBuildID = toOUString(aFromNode.string_value().str());
- aUpdateInfo.aSeeAlsoURL = toOUString(aSeeAlsoNode.string_value().str());
+ aUpdateInfo.aFromBuildID = toOUString(aFromNode.string_value());
+ aUpdateInfo.aSeeAlsoURL = toOUString(aSeeAlsoNode.string_value());
aUpdateInfo.aUpdateFile = parse_update_file(aUpdateNode);
- std::vector<orcus::pstring> aLanguages = aLanguageNode.keys();
+ std::vector<std::string_view> aLanguages = aLanguageNode.keys();
for (auto const& language : aLanguages)
{
language_file aLanguageFile;
auto aLangEntry = aLanguageNode.child(language);
- aLanguageFile.aLangCode = toOUString(language.str());
+ aLanguageFile.aLangCode = toOUString(language);
aLanguageFile.aUpdateFile = parse_update_file(aLangEntry);
aUpdateInfo.aLanguageFiles.push_back(aLanguageFile);
}
@@ -546,6 +560,8 @@ std::string download_content(const OString& rURL, bool bFile, OUString& rHash)
if (!curl)
return std::string();
+ ::InitCurl_easy(curl.get());
+
curl_easy_setopt(curl.get(), CURLOPT_URL, rURL.getStr());
curl_easy_setopt(curl.get(), CURLOPT_USERAGENT, kUserAgent);
bool bUseProxy = false;
@@ -562,11 +578,15 @@ std::string download_content(const OString& rURL, bool bFile, OUString& rHash)
headerlist = curl_slist_append(headerlist, buf);
curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1); // follow redirects
- // only allow redirect to http:// and https://
- curl_easy_setopt(curl.get(), CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
+ // only allow redirect to https://
+#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 85)
+ curl_easy_setopt(curl.get(), CURLOPT_REDIR_PROTOCOLS_STR, "https");
+#else
+ curl_easy_setopt(curl.get(), CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS);
+#endif
std::string response_body;
- utl::TempFile aTempFile;
+ utl::TempFileNamed aTempFile;
WriteDataFile aFile(aTempFile.GetStream(StreamMode::WRITE));
if (!bFile)
{
@@ -655,9 +675,11 @@ void download_file(const OUString& rURL, size_t nFileSize, const OUString& rHash
throw invalid_hash(rHash, aHash);
}
- OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/");
+ OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/updates/");
rtl::Bootstrap::expandMacros(aPatchDirURL);
osl::Directory::create(aPatchDirURL);
+ aPatchDirURL += "0/";
+ osl::Directory::create(aPatchDirURL);
OUString aDestFile = aPatchDirURL + aFileName;
Updater::log("Destination File: " + aDestFile);
@@ -743,6 +765,14 @@ void update_checker()
comphelper::ConfigurationChanges::create());
officecfg::Office::Update::Update::SeeAlso::set(aSeeAlsoURL, batch);
batch->commit();
+ OUString const statUrl = Updater::getPatchDirURL() + "update.status";
+ SvFileStream stat(statUrl, StreamMode::WRITE | StreamMode::TRUNC);
+ stat.WriteOString("pending-service");
+ stat.Flush();
+ if (auto const e = stat.GetError()) {
+ Updater::log("Writing <" + statUrl + "> failed with " + e.toString());
+ }
+ stat.Close();
}
}
}
@@ -775,7 +805,7 @@ void update_checker()
OUString Updater::getUpdateInfoLog()
{
- OUString aUpdateInfoURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/updating.log");
+ OUString aUpdateInfoURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/updates/updating.log");
rtl::Bootstrap::expandMacros(aUpdateInfoURL);
return aUpdateInfoURL;
@@ -783,7 +813,7 @@ OUString Updater::getUpdateInfoLog()
OUString Updater::getPatchDirURL()
{
- OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/patch/");
+ OUString aPatchDirURL("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/updates/0/");
rtl::Bootstrap::expandMacros(aPatchDirURL);
return aPatchDirURL;
@@ -834,7 +864,7 @@ void Updater::log(const char* pMessage)
OUString aUpdateLog = getUpdateInfoLog();
SvFileStream aLog(aUpdateLog, StreamMode::STD_READWRITE);
aLog.Seek(aLog.Tell() + aLog.remainingSize()); // make sure we are at the end
- aLog.WriteCharPtr(pMessage);
+ aLog.WriteOString(pMessage);
}
OUString Updater::getBuildID()