2021-11-18 14:58:01 +00:00
|
|
|
#include "updates_checker.h"
|
2019-07-24 12:41:55 +00:00
|
|
|
#include "version.h"
|
2022-10-18 09:35:04 +00:00
|
|
|
#include <QGuiApplication>
|
|
|
|
#include <QXmlStreamReader>
|
2019-07-24 12:41:55 +00:00
|
|
|
|
|
|
|
UpdatesChecker::UpdatesChecker()
|
|
|
|
{
|
|
|
|
connect(&m_networkAccessManager, &QNetworkAccessManager::finished, this, &UpdatesChecker::downloadFinished);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdatesChecker::start()
|
|
|
|
{
|
|
|
|
QUrl url(APP_UPDATES_CHECKER_URL);
|
|
|
|
QNetworkRequest request(url);
|
|
|
|
m_networkAccessManager.get(request);
|
|
|
|
}
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
const QString& UpdatesChecker::message() const
|
2019-07-24 12:41:55 +00:00
|
|
|
{
|
|
|
|
return m_message;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool UpdatesChecker::isLatest() const
|
|
|
|
{
|
|
|
|
return m_isLatest;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool UpdatesChecker::hasError() const
|
|
|
|
{
|
|
|
|
return m_hasError;
|
|
|
|
}
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
bool UpdatesChecker::parseUpdateInfoXml(const QByteArray& updateInfoXml, std::vector<UpdateItem>* updateItems)
|
2019-07-24 12:41:55 +00:00
|
|
|
{
|
|
|
|
std::vector<QString> elementNameStack;
|
|
|
|
QXmlStreamReader reader(updateInfoXml);
|
|
|
|
while (!reader.atEnd()) {
|
|
|
|
reader.readNext();
|
|
|
|
if (!reader.isStartElement() && !reader.isEndElement()) {
|
|
|
|
if (!reader.name().toString().isEmpty())
|
|
|
|
qDebug() << "Skip xml element:" << reader.name().toString() << " tokenType:" << reader.tokenType();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
QString baseName = reader.name().toString();
|
|
|
|
if (reader.isStartElement()) {
|
|
|
|
elementNameStack.push_back(baseName);
|
|
|
|
if (elementNameStack.size() > 10) {
|
|
|
|
qDebug() << "Invalid xml, element name stack exceed limits";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QStringList nameItems;
|
2022-10-18 09:35:04 +00:00
|
|
|
for (const auto& nameItem : elementNameStack) {
|
2019-07-24 12:41:55 +00:00
|
|
|
nameItems.append(nameItem);
|
|
|
|
}
|
|
|
|
QString fullName = nameItems.join(".");
|
|
|
|
if (reader.isEndElement())
|
|
|
|
elementNameStack.pop_back();
|
|
|
|
if (reader.isStartElement()) {
|
|
|
|
if (fullName == "updates.update") {
|
|
|
|
UpdateItem updateItem;
|
|
|
|
updateItem.forTags = reader.attributes().value("for").toString().toLower();
|
|
|
|
updateItem.version = reader.attributes().value("version").toString();
|
|
|
|
updateItem.humanVersion = reader.attributes().value("humanVersion").toString();
|
|
|
|
updateItem.descriptionUrl = reader.attributes().value("descriptionUrl").toString();
|
2022-10-18 09:35:04 +00:00
|
|
|
if (!updateItem.forTags.isEmpty() && !updateItem.version.isEmpty() && !updateItem.humanVersion.isEmpty() && !updateItem.descriptionUrl.isEmpty()) {
|
2019-07-24 12:41:55 +00:00
|
|
|
if (updateItems->size() >= 100)
|
|
|
|
return false;
|
|
|
|
updateItem.forTags = "," + updateItem.forTags + ",";
|
|
|
|
updateItems->push_back(updateItem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
bool UpdatesChecker::isVersionLessThan(const QString& version, const QString& compareWith)
|
2019-07-24 12:41:55 +00:00
|
|
|
{
|
|
|
|
auto versionTokens = version.split(".");
|
|
|
|
auto compareWithTokens = compareWith.split(".");
|
|
|
|
if (versionTokens.size() > 4) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
while (compareWithTokens.size() < 4)
|
|
|
|
compareWithTokens.push_back("0");
|
|
|
|
if (compareWithTokens.size() > 4) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
while (compareWithTokens.size() < 4)
|
|
|
|
compareWithTokens.push_back("0");
|
|
|
|
for (size_t i = 0; i < 4; ++i) {
|
|
|
|
int left = versionTokens[i].toInt();
|
|
|
|
int right = compareWithTokens[i].toInt();
|
|
|
|
if (left > right)
|
|
|
|
return false;
|
|
|
|
else if (left < right)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
const UpdatesChecker::UpdateItem& UpdatesChecker::matchedUpdateItem() const
|
2019-07-24 12:41:55 +00:00
|
|
|
{
|
|
|
|
return m_matchedUpdateItem;
|
|
|
|
}
|
|
|
|
|
2022-10-18 09:35:04 +00:00
|
|
|
void UpdatesChecker::downloadFinished(QNetworkReply* reply)
|
2019-07-24 12:41:55 +00:00
|
|
|
{
|
|
|
|
if (reply->error()) {
|
|
|
|
qDebug() << "Download update info failed:" << qPrintable(reply->errorString());
|
|
|
|
m_message = tr("Fetch update info failed, please retry later");
|
|
|
|
} else {
|
|
|
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
|
|
if (200 != statusCode) {
|
|
|
|
qDebug() << "Download update info failed, statusCode:" << statusCode;
|
|
|
|
m_message = tr("Fetch update info failed, please retry later");
|
|
|
|
} else {
|
|
|
|
std::vector<UpdateItem> updateItems;
|
|
|
|
if (!parseUpdateInfoXml(reply->readAll(), &updateItems)) {
|
|
|
|
m_message = tr("Fetch update info failed, please retry later");
|
|
|
|
} else {
|
|
|
|
m_isLatest = true;
|
|
|
|
m_hasError = false;
|
|
|
|
m_message = tr("%1 %2 is currently the newest version available").arg(APP_NAME).arg(APP_HUMAN_VER);
|
|
|
|
QString platform = QString(APP_PLATFORM).toLower();
|
|
|
|
if (!platform.isEmpty()) {
|
|
|
|
platform = "," + platform + ",";
|
2022-10-18 09:35:04 +00:00
|
|
|
for (const auto& it : updateItems) {
|
2019-07-24 12:41:55 +00:00
|
|
|
if (-1 == it.forTags.indexOf(platform))
|
|
|
|
continue;
|
|
|
|
if (isVersionLessThan(APP_VER, it.version)) {
|
|
|
|
m_isLatest = false;
|
|
|
|
m_message = tr("An update is available: %1 %2").arg(APP_NAME).arg(it.humanVersion);
|
|
|
|
m_matchedUpdateItem = it;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
reply->deleteLater();
|
|
|
|
emit finished();
|
|
|
|
}
|