From 1de820dc4bbc8cd815ae740456a3c28e71097300 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 4 Mar 2017 16:55:57 -0500 Subject: [PATCH] Fix/re-enable checking for updates We can (again) check for updates and, if an update is available, send the user to the site to download them. The old format (a .json specifying a version number and download URL) was kept. The address for this file is now specified in the settings. --- src/core/UBApplicationController.cpp | 140 ++++++++++++--------------- src/core/UBApplicationController.h | 15 +-- src/core/UBSettings.cpp | 1 + src/core/UBSettings.h | 1 + src/frameworks/UBVersion.cpp | 25 +++-- 5 files changed, 86 insertions(+), 96 deletions(-) diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 36ae40ca..8b22b47c 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -90,7 +90,6 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, , mAutomaticCheckForUpdates(false) , mCheckingForUpdates(false) , mIsShowingDesktop(false) - , mHttp(0) { mDisplayManager = new UBDisplayManager(this); @@ -121,7 +120,7 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, connect(UBApplication::webController, SIGNAL(imageCaptured(const QPixmap &, bool, const QUrl&)) , this, SLOT(addCapturedPixmap(const QPixmap &, bool, const QUrl&))); - networkAccessManager = new QNetworkAccessManager (this); + mNetworkAccessManager = new QNetworkAccessManager (this); QTimer::singleShot (1000, this, SLOT (checkAtLaunch())); } @@ -136,8 +135,6 @@ UBApplicationController::~UBApplicationController() delete mBlackScene; delete mMirror; - if (mHttp) delete mHttp; - delete(mOpenSankoreImporter); mOpenSankoreImporter = NULL; } @@ -478,85 +475,71 @@ void UBApplicationController::showDesktop(bool dontSwitchFrontProcess) } -void UBApplicationController::checkUpdate(QString urlString) +void UBApplicationController::checkUpdate(const QUrl& url) { + QUrl jsonUrl = url; + if (url.isEmpty()) + jsonUrl = UBSettings::settings()->appSoftwareUpdateURL->get().toUrl(); + qDebug() << "Checking for update at url: " << jsonUrl.toString(); - #if defined(QT_NO_DEBUG) - /* - if(mHttp) - mHttp->deleteLater(); - QUrl url(urlString); - mHttp = new QHttpPart(url.host()); - connect(mHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(updateRequestFinished(int,bool))); - connect(mHttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); - - mHttp->get(url.path()); - - */ - -#else - if(mHttpreply) - mHttpreply->deleteLater(); - QUrl url(urlString); - mHttpreply = qnam.get(QNetworkRequest(url)); - connect(mHttpreply, SIGNAL(requestFinished(int,bool)), this, SLOT(updateRequestFinished(int,bool))); - connect(mHttpreply, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); - // mHttpreply->setUrl(url.path()); - //mHttp->get(url.path()); + connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(updateRequestFinished(QNetworkReply*))); + + mNetworkAccessManager->get(QNetworkRequest(jsonUrl)); -#endif } -/* -void UBApplicationController::updateHeaderReceived(QHttpResponseHeader header) + + +void UBApplicationController::updateRequestFinished(QNetworkReply * reply) { - if(header.statusCode() == 302 && header.hasKey("Location")){ - mHttp->close(); - checkUpdate(header.value("Location")); + if (reply->error()) { + qWarning() << "Error downloading update file: " << reply->errorString(); + return; } -} -*/ -void UBApplicationController::updateHeaderReceived(QNetworkRequest header ) -{ - //if(header.attribute(QNetworkRequest::HttpStatusCodeAttribute) == 302 && header.header(QNetworkRequest::LocationHeader)){ - // mHttp->close(); - mHttpreply->close(); - //checkUpdate(header.value("Location")); - // } -} + // Check if we are being redirected. If so, call checkUpdate again -void UBApplicationController::updateRequestFinished(int id, bool error) -{ - if (error){ - qWarning() << "http command id" << id << "return an error"; - } - else{ - /* QString responseString = QString(mHttp->readAll()); - qDebug() << responseString; - if (!responseString.isEmpty() && responseString.contains("version") && responseString.contains("url")){ - mHttp->close(); - mHttp->deleteLater(); - mHttp = 0; - downloadJsonFinished(responseString); - } - */ - QString responseString = QString(mHttpreply->readAll()); - qDebug() << responseString; - if (!responseString.isEmpty() && responseString.contains("version") && responseString.contains("url")){ - mHttpreply->close(); - mHttpreply->deleteLater(); - mHttpreply = 0; - downloadJsonFinished(responseString); - } - } -} + QVariant redirect_target = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (!redirect_target.isNull()) { + // The returned URL might be relative. resolved() creates an absolute url from it + QUrl redirect_url(reply->url().resolved(redirect_target.toUrl())); + checkUpdate(redirect_url); + return; + } + + // No error and no redirect => we read the whole response + + QString responseString = QString(reply->readAll()); + + if (!responseString.isEmpty() && + responseString.contains("version") && + responseString.contains("url")) { + + reply->close(); + reply->deleteLater(); + + downloadJsonFinished(responseString); + } +} void UBApplicationController::downloadJsonFinished(QString currentJson) { + /* + The .json files simply specify the latest version number available, and + the URL to send the user to, so they can download it. + + They look like: + + { + "version": "1.3.5", + "url": "http://openboard.ch" + } + */ + QScriptValue scriptValue; QScriptEngine scriptEngine; scriptValue = scriptEngine.evaluate ("(" + currentJson + ")"); @@ -564,17 +547,18 @@ void UBApplicationController::downloadJsonFinished(QString currentJson) UBVersion installedVersion (qApp->applicationVersion()); UBVersion jsonVersion (scriptValue.property("version").toString()); + qDebug() << "json version: " << jsonVersion.toUInt(); + qDebug() << "installed version: " << installedVersion.toUInt(); + if (jsonVersion > installedVersion) { - if (UBApplication::mainWindow->yesNoQuestion(tr("Update available"), tr ("New update available, would you go to the web page ?"))){ - QUrl url(scriptValue.property ("url").toString()); - QDesktopServices::openUrl (url); - } - } - else { - if (isNoUpdateDisplayed) { - mMainWindow->information(tr("Update"), tr("No update available")); + if (UBApplication::mainWindow->yesNoQuestion(tr("Update available"), tr ("New update available, would you go to the web page ?"))){ + QUrl url(scriptValue.property("url").toString()); + QDesktopServices::openUrl(url); } } + else if (isNoUpdateDisplayed) { + mMainWindow->information(tr("Update"), tr("No update available")); + } } void UBApplicationController::checkAtLaunch() @@ -583,14 +567,14 @@ void UBApplicationController::checkAtLaunch() if(UBSettings::settings()->appEnableAutomaticSoftwareUpdates->get().toBool()){ isNoUpdateDisplayed = false; - //checkUpdate (); + checkUpdate(); } } void UBApplicationController::checkUpdateRequest() { isNoUpdateDisplayed = true; - //checkUpdate (); + checkUpdate(); } void UBApplicationController::hideDesktop() diff --git a/src/core/UBApplicationController.h b/src/core/UBApplicationController.h index 03ace3a9..c3cfb40d 100644 --- a/src/core/UBApplicationController.h +++ b/src/core/UBApplicationController.h @@ -53,12 +53,8 @@ class UBVersion; class UBSoftwareUpdate; class QNetworkAccessManager; class QNetworkReply; -class QHttpPart; class UBRightPalette; class UBOpenSankoreImporter; -class QScriptValue; -class QScriptEngine; -class QNetworkReply; class UBApplicationController : public QObject { @@ -158,8 +154,8 @@ class UBApplicationController : public QObject void checkAtLaunch(); private slots: - void updateRequestFinished(int id, bool error); - void updateHeaderReceived(QNetworkRequest header ); + void updateRequestFinished(QNetworkReply * reply); + protected: @@ -193,13 +189,10 @@ class UBApplicationController : public QObject bool mIsShowingDesktop; bool isNoUpdateDisplayed; - void checkUpdate (QString urlString = "http://get.openboard.org/update.json"); - QNetworkAccessManager *networkAccessManager; + void checkUpdate(const QUrl &url = QUrl()); + QNetworkAccessManager * mNetworkAccessManager; void downloadJsonFinished(QString updateString); - QHttpPart* mHttp; - QNetworkAccessManager qnam; - QNetworkReply *mHttpreply; }; #endif /* UBAPPLICATIONCONTROLLER_H_ */ diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index cccf87b7..aba5d8ce 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -226,6 +226,7 @@ void UBSettings::init() appToolBarDisplayText = new UBSetting(this, "App", "ToolBarDisplayText", true); appEnableAutomaticSoftwareUpdates = new UBSetting(this, "App", "EnableAutomaticSoftwareUpdates", false); appEnableSoftwareUpdates = new UBSetting(this, "App", "EnableSoftwareUpdates", true); + appSoftwareUpdateURL = new UBSetting(this, "App", "SoftwareUpdateURL", "http://www.openboard.ch/update.json"); appToolBarOrientationVertical = new UBSetting(this, "App", "ToolBarOrientationVertical", false); appPreferredLanguage = new UBSetting(this,"App","PreferredLanguage", ""); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 9f024d57..44757652 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -240,6 +240,7 @@ class UBSettings : public QObject UBSetting* appToolBarDisplayText; UBSetting* appEnableAutomaticSoftwareUpdates; UBSetting* appEnableSoftwareUpdates; + UBSetting* appSoftwareUpdateURL; UBSetting* appToolBarOrientationVertical; UBSetting* appPreferredLanguage; diff --git a/src/frameworks/UBVersion.cpp b/src/frameworks/UBVersion.cpp index a08c4fc7..b8916152 100644 --- a/src/frameworks/UBVersion.cpp +++ b/src/frameworks/UBVersion.cpp @@ -42,21 +42,32 @@ UBVersion::UBVersion(const QString &string) uint UBVersion::toUInt() const { + /* Based on semantic versioning, version numbers look like: + * Major.Minor.Patch-Type.Build + * + * To compare version numbers, the string is split into each part, and they are multiplied + * to give a number where the first two digits are the Major version, the next two are the + * Minor version, and so on. + * + * i.e if Major, Minor etc. are named A, B, C, D, E, the number will look like: + * AABBCCDDEE + */ + uint result = 0; - QStringList list = mString.split("."); + QStringList list = mString.split(QRegExp("[-\\.]")); switch (list.count()) { case 2: //short version 1.0 - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (Release * 100); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + (Release * 100); break; case 3: //release version 1.0.0 - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (Release * 100) + list.at(2).toUInt(); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + list.at(2).toUInt()*10000 + (Release * 100); break; - case 4:{ - //standard version 1.0.a/b/r.0 - uint releaseStage = list.at(2).startsWith("a") ? Alpha :(list.at(2).startsWith("b") ? Beta : ReleaseCandidate); - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (releaseStage * 100) + list.at(3).toUInt(); + case 5:{ + //standard version 1.0.0.a/b/rc.0 + uint releaseStage = list.at(3).startsWith("a") ? Alpha :(list.at(3).startsWith("b") ? Beta : ReleaseCandidate); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + (list.at(2).toUInt() * 10000) + (releaseStage * 100) + list.at(4).toUInt(); break; } default: