mirror of https://github.com/procxx/kepka.git
Use static version map for autoupdates.
This commit is contained in:
parent
993cb987a6
commit
48e913bf2c
|
@ -109,7 +109,6 @@ void Launcher::prepareSettings() {
|
||||||
|
|
||||||
switch (cPlatform()) {
|
switch (cPlatform()) {
|
||||||
case dbipWindows:
|
case dbipWindows:
|
||||||
gUpdateURL = QUrl(qsl("http://tdesktop.com/win/tupdates/current"));
|
|
||||||
#ifndef OS_WIN_STORE
|
#ifndef OS_WIN_STORE
|
||||||
gPlatformString = qsl("Windows");
|
gPlatformString = qsl("Windows");
|
||||||
#else // OS_WIN_STORE
|
#else // OS_WIN_STORE
|
||||||
|
@ -117,7 +116,6 @@ void Launcher::prepareSettings() {
|
||||||
#endif // OS_WIN_STORE
|
#endif // OS_WIN_STORE
|
||||||
break;
|
break;
|
||||||
case dbipMac:
|
case dbipMac:
|
||||||
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac/tupdates/current"));
|
|
||||||
#ifndef OS_MAC_STORE
|
#ifndef OS_MAC_STORE
|
||||||
gPlatformString = qsl("MacOS");
|
gPlatformString = qsl("MacOS");
|
||||||
#else // OS_MAC_STORE
|
#else // OS_MAC_STORE
|
||||||
|
@ -125,15 +123,12 @@ void Launcher::prepareSettings() {
|
||||||
#endif // OS_MAC_STORE
|
#endif // OS_MAC_STORE
|
||||||
break;
|
break;
|
||||||
case dbipMacOld:
|
case dbipMacOld:
|
||||||
gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current"));
|
|
||||||
gPlatformString = qsl("MacOSold");
|
gPlatformString = qsl("MacOSold");
|
||||||
break;
|
break;
|
||||||
case dbipLinux64:
|
case dbipLinux64:
|
||||||
gUpdateURL = QUrl(qsl("http://tdesktop.com/linux/tupdates/current"));
|
|
||||||
gPlatformString = qsl("Linux64bit");
|
gPlatformString = qsl("Linux64bit");
|
||||||
break;
|
break;
|
||||||
case dbipLinux32:
|
case dbipLinux32:
|
||||||
gUpdateURL = QUrl(qsl("http://tdesktop.com/linux32/tupdates/current"));
|
|
||||||
gPlatformString = qsl("Linux32bit");
|
gPlatformString = qsl("Linux32bit");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace Core {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kCheckTimeout = TimeMs(10000);
|
constexpr auto kCheckTimeout = TimeMs(10000);
|
||||||
|
constexpr auto kMaxResponseSize = 1024 * 1024;
|
||||||
|
const auto kUpdateUrl = "http://updates.tdesktop.com";
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
using VersionInt = DWORD;
|
using VersionInt = DWORD;
|
||||||
|
@ -97,6 +99,7 @@ public:
|
||||||
|
|
||||||
void start(bool forceWait);
|
void start(bool forceWait);
|
||||||
void stop();
|
void stop();
|
||||||
|
void test();
|
||||||
|
|
||||||
State state() const;
|
State state() const;
|
||||||
int already() const;
|
int already() const;
|
||||||
|
@ -119,7 +122,14 @@ private:
|
||||||
void gotFailure(QNetworkReply::NetworkError e);
|
void gotFailure(QNetworkReply::NetworkError e);
|
||||||
void clearSentRequest();
|
void clearSentRequest();
|
||||||
void requestTimeout();
|
void requestTimeout();
|
||||||
|
void startDownloadThread(
|
||||||
|
uint64 availableVersion,
|
||||||
|
bool isAvailableBeta,
|
||||||
|
QString url);
|
||||||
|
bool checkOldResponse(const QByteArray &response);
|
||||||
|
bool checkResponse(const QByteArray &response);
|
||||||
|
|
||||||
|
bool _testing = false;
|
||||||
bool _isReady = false;
|
bool _isReady = false;
|
||||||
base::Timer _timer;
|
base::Timer _timer;
|
||||||
base::Timer _retryTimer;
|
base::Timer _retryTimer;
|
||||||
|
@ -233,21 +243,19 @@ void Updater::gotResponse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
cSetLastUpdateCheck(unixtime());
|
cSetLastUpdateCheck(unixtime());
|
||||||
const auto m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromLatin1(_reply->readAll()));
|
const auto response = _reply->readAll();
|
||||||
if (m.hasMatch()) {
|
if (response.size() >= kMaxResponseSize) {
|
||||||
uint64 currentVersion = m.captured(1).toULongLong();
|
LOG(("App Error: Bad update map size: %1").arg(response.size()));
|
||||||
QString url = m.captured(2);
|
gotFailure(QNetworkReply::UnknownContentError);
|
||||||
bool betaVersion = false;
|
return;
|
||||||
if (url.startsWith(qstr("beta_"))) {
|
|
||||||
betaVersion = true;
|
|
||||||
url = url.mid(5) + '_' + Core::countBetaVersionSignature(currentVersion);
|
|
||||||
}
|
}
|
||||||
if ((!betaVersion || cBetaVersion()) && currentVersion > (betaVersion ? cBetaVersion() : uint64(AppVersion))) {
|
if (!checkOldResponse(response)) {
|
||||||
_thread = std::make_unique<QThread>();
|
if (!checkResponse(response)) {
|
||||||
_private = new Private(this, _thread.get(), url);
|
gotFailure(QNetworkReply::UnknownContentError);
|
||||||
_thread->start();
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearSentRequest();
|
clearSentRequest();
|
||||||
if (!_thread) {
|
if (!_thread) {
|
||||||
if (const auto update = FindUpdateFile(); !update.isEmpty()) {
|
if (const auto update = FindUpdateFile(); !update.isEmpty()) {
|
||||||
|
@ -269,6 +277,157 @@ void Updater::gotFailure(QNetworkReply::NetworkError e) {
|
||||||
start(true);
|
start(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Updater::checkOldResponse(const QByteArray &response) {
|
||||||
|
const auto string = QString::fromLatin1(response);
|
||||||
|
const auto old = QRegularExpression(
|
||||||
|
qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")
|
||||||
|
).match(string);
|
||||||
|
if (!old.hasMatch()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto availableVersion = old.captured(1).toULongLong();
|
||||||
|
const auto url = old.captured(2);
|
||||||
|
const auto isAvailableBeta = url.startsWith(qstr("beta_"));
|
||||||
|
startDownloadThread(
|
||||||
|
availableVersion,
|
||||||
|
isAvailableBeta,
|
||||||
|
isAvailableBeta ? url.mid(5) + "_{signature}" : url);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Updater::checkResponse(const QByteArray &response) {
|
||||||
|
auto error = QJsonParseError{ 0, QJsonParseError::NoError };
|
||||||
|
const auto document = QJsonDocument::fromJson(response, &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
LOG(("Update Error: Failed to parse response JSON, error: %1"
|
||||||
|
).arg(error.errorString()));
|
||||||
|
return false;
|
||||||
|
} else if (!document.isObject()) {
|
||||||
|
LOG(("Update Error: Not an object received in response JSON."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto platforms = document.object();
|
||||||
|
const auto platform = [&] {
|
||||||
|
switch (cPlatform()) {
|
||||||
|
case dbipWindows: return "win";
|
||||||
|
case dbipMac: return "mac";
|
||||||
|
case dbipMacOld: return "mac32";
|
||||||
|
case dbipLinux64: return "linux";
|
||||||
|
case dbipLinux32: return "linux32";
|
||||||
|
}
|
||||||
|
Unexpected("Platform in Updater::checkResponse.");
|
||||||
|
}();
|
||||||
|
const auto it = platforms.constFind(platform);
|
||||||
|
if (it == platforms.constEnd()) {
|
||||||
|
LOG(("Update Error: Platform '%1' not found in response."
|
||||||
|
).arg(platform));
|
||||||
|
return false;
|
||||||
|
} else if (!it->isObject()) {
|
||||||
|
LOG(("Update Error: Not an object found for platform '%1'."
|
||||||
|
).arg(platform));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto types = it->toObject();
|
||||||
|
const auto list = [&]() -> std::vector<QString> {
|
||||||
|
if (cBetaVersion()) {
|
||||||
|
return { "alpha", "beta", "stable" };
|
||||||
|
} else if (cAlphaVersion()) {
|
||||||
|
return { "beta", "stable" };
|
||||||
|
}
|
||||||
|
return { "stable" };
|
||||||
|
}();
|
||||||
|
auto bestIsAvailableBeta = false;
|
||||||
|
auto bestAvailableVersion = 0ULL;
|
||||||
|
auto bestLink = QString();
|
||||||
|
for (const auto &type : list) {
|
||||||
|
const auto it = types.constFind(type);
|
||||||
|
if (it == types.constEnd()) {
|
||||||
|
continue;
|
||||||
|
} else if (!it->isObject()) {
|
||||||
|
LOG(("Update Error: Not an object found for '%1:%2'."
|
||||||
|
).arg(platform).arg(type));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto map = it->toObject();
|
||||||
|
const auto key = _testing ? "testing" : "released";
|
||||||
|
const auto version = map.constFind(key);
|
||||||
|
const auto link = map.constFind("link");
|
||||||
|
if (version == map.constEnd()) {
|
||||||
|
continue;
|
||||||
|
} else if (link == map.constEnd()) {
|
||||||
|
LOG(("Update Error: Link not found for '%1:%2'."
|
||||||
|
).arg(platform).arg(type));
|
||||||
|
return false;
|
||||||
|
} else if (!link->isString()) {
|
||||||
|
LOG(("Update Error: Link is not a string for '%1:%2'."
|
||||||
|
).arg(platform).arg(type));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto isAvailableBeta = (type == "alpha");
|
||||||
|
const auto availableVersion = [&] {
|
||||||
|
if (version->isString()) {
|
||||||
|
return version->toString().toULongLong();
|
||||||
|
} else if (version->isDouble()) {
|
||||||
|
return uint64(std::round(version->toDouble()));
|
||||||
|
}
|
||||||
|
return 0ULL;
|
||||||
|
}();
|
||||||
|
if (!availableVersion) {
|
||||||
|
LOG(("Update Error: Version is not valid for '%1:%2:%3'."
|
||||||
|
).arg(platform).arg(type).arg(key));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto compare = isAvailableBeta
|
||||||
|
? availableVersion
|
||||||
|
: availableVersion * 1000;
|
||||||
|
const auto bestCompare = bestIsAvailableBeta
|
||||||
|
? bestAvailableVersion
|
||||||
|
: bestAvailableVersion * 1000;
|
||||||
|
if (compare > bestCompare) {
|
||||||
|
bestAvailableVersion = availableVersion;
|
||||||
|
bestIsAvailableBeta = isAvailableBeta;
|
||||||
|
bestLink = link->toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!bestAvailableVersion) {
|
||||||
|
LOG(("Update Error: No valid entry found for platform '%1'."
|
||||||
|
).arg(platform));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
startDownloadThread(
|
||||||
|
bestAvailableVersion,
|
||||||
|
bestIsAvailableBeta,
|
||||||
|
kUpdateUrl + bestLink);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Updater::startDownloadThread(
|
||||||
|
uint64 availableVersion,
|
||||||
|
bool isAvailableBeta,
|
||||||
|
QString url) {
|
||||||
|
const auto myVersion = isAvailableBeta
|
||||||
|
? cBetaVersion()
|
||||||
|
: uint64(AppVersion);
|
||||||
|
const auto validVersion = (cBetaVersion() || !isAvailableBeta);
|
||||||
|
if (!validVersion || availableVersion <= myVersion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto versionUrl = url.replace(
|
||||||
|
"{version}",
|
||||||
|
QString::number(availableVersion));
|
||||||
|
const auto finalUrl = isAvailableBeta
|
||||||
|
? QString(versionUrl).replace(
|
||||||
|
"{signature}",
|
||||||
|
countBetaVersionSignature(availableVersion))
|
||||||
|
: versionUrl;
|
||||||
|
_thread = std::make_unique<QThread>();
|
||||||
|
_private = new Private(
|
||||||
|
this,
|
||||||
|
_thread.get(),
|
||||||
|
finalUrl);
|
||||||
|
_thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
void Updater::handleReady() {
|
void Updater::handleReady() {
|
||||||
_isReady = true;
|
_isReady = true;
|
||||||
stop();
|
stop();
|
||||||
|
@ -356,17 +515,8 @@ void Updater::start(bool forceWait) {
|
||||||
if (sendRequest) {
|
if (sendRequest) {
|
||||||
clearSentRequest();
|
clearSentRequest();
|
||||||
|
|
||||||
auto url = QUrl(cUpdateURL());
|
auto url = QUrl(kUpdateUrl + QString("/current"));
|
||||||
if (cBetaVersion()) {
|
DEBUG_LOG(("Update Info: requesting update state from '%1'"
|
||||||
url.setQuery(qsl("version=%1&beta=%2"
|
|
||||||
).arg(AppVersion
|
|
||||||
).arg(cBetaVersion()));
|
|
||||||
} else if (cAlphaVersion()) {
|
|
||||||
url.setQuery(qsl("version=%1&alpha=1").arg(AppVersion));
|
|
||||||
} else {
|
|
||||||
url.setQuery(qsl("version=%1").arg(AppVersion));
|
|
||||||
}
|
|
||||||
DEBUG_LOG(("App Info: requesting update state from '%1'"
|
|
||||||
).arg(url.toDisplayString()));
|
).arg(url.toDisplayString()));
|
||||||
const auto request = QNetworkRequest(url);
|
const auto request = QNetworkRequest(url);
|
||||||
_manager = std::make_unique<QNetworkAccessManager>();
|
_manager = std::make_unique<QNetworkAccessManager>();
|
||||||
|
@ -384,6 +534,12 @@ void Updater::start(bool forceWait) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Updater::test() {
|
||||||
|
_testing = true;
|
||||||
|
cSetLastUpdateCheck(0);
|
||||||
|
start(false);
|
||||||
|
}
|
||||||
|
|
||||||
void Updater::requestTimeout() {
|
void Updater::requestTimeout() {
|
||||||
if (_reply) {
|
if (_reply) {
|
||||||
stop();
|
stop();
|
||||||
|
@ -426,6 +582,10 @@ void UpdateChecker::start(bool forceWait) {
|
||||||
_updater->start(forceWait);
|
_updater->start(forceWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateChecker::test() {
|
||||||
|
_updater->test();
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateChecker::stop() {
|
void UpdateChecker::stop() {
|
||||||
_updater->stop();
|
_updater->stop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
|
|
||||||
void start(bool forceWait = false);
|
void start(bool forceWait = false);
|
||||||
void stop();
|
void stop();
|
||||||
|
void test();
|
||||||
|
|
||||||
State state() const;
|
State state() const;
|
||||||
int already() const;
|
int already() const;
|
||||||
|
|
|
@ -397,7 +397,7 @@ bool CheckBetaVersionDir() {
|
||||||
QByteArray k;
|
QByteArray k;
|
||||||
dataStream >> v >> k;
|
dataStream >> v >> k;
|
||||||
if (dataStream.status() == QDataStream::Ok && !k.isEmpty()) {
|
if (dataStream.status() == QDataStream::Ok && !k.isEmpty()) {
|
||||||
cSetBetaVersion(qMax(v, AppVersion * 1000ULL));
|
cSetBetaVersion(AppVersion * 1000ULL);
|
||||||
cSetBetaPrivateKey(k);
|
cSetBetaPrivateKey(k);
|
||||||
cSetRealBetaVersion(v);
|
cSetRealBetaVersion(v);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -87,7 +87,6 @@ DBIPlatform gPlatform = dbipLinux32;
|
||||||
#error Unknown platform
|
#error Unknown platform
|
||||||
#endif
|
#endif
|
||||||
QString gPlatformString;
|
QString gPlatformString;
|
||||||
QUrl gUpdateURL;
|
|
||||||
bool gIsElCapitan = false;
|
bool gIsElCapitan = false;
|
||||||
bool gIsSnowLeopard = false;
|
bool gIsSnowLeopard = false;
|
||||||
|
|
||||||
|
|
|
@ -194,7 +194,6 @@ DeclareReadSetting(DBIPlatform, Platform);
|
||||||
DeclareReadSetting(QString, PlatformString);
|
DeclareReadSetting(QString, PlatformString);
|
||||||
DeclareReadSetting(bool, IsElCapitan);
|
DeclareReadSetting(bool, IsElCapitan);
|
||||||
DeclareReadSetting(bool, IsSnowLeopard);
|
DeclareReadSetting(bool, IsSnowLeopard);
|
||||||
DeclareReadSetting(QUrl, UpdateURL);
|
|
||||||
|
|
||||||
DeclareSetting(int, OtherOnline);
|
DeclareSetting(int, OtherOnline);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mtproto/mtp_instance.h"
|
#include "mtproto/mtp_instance.h"
|
||||||
#include "mtproto/dc_options.h"
|
#include "mtproto/dc_options.h"
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
|
#include "core/update_checker.h"
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
#include "window/themes/window_theme_editor.h"
|
#include "window/themes/window_theme_editor.h"
|
||||||
#include "media/media_audio_track.h"
|
#include "media/media_audio_track.h"
|
||||||
|
@ -47,6 +48,9 @@ void fillCodes() {
|
||||||
Messenger::Instance().onSwitchTestMode();
|
Messenger::Instance().onSwitchTestMode();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
Codes.insert(qsl("testupdate"), [] {
|
||||||
|
Core::UpdateChecker().test();
|
||||||
|
});
|
||||||
Codes.insert(qsl("loadlang"), [] {
|
Codes.insert(qsl("loadlang"), [] {
|
||||||
Lang::CurrentCloudManager().switchToLanguage(qsl("custom"));
|
Lang::CurrentCloudManager().switchToLanguage(qsl("custom"));
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue