UpdateCheck.h header
#include <ew/app/update/UpdateCheck.h>
Namespace ew::app::update
UpdateManifest struct
struct ew::app::update::UpdateManifest
The published description of the newest release, fetched from updateManifestUrl() (https://dl.ordfoss.com/latest.json, written by tools/web/publish-release.ps1). The desktop uses it to flag "an update is available" and to download + verify the installer.
Members
QString ew::app::update::UpdateManifest::version
The newest released version, e.g. "0.2.0".
QString ew::app::update::UpdateManifest::installerUrl
Where the installer lives. parseUpdateManifest guarantees this is HTTPS on the official download host – the manifest names a binary the app will RUN, so anything else is rejected wholesale.
QString ew::app::update::UpdateManifest::sha256
Hex SHA-256 of the installer bytes; the downloader verifies before launching anything.
QString ew::app::update::UpdateManifest::notesUrl
Where the human-readable release notes live (optional; empty when absent).
bool ew::app::update::UpdateManifest::operator==(const UpdateManifest &) const =default
Compares equal when every field matches.
Enumerations
enum class UpdateChannel { Stable, Beta }
Which stream of releases an install follows.
enum class UpdateCheckFailure { Unreachable, AccessEnded, Unreadable }
Why an update check ended without a manifest – so the caller can say the right thing.
Functions
QString ew::app::update::betaManifestUrl(const QString &betaKey)
The manifest URL for an allow-listed beta tester holding betaKey.
The key travels in the PATH, not a header, because HttpClient::get() takes none and widening that shared interface for one caller is the wrong trade. It is not a credential in the usual sense: it grants a download, reads nothing, spends nothing, and is revoked with one write.
Returns an empty string when betaKey is not well formed, so a blank or mistyped key produces no request at all rather than a request that cannot succeed.
UpdateCheckFailure ew::app::update::classifyUpdateFailure(int statusCode, const QByteArray &body)
Classifies a failed fetch from its HTTP status and body.
The distinction it exists for: a 403 from the beta gate means a tester's access ended and must say so plainly, while a transport failure must stay silent. Reporting "your beta access has ended" to someone merely offline would be a lie about their account; reporting a network error to someone whose key was revoked leaves them retrying forever.
int ew::app::update::compareVersions(const QString &a, const QString &b)
Compares two versions by SemVer 2.0.0 precedence: negative when a < b, zero when equal, positive when a > b. Missing segments count as zero, so "1.2" == "1.2.0".
Pre-release suffixes are ordered, not ignored, and the rule is the one the beta scheme rests on (docs/VERSIONING.md): a version carrying a suffix is LOWER than the same version without one, so 0.3.0-beta.2 < 0.3.0. Two suffixes compare identifier by identifier – numerically where both are numeric (beta.9 < beta.10), a numeric identifier below an alphanumeric one, and a longer run of otherwise-equal identifiers as the later. Build metadata (+sha) takes no part in precedence.
This is implemented as the general rule rather than a special case for the literal "beta", because the first release named "rc" or "alpha" would otherwise sort wrongly with nothing to say so.
bool ew::app::update::isNewerVersion(const QString ¤tVersion, const UpdateManifest &manifest)
True when manifest describes a strictly newer version than currentVersion.
bool ew::app::update::isWellFormedBetaKey(const QString &betaKey)
True when betaKey has the shape this product issues: ordf_beta_ and 32 hex characters.
A cheap, local check, not an authorisation: only the server knows whether a key is live. It exists so the UI can refuse an obviously wrong paste immediately and say why, instead of sending it and reporting a refusal that looks like the tester's access was withdrawn.
QString ew::app::update::legacyUpdateManifestUrl()
The pre-0.2.0 manifest URL, tried only when updateManifestUrl() cannot be reached.
Insurance against a one-way door: an install whose only manifest host became unreachable could never hear about a release again, and no amount of later server-side fixing would reach it.
QString ew::app::update::manifestUrlFor(UpdateChannel channel, const QString &betaKey)
The manifest URL for channel, or the stable one when a beta key is missing or malformed.
Falling BACK rather than failing is deliberate: an install set to Beta whose key was cleared should keep hearing about stable releases, not go silent. Silence is the one failure mode an updater must never have, because it is indistinguishable from being up to date.
std::optional< UpdateManifest > ew::app::update::parseUpdateManifest(const QByteArray &json)
Parses json (the fetched latest.json) into a manifest, or nullopt when it is malformed or unsafe. Unsafe means: missing/non-semantic version, missing/malformed SHA-256, or an installer URL that is not HTTPS on one of updateDownloadHosts() – the manifest tells the app what binary to fetch and run, so a tampered or mis-hosted entry rejects the whole manifest rather than degrade.
std::optional< UpdateManifest > ew::app::update::parseUpdateManifest(const QByteArray &json, const QString &manifestUrl)
As above, but resolves a RELATIVE installerUrl against manifestUrl, the address the manifest was fetched from.
The beta manifest ships installerUrl as a bare filename on purpose. It is served from …/beta/<key>/latest.json, so a relative reference resolves to the installer beside it – and an ABSOLUTE url there would have to contain somebody's key, which every tester who opened the file would then hold. Since the key is what identifies who leaked a build, a manifest that hands one out destroys the only property the beta channel actually provides.
Resolution happens BEFORE the host check, never instead of it: the result still has to be HTTPS on an official download host, so a protocol-relative //evil.example/x.exe is rejected exactly as an absolute one would be.
QStringList ew::app::update::updateDownloadHosts()
Every host an update installer may be downloaded from, current first.
There are two, and it is a deliberate migration rather than an oversight. Releases live on dl.ordfoss.com from 0.2.0 onwards. dl.easywriter.site stays accepted permanently because builds older than 0.2.0 know only that host and reject a manifest whose installer is served anywhere else – so the single release that carries those users across must be published there too. Accepting both also means a manifest can be re-pointed later without stranding anyone.
QString ew::app::update::updateManifestUrl()
The well-known manifest URL the app checks on the stable channel.