/* * Copyright (c) 2014-2016 Alex Spataru * * This file is part of the QSimpleUpdater library, which is released under * the DBAD license, you can read a copy of it below: * * DON'T BE A DICK PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, * DISTRIBUTION AND MODIFICATION: * * Do whatever you like with the original work, just don't be a dick. * Being a dick includes - but is not limited to - the following instances: * * 1a. Outright copyright infringement - Don't just copy this and change the * name. * 1b. Selling the unmodified original with no work done what-so-ever, that's * REALLY being a dick. * 1c. Modifying the original work to contain hidden harmful content. * That would make you a PROPER dick. * * If you become rich through modifications, related works/services, or * supporting the original work, share the love. * Only a dick would make loads off this work and not buy the original works * creator(s) a pint. * * Code is provided with no warranty. Using somebody else's code and bitching * when it goes wrong makes you a DONKEY dick. * Fix the problem yourself. A non-dick would submit the fix back. */ #include #include #include #include #include #include #include "Updater.h" #include "Downloader.h" #include "loappconfig.h" #include "qsettings.h" #include "LoUIClass/x_uimsgboxokcancel.h" Updater::Updater() { m_url = ""; m_openUrl = ""; m_changelog = ""; m_downloadUrl = ""; m_latestVersion = ""; m_customAppcast = false; m_notifyOnUpdate = true; m_notifyOnFinish = false; m_updateAvailable = true; m_sameVersion=false; m_downloaderEnabled = true; m_noTipDownload=false; m_bSameStringCompare=false; m_moduleName = qApp->applicationName(); m_moduleVersion = qApp->applicationVersion(); m_mandatoryUpdate = false; m_downloader = new Downloader(); m_manager = new QNetworkAccessManager(); QNetworkReply *pReply = m_manager->get(QNetworkRequest(QUrl("https://www.ledok.cn/download/definitions/updates.json"))); //QNetworkReply *pReply = m_manager->get(QNetworkRequest(QUrl("https://www.ledok.cn"))); QReplyTimeout *pTimeout = new QReplyTimeout(pReply, 10000); // 超时进一步处理 connect(pTimeout, &QReplyTimeout::timeout, [=]() { qDebug() << "Timeout"; }); #if defined Q_OS_WIN m_platform = "windows"; #elif defined Q_OS_MAC m_platform = "osx"; #elif defined Q_OS_LINUX m_platform = "linux"; #elif defined Q_OS_ANDROID m_platform = "android"; #elif defined Q_OS_IOS m_platform = "ios"; #endif setUserAgentString (QString ("%1/%2 (Qt; QSimpleUpdater)").arg (qApp->applicationName(), qApp->applicationVersion())); connect (m_downloader, SIGNAL (downloadFinished (QString, QString)), this, SIGNAL (downloadFinished (QString, QString))); connect (m_manager, SIGNAL (finished (QNetworkReply*)), this, SLOT (onReply (QNetworkReply*))); } Updater::~Updater() { delete m_downloader; } /** * Returns the URL of the update definitions file */ QString Updater::url() const { return m_url; } /** * Returns the URL that the update definitions file wants us to open in * a web browser. * * \warning You should call \c checkForUpdates() before using this functio */ QString Updater::openUrl() const { return m_openUrl; } /** * Returns the changelog defined by the update definitions file. * \warning You should call \c checkForUpdates() before using this function */ QString Updater::changelog() const { return m_changelog; } /** * Returns the name of the module (if defined) */ QString Updater::moduleName() const { return m_moduleName; } /** * Returns the platform key (be it system-set or user-set). * If you do not define a platform key, the system will assign the following * platform key: * - On iOS: \c ios * - On Mac OSX: \c osx * - On Android: \c android * - On GNU/Linux: \c linux * - On Microsoft Windows: \c windows */ QString Updater::platformKey() const { return m_platform; } /** * Returns the download URL defined by the update definitions file. * \warning You should call \c checkForUpdates() before using this function */ QString Updater::downloadUrl() const { return m_downloadUrl; } /** * Returns the latest version defined by the update definitions file. * \warning You should call \c checkForUpdates() before using this function */ QString Updater::latestVersion() const { return m_latestVersion; } /** * Returns the user-agent header used by the client when communicating * with the server through HTTP */ QString Updater::userAgentString() const { return m_userAgentString; } /** * Returns the "local" version of the installed module */ QString Updater::moduleVersion() const { return m_moduleVersion; } /** * Returns \c true if the updater should NOT interpret the downloaded appcast. * This is useful if you need to store more variables (or information) in the * JSON file or use another appcast format (e.g. XML) */ bool Updater::customAppcast() const { return m_customAppcast; } /** * Returns \c true if the updater should notify the user when an update is * available. */ bool Updater::notifyOnUpdate() const { return m_notifyOnUpdate; } /** * Returns \c true if the updater should notify the user when it finishes * checking for updates. * * \note If set to \c true, the \c Updater will notify the user even when there * are no updates available (by congratulating him/her about being smart) */ bool Updater::notifyOnFinish() const { return m_notifyOnFinish; } /** * Returns \c true if there the current update is mandatory. * \warning You should call \c checkForUpdates() before using this function */ bool Updater::mandatoryUpdate() const { return m_mandatoryUpdate; } /** * Returns \c true if there is an update available. * \warning You should call \c checkForUpdates() before using this function */ bool Updater::updateAvailable() const { qDebug()<<"updateAvailable="<networkAccessible() == QNetworkAccessManager::NotAccessible){ qDebug()<<"setNetworkAccessible(QNetworkAccessManager::Accessible"; m_manager->setNetworkAccessible(QNetworkAccessManager::Accessible); } m_manager->get (request); qDebug()<setUserAgentString (agent); } /** * Changes the module \a version * \note The module version is used to compare the local and remote versions. * If the \a version parameter is empty, then the \c Updater will use the * application version (referenced by \c qApp) */ void Updater::setModuleVersion (const QString& version) { m_moduleVersion = version; } /** * If the \a enabled parameter is set to \c true, the \c Updater will open the * integrated downloader if the user agrees to install the update (if any) */ void Updater::setDownloaderEnabled (const bool enabled) { m_downloaderEnabled = enabled; } /** * Changes the platform key. * If the platform key is empty, then the system will use the following keys: * - On iOS: \c ios * - On Mac OSX: \c osx * - On Android: \c android * - On GNU/Linux: \c linux * - On Microsoft Windows: \c windows */ void Updater::setPlatformKey (const QString& platformKey) { m_platform = platformKey; } /** * If the \a customAppcast parameter is set to \c true, then the \c Updater * will not try to read the network reply from the server, instead, it will * emit the \c appcastDownloaded() signal, which allows the application to * read and interpret the appcast file by itself */ void Updater::setUseCustomAppcast (const bool customAppcast) { m_customAppcast = customAppcast; } /** * If the \a custom parameter is set to \c true, the \c Updater will not try * to open the downloaded file. Use the signals fired by the \c QSimpleUpdater * to install the update from the downloaded file by yourself. */ void Updater::setUseCustomInstallProcedures (const bool custom) { m_downloader->setUseCustomInstallProcedures (custom); } /** * If the \a mandatory_update is set to \c true, the \c Updater has to download and install the * update. If the user cancels or exits, the application will close */ void Updater::setMandatoryUpdate(const bool mandatory_update) { m_mandatoryUpdate = mandatory_update; } /** * Called when the download of the update definitions file is finished. */ void Updater::onReply (QNetworkReply* reply) { /* Check if we need to redirect */ QUrl redirect = reply->attribute ( QNetworkRequest::RedirectionTargetAttribute).toUrl(); if (!redirect.isEmpty()) { setUrl (redirect.toString()); checkForUpdates(); return; } reply->ignoreSslErrors(); /* There was a network error */ int aa=reply->error(); if (aa != QNetworkReply::NoError) { qDebug()<<"QNetworkReply::Error="<url()<readAll()); emit checkingFinished (url()); return; } /* Try to create a JSON document from downloaded data */ QJsonDocument document = QJsonDocument::fromJson (reply->readAll()); /* JSON is invalid */ if (document.isNull()) { qDebug()<<"document.isNull()"; setUpdateAvailable (false); emit checkingFinished (url()); return; } /* Get the platform information */ QJsonObject updates = document.object().value ("updates").toObject(); QJsonObject platform = updates.value (platformKey()).toObject(); /* Get update information */ m_openUrl = platform.value ("open-url").toString(); LoAppConfig *cfg = LoAppConfig::getInstance(); QSettings *settings = new QSettings(cfg->OrganizationName(), cfg->ApplicationName()); if(settings->value("MainSetting/Language").isValid()) { QString lang = settings->value("MainSetting/Language").toString(); if(lang == "zhCN") { m_changelog = platform.value ("changelog_zhCN").toString(); } else if(lang == "zhTH") { m_changelog = platform.value ("changelog_zhTH").toString(); } else if(lang == "jaJP") { m_changelog = platform.value ("changelog_jaJP").toString(); } else { m_changelog = platform.value ("changelog_enUS").toString(); } } else { m_changelog = platform.value ("changelog_enUS").toString(); } m_downloadUrl = platform.value ("download-url").toString(); m_latestVersion = platform.value ("latest-version").toString(); if (platform.contains("mandatory-update")) m_mandatoryUpdate = platform.value ("mandatory-update").toBool(); /* Compare latest and current version */ if(m_bSameStringCompare) { qDebug()<setUrlId (url()); m_downloader->setFileName (downloadUrl().split ("/").last()); m_downloader->setMandatoryUpdate(m_mandatoryUpdate); m_downloader->startDownload (QUrl (downloadUrl())); m_downloader->m_strVersion=latestVersion(); } else { // QString title = "

