# HG changeset patch # User Andre Heinecke # Date 1411564360 -7200 # Node ID a1e990947172a37097f863b6cbd5dbf7c742b1bb # Parent e401680b0cbd0610a0b2edf72187273d5a387fac (issue38) Add long time error handling. A Long Time Error is an error that will be shown to the user if it happened at least seven times with an interval of at least a day between occurances. After one success a long time error will be reset. diff -r e401680b0cbd -r a1e990947172 ui/downloader.cpp --- a/ui/downloader.cpp Wed Sep 24 15:05:53 2014 +0200 +++ b/ui/downloader.cpp Wed Sep 24 15:12:40 2014 +0200 @@ -157,7 +157,9 @@ if (mDownloadSW) { if (!mSSLConnection->downloadFile(mResourceSW, fileName, MAX_SW_SIZE)) { - emit error(tr("Failed to download File"), SSLConnection::ConnectionLost); + emit error(tr("Failed to download File.") + "\n" + + tr("The connection to the update server was lost or" + " the disk is full."), SSLConnection::ConnectionLost); qDebug() << "Failed to download software update."; return; } diff -r e401680b0cbd -r a1e990947172 ui/mainwindow.cpp --- a/ui/mainwindow.cpp Wed Sep 24 15:05:53 2014 +0200 +++ b/ui/mainwindow.cpp Wed Sep 24 15:12:40 2014 +0200 @@ -196,13 +196,13 @@ if (!availableFileName.isEmpty()) { mListToInstall.readList(availableFileName.toUtf8().constData()); if (!mListToInstall.isValid()) { + handleLTE(lteInvalidList); mCurState = TransferError; - // Probably a bug when Qt fileName is encoded and cFileName - // fails because of this. This needs a unit test! - // Maybe check that the file is in our data directory QFile::remove(availableFileName); mSettings.remove("List/available"); mSettings.remove("List/availableDate"); + } else { + handleLTE(lteInvalidList, true); } } else { // Make sure the available notation is also removed @@ -254,12 +254,14 @@ swFileName.toUtf8().size()); qDebug() << "Binary verify result: " << verifyResult.result; if (verifyResult.result != VerifyValid) { + handleLTE(lteInvalidSoftware); qDebug() << "Failed to verify downloaded data."; QFile::remove(swFileName); mSettings.remove("Software/available"); mSettings.remove("Software/availableDate"); return; } + handleLTE(lteInvalidSoftware, true); /* Reset error state */ fclose(verifyResult.fptr); } @@ -270,9 +272,8 @@ verifyListData(); if (!mListToInstall.isValid()) { + handleLTE(lteInvalidList); /* Downloader provided invalid files */ - /* TODO (issue38): Error count. Error handling. Otherwise - * we can go into an endless loop here */ /* Retry the download again in 10 - 20 minutes */ QTimer::singleShot(600000 + (qrand() % 60000), this, SLOT(checkUpdates())); @@ -306,10 +307,14 @@ showMessage(); } -QString getPrettyInstallerName(QString realFileName) { +QString MainWindow::getPrettyInstallerName(QString realFileName) { QTemporaryDir tDir; if (!tDir.isValid()) { qDebug () << "Failed to create temporary directory."; + showErrorMessage (tr("Failed to create temporary directory.") + "\n" + + tr("Please ensure that you have the access rights to write in " + "the temporary directory and that there is at least 20MB free " + "disk space available.")); return QString(); } QString targetPath = tDir.path() + "/" + QObject::tr("TrustBridge-Updater", @@ -320,6 +325,10 @@ targetPath += ".exe"; #endif if (!QFile::copy(realFileName, targetPath)) { + showErrorMessage (tr("Failed to create a temporary copy of the installer.") + "\n" + + tr("Please ensure that you have the access rights to write in " + "the temporary directory and that there is at least 20MB free " + "disk space available.")); qDebug() << "Failed to create temporary copy of installer."; } return targetPath; @@ -334,8 +343,6 @@ if (filePath.isEmpty()) { qDebug() << "Failed to copy updater to temporary location."; - showErrorMessage(tr("Failed to create update process.") + "\n" + - tr("This could be caused by not enough disk space or invalid permissions.")); return; } mSettings.setValue("Software/Updater", filePath); /* So it can be deleted @@ -346,9 +353,11 @@ filePath.toUtf8().size()); if (vres.result != VerifyValid) { + handleLTE(lteInvalidSoftware); qDebug() << "Invalid software. Not installing"; return; - } + } + handleLTE(lteInvalidSoftware, true); QFileInfo fi(QCoreApplication::applicationFilePath()); QDir installDir = fi.absoluteDir(); @@ -571,8 +580,12 @@ void MainWindow::downloaderError(const QString &message, SSLConnection::ErrorCode error) { - /* TODO (issue38) handle error according to a plan */ syslog_error_printf ("Failed to check for updates: %s", message.toUtf8().constData()); + if (error == SSLConnection::InvalidCertificate) { + handleLTE(lteInvalidCertificate); + } else { + handleLTE(lteNoConnection); + } #ifdef IS_TAG_BUILD /* During tag build it should never happen that an url checked is not available * during development this is normal as each revision produces a new url. */ @@ -1647,6 +1660,8 @@ mLastUpdateCheckContents->show(); mLastUpdateCheck->show(); syslog_info_printf(tr("Sucessfully checked for updates.").toUtf8().constData()); + handleLTE(lteNoConnection, true); /* Reset error state */ + handleLTE(lteInvalidCertificate, true); } if ((getState() != NewSoftwareAvailable && getState() != NewListAvailable && mTrayMode) && !isVisible()) { @@ -1704,3 +1719,90 @@ { QMessageBox::warning(this, tr("TrustBridge error"), msg); } + +void MainWindow::handleLTE(LongTimeErrors lte, bool reset) +{ + QString settingPrefix; + switch (lte) { + case lteInvalidSoftware: + settingPrefix = "LTE/invalidSW"; + break; + case lteInvalidList: + settingPrefix = "LTE/invalidList"; + break; + case lteInvalidCertificate: + settingPrefix = "LTE/invalidCertificate"; + break; + case lteNoConnection: + settingPrefix = "LTE/noConnection"; + break; + default: + qDebug() << "Unhandled error. " << lte; + } + + if (reset) { + /* delete all values and be done */ + mSettings.remove(settingPrefix + "_lastSaved"); + mSettings.remove(settingPrefix + "_count"); + mSettings.remove(settingPrefix + "_lastMsgShown"); + return; + } + + QDateTime lastSaved = mSettings.value(settingPrefix + "_lastSaved").toDateTime(); + bool cnt_valid; + int cnt = mSettings.value(settingPrefix + "_count").toInt(&cnt_valid); + if (!cnt_valid) { + cnt = 0; + } + + if (!lastSaved.isValid() || lastSaved.daysTo(QDateTime::currentDateTime()) >= 1) { + /* The error count is increased at most once a day */ + mSettings.setValue(settingPrefix + "_lastSaved", QDateTime::currentDateTime()); + mSettings.setValue(settingPrefix + "_count", ++cnt); + } + + + if (cnt < 7) { + /* We are done */ + return; + } + /* A week has passed. Start showing the error. */ + QDateTime lastShown = mSettings.value(settingPrefix + "_lastShown").toDateTime(); + if (lastShown.isValid() && lastShown.daysTo(QDateTime::currentDateTime()) < 1) { + /* Only show the error message once a day */ + return; + } + + mSettings.setValue(settingPrefix + "_lastShown", QDateTime::currentDateTime()); + + switch (lte) { + case lteInvalidSoftware: + showErrorMessage(tr("The integrity check for the available software update has " + "failed repeatedly.") + "\n" + + tr("Please contact your Support or the publisher of the Software.")); + break; + case lteInvalidList: + showErrorMessage(tr("The integrity check of the available certificates has " + "failed repeatedly.") + "\n" + + tr("Please contact your Support or the publisher of the Software.")); + break; + case lteInvalidCertificate: + showErrorMessage(tr("The authentication of the download server has " + "failed repeatedly.") + "\n" + + tr("Please contact your Support or the publisher of the Software.")); + break; + case lteNoConnection: + bool useProxy = mSettings.value("UseProxy", false).toBool(); + if (useProxy) { + showErrorMessage(tr("The connection to the download server has " + "failed repeatedly.") + "\n" + + tr("Please check that the Proxy Server \"%1\" is available.").arg( + mSettings.value("ProxyURL").toString())); + } else { + showErrorMessage(tr("The connection to the download server has " + "failed repeatedly.") + "\n" + + tr("Please check your internet connection.")); + } + break; + } +} diff -r e401680b0cbd -r a1e990947172 ui/mainwindow.h --- a/ui/mainwindow.h Wed Sep 24 15:05:53 2014 +0200 +++ b/ui/mainwindow.h Wed Sep 24 15:12:40 2014 +0200 @@ -61,6 +61,19 @@ TransferError, NothingChanged }; + + /** + * @enum LongTimeErrors + * @brief Errors that should be stored and only shown after some time has elapsed. + */ + enum LongTimeErrors { + lteInvalidSoftware, /*! The downloaded Software was invalid. */ + lteInvalidCertificate, /*! The SSL certificate of the download server was wrong. */ + lteInvalidList, /*! The downloaded Certificate List was invalid. */ + lteNoConnection + }; + + /** @brief accessor for the current state. */ CurrentState getState() {return mCurState;} void setState(CurrentState state) {mCurState = state;} @@ -181,6 +194,18 @@ void changesChanged(const QString& cnt); private: + /** @brief Get a installer file name that can be shown to a user. + * + * This copys the real file to a temporary location with a user + * visible localized file name. Does error Handling. + * + * @param [in] realFileName The original file name. + * + * @returns a null string in case on errors. The new filename + * otherwise. + */ + QString getPrettyInstallerName(QString realFileName); + /** @brief the combined number of changes made in all lists */ int changeCount(); @@ -206,6 +231,23 @@ */ void verifySWData(); + /** @brief note an long time error in the settings and show a message. + * + * Saves a software verify error in the settings and notifies the + * user if necessary. + * + * @param [in] lte The error to handle. + * @param [in] reset weather or not the error count should be reset. + * + **/ + void handleLTE(LongTimeErrors lte, bool reset = false); + + /** @brief note a verify error in the settings and show a message + * + * Saves a software verify error in the settings and notifies the + * user if necessary.*/ + void swVerifyError(); + void createTrayIcon(); void createActions(); void loadCertificateList();