9#include <QJsonDocument>
11#include <QNetworkReply>
12#include <QNetworkRequest>
15#include <QVersionNumber>
20static constexpr auto k_apiUrl =
"https://api.github.com/repos/gibis-unifesp/wiredpanda/releases/latest";
28#elif defined(Q_OS_MACOS)
30#elif defined(Q_OS_LINUX)
39 if (platform ==
"Linux") {
40 return name.endsWith(
".AppImage") && name.contains(arch, Qt::CaseInsensitive);
42 if (platform ==
"Windows") {
43 return name.contains(
"Windows") && name.endsWith(
".zip") && name.contains(arch, Qt::CaseInsensitive);
45 if (platform ==
"macOS") {
47 return name.contains(
"macOS") && name.endsWith(
".dmg");
52bool shouldOfferUpdate(
const QString &tagName,
const QVersionNumber ¤tVersion,
const QString &skippedVersion)
54 const QVersionNumber latest = QVersionNumber::fromString(tagName).normalized();
55 if (latest.isNull() || latest <= currentVersion) {
60 return latest.toString() != skippedVersion;
65 return url.isValid() && url.scheme() == QLatin1String(
"https") && url.host() == QLatin1String(
"github.com");
76 connect(&m_network, &QNetworkAccessManager::sslErrors,
this, [](QNetworkReply *reply,
const QList<QSslError> &errors) {
77 qWarning() <<
"UpdateChecker: SSL errors, aborting reply:" << errors;
91 const QString today = QDate::currentDate().toString(Qt::ISODate);
96 QNetworkRequest request = QNetworkRequest{QUrl(
k_apiUrl)};
97 request.setHeader(QNetworkRequest::UserAgentHeader,
"wiRedPanda/" APP_VERSION);
98 request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
99 QNetworkRequest::NoLessSafeRedirectPolicy);
100 request.setTransferTimeout(10000);
102 QNetworkReply *reply = m_network.get(request);
106 reply->setReadBufferSize(1024 * 1024 + 1);
107 connect(reply, &QNetworkReply::downloadProgress,
this, [reply](qint64 received, qint64) {
108 if (received > 1024 * 1024) {
112 connect(reply, &QNetworkReply::finished,
this, [
this, reply] { onReplyFinished(reply); });
115void UpdateChecker::onReplyFinished(QNetworkReply *reply)
117 reply->deleteLater();
121 if (reply->error() != QNetworkReply::NoError) {
125 const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
126 if (doc.isNull() || !doc.isObject()) {
136 const QString tagName = doc.object().value(
"tag_name").toString();
140 const QVersionNumber latest = QVersionNumber::fromString(tagName).normalized();
144 const QString arch = QSysInfo::buildCpuArchitecture();
145 const QJsonArray assets = doc.object().value(
"assets").toArray();
146 for (
const QJsonValue &assetVal : assets) {
147 const QJsonObject asset = assetVal.toObject();
148 const QString name = asset.value(
"name").toString();
150 downloadUrl = QUrl(asset.value(
"browser_download_url").toString());
155 const QUrl releaseUrl = QUrl(doc.object().value(
"html_url").toString());
157 qWarning() <<
"UpdateChecker: release URL has unexpected scheme/host, ignoring update notification:" << releaseUrl;
161 qWarning() <<
"UpdateChecker: download URL has unexpected scheme/host, falling back to release page:" << downloadUrl;
Typed wrappers around QSettings for all application preferences.
static constexpr auto k_apiUrl
bool isSafeGitHubUrl(const QUrl &url)
True when url is safe to download from or hand to the OS's URL handler.
bool shouldOfferUpdate(const QString &tagName, const QVersionNumber ¤tVersion, const QString &skippedVersion)
True when the release tagged tagName should be offered to a user running currentVersion who may have ...
static QString currentPlatform()
bool isMatchingReleaseAsset(const QString &name, const QString &platform, const QString &arch)
True when a GitHub release asset filename is the binary for the given platform ("Windows"/"macOS"/"Li...
Checks the GitHub Releases API for newer versions of wiRedPanda.
bool isSafeGitHubUrl(const QUrl &url)
True when url is safe to download from or hand to the OS's URL handler.
bool shouldOfferUpdate(const QString &tagName, const QVersionNumber ¤tVersion, const QString &skippedVersion)
True when the release tagged tagName should be offered to a user running currentVersion who may have ...
bool isMatchingReleaseAsset(const QString &name, const QString &platform, const QString &arch)
True when a GitHub release asset filename is the binary for the given platform ("Windows"/"macOS"/"Li...
File-format version constants and application version accessor.
static QString updateCheckLastDate()
static bool updateChecksDisabled()
Global opt-out of update checks (for offline/managed installs); default false (enabled).
static QString updateCheckSkippedVersion()
static void setUpdateCheckLastDate(const QString &date)
UpdateChecker(QObject *parent=nullptr)
void updateAvailable(const QString &latestVersion, const QUrl &downloadUrl, const QUrl &releaseUrl)
Emitted when a newer release is available and has not been suppressed.
void checkForUpdates()
Initiates an asynchronous version check.
const QVersionNumber current