" // + tr ("Version %1 of %2 has been released!") // .arg (latestVersion()).arg (moduleName()) // + "

"; // X_UIMsgBoxOkCancel *dlg = new X_UIMsgBoxOkCancel(tr("Tip Info"),title); // if(dlg->exec() == QDialog::Accepted) { if (!openUrl().isEmpty()) QDesktopServices::openUrl (QUrl (openUrl())); else if (downloaderEnabled()) { m_downloader->setUrlId (url()); m_downloader->setFileName (downloadUrl().split ("/").last()); m_downloader->setMandatoryUpdate(m_mandatoryUpdate); m_downloader->startDownload (QUrl (downloadUrl())); m_downloader->m_strVersion=latestVersion(); } else QDesktopServices::openUrl (QUrl (downloadUrl())); } // else { // if(m_mandatoryUpdate) // { // QApplication::quit(); // } // } // box.setText (title); // box.setInformativeText (text); // box.setStandardButtons (QMessageBox::No | QMessageBox::Yes); // box.setDefaultButton (QMessageBox::Yes); // if (box.exec() == QMessageBox::Yes) // { // if (!openUrl().isEmpty()) // QDesktopServices::openUrl (QUrl (openUrl())); // else if (downloaderEnabled()) // { // m_downloader->setUrlId (url()); // m_downloader->setFileName (downloadUrl().split ("/").last()); // m_downloader->setMandatoryUpdate(m_mandatoryUpdate); // m_downloader->startDownload (QUrl (downloadUrl())); // m_downloader->m_strVersion=latestVersion(); // } // else // QDesktopServices::openUrl (QUrl (downloadUrl())); // } // else // { // if(m_mandatoryUpdate) // { // QApplication::quit(); // } // } } } else if (notifyOnFinish()) { box.setStandardButtons (QMessageBox::Close); box.setInformativeText (tr ("No updates are available for the moment")); box.setText ("

" + tr ("Congratulations! You are running the " "latest version of %1").arg (moduleName()) + "

"); box.exec(); } } /** * Compares the two version strings (\a x and \a y). * - If \a x is greater than \y, this function returns \c true. * - If \a y is greater than \x, this function returns \c false. * - If both versions are the same, this function returns \c false. */ bool Updater::compare (const QString& x, const QString& y) { QStringList versionsX = x.split ("."); QStringList versionsY = y.split ("."); int count = qMin (versionsX.count(), versionsY.count()); for (int i = 0; i < count; ++i) { int a = QString (versionsX.at (i)).toInt(); int b = QString (versionsY.at (i)).toInt(); if (a >= b) return true; else if (b > a) return false; } return versionsY.count() < versionsX.count(); }