comparison ui/mainwindow.cpp @ 1227:a1e990947172

(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.
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 24 Sep 2014 15:12:40 +0200
parents 1171a4778562
children 05b938021a24
comparison
equal deleted inserted replaced
1226:e401680b0cbd 1227:a1e990947172
194 QString availableFileName = mSettings.value("List/available").toString(); 194 QString availableFileName = mSettings.value("List/available").toString();
195 QString installedFileName = mSettings.value("List/installed").toString(); 195 QString installedFileName = mSettings.value("List/installed").toString();
196 if (!availableFileName.isEmpty()) { 196 if (!availableFileName.isEmpty()) {
197 mListToInstall.readList(availableFileName.toUtf8().constData()); 197 mListToInstall.readList(availableFileName.toUtf8().constData());
198 if (!mListToInstall.isValid()) { 198 if (!mListToInstall.isValid()) {
199 handleLTE(lteInvalidList);
199 mCurState = TransferError; 200 mCurState = TransferError;
200 // Probably a bug when Qt fileName is encoded and cFileName
201 // fails because of this. This needs a unit test!
202 // Maybe check that the file is in our data directory
203 QFile::remove(availableFileName); 201 QFile::remove(availableFileName);
204 mSettings.remove("List/available"); 202 mSettings.remove("List/available");
205 mSettings.remove("List/availableDate"); 203 mSettings.remove("List/availableDate");
204 } else {
205 handleLTE(lteInvalidList, true);
206 } 206 }
207 } else { 207 } else {
208 // Make sure the available notation is also removed 208 // Make sure the available notation is also removed
209 mSettings.remove("List/available"); 209 mSettings.remove("List/available");
210 mSettings.remove("List/availableDate"); 210 mSettings.remove("List/availableDate");
252 } 252 }
253 bin_verify_result verifyResult = verify_binary(swFileName.toUtf8().constData(), 253 bin_verify_result verifyResult = verify_binary(swFileName.toUtf8().constData(),
254 swFileName.toUtf8().size()); 254 swFileName.toUtf8().size());
255 qDebug() << "Binary verify result: " << verifyResult.result; 255 qDebug() << "Binary verify result: " << verifyResult.result;
256 if (verifyResult.result != VerifyValid) { 256 if (verifyResult.result != VerifyValid) {
257 handleLTE(lteInvalidSoftware);
257 qDebug() << "Failed to verify downloaded data."; 258 qDebug() << "Failed to verify downloaded data.";
258 QFile::remove(swFileName); 259 QFile::remove(swFileName);
259 mSettings.remove("Software/available"); 260 mSettings.remove("Software/available");
260 mSettings.remove("Software/availableDate"); 261 mSettings.remove("Software/availableDate");
261 return; 262 return;
262 } 263 }
264 handleLTE(lteInvalidSoftware, true); /* Reset error state */
263 fclose(verifyResult.fptr); 265 fclose(verifyResult.fptr);
264 } 266 }
265 267
266 void MainWindow::handleNewList(const QString& fileName, const QDateTime& modDate) { 268 void MainWindow::handleNewList(const QString& fileName, const QDateTime& modDate) {
267 qDebug() << "new list available"; 269 qDebug() << "new list available";
268 mSettings.setValue("List/available", fileName); 270 mSettings.setValue("List/available", fileName);
269 mSettings.setValue("List/availableDate", modDate); 271 mSettings.setValue("List/availableDate", modDate);
270 272
271 verifyListData(); 273 verifyListData();
272 if (!mListToInstall.isValid()) { 274 if (!mListToInstall.isValid()) {
275 handleLTE(lteInvalidList);
273 /* Downloader provided invalid files */ 276 /* Downloader provided invalid files */
274 /* TODO (issue38): Error count. Error handling. Otherwise
275 * we can go into an endless loop here */
276 277
277 /* Retry the download again in 10 - 20 minutes */ 278 /* Retry the download again in 10 - 20 minutes */
278 QTimer::singleShot(600000 + (qrand() % 60000), this, SLOT(checkUpdates())); 279 QTimer::singleShot(600000 + (qrand() % 60000), this, SLOT(checkUpdates()));
279 qDebug() << "Failed to verify list."; 280 qDebug() << "Failed to verify list.";
280 } else { 281 } else {
304 305
305 mSettings.sync(); 306 mSettings.sync();
306 showMessage(); 307 showMessage();
307 } 308 }
308 309
309 QString getPrettyInstallerName(QString realFileName) { 310 QString MainWindow::getPrettyInstallerName(QString realFileName) {
310 QTemporaryDir tDir; 311 QTemporaryDir tDir;
311 if (!tDir.isValid()) { 312 if (!tDir.isValid()) {
312 qDebug () << "Failed to create temporary directory."; 313 qDebug () << "Failed to create temporary directory.";
314 showErrorMessage (tr("Failed to create temporary directory.") + "\n" +
315 tr("Please ensure that you have the access rights to write in "
316 "the temporary directory and that there is at least 20MB free "
317 "disk space available."));
313 return QString(); 318 return QString();
314 } 319 }
315 QString targetPath = tDir.path() + "/" + QObject::tr("TrustBridge-Updater", 320 QString targetPath = tDir.path() + "/" + QObject::tr("TrustBridge-Updater",
316 "Used as filename for the updater. Only use ASCII please."); 321 "Used as filename for the updater. Only use ASCII please.");
317 322
318 tDir.setAutoRemove(false); 323 tDir.setAutoRemove(false);
319 #ifdef WIN32 324 #ifdef WIN32
320 targetPath += ".exe"; 325 targetPath += ".exe";
321 #endif 326 #endif
322 if (!QFile::copy(realFileName, targetPath)) { 327 if (!QFile::copy(realFileName, targetPath)) {
328 showErrorMessage (tr("Failed to create a temporary copy of the installer.") + "\n" +
329 tr("Please ensure that you have the access rights to write in "
330 "the temporary directory and that there is at least 20MB free "
331 "disk space available."));
323 qDebug() << "Failed to create temporary copy of installer."; 332 qDebug() << "Failed to create temporary copy of installer.";
324 } 333 }
325 return targetPath; 334 return targetPath;
326 } 335 }
327 336
332 /* Copy the file to a temporary name for installation */ 341 /* Copy the file to a temporary name for installation */
333 filePath = getPrettyInstallerName(filePath); 342 filePath = getPrettyInstallerName(filePath);
334 343
335 if (filePath.isEmpty()) { 344 if (filePath.isEmpty()) {
336 qDebug() << "Failed to copy updater to temporary location."; 345 qDebug() << "Failed to copy updater to temporary location.";
337 showErrorMessage(tr("Failed to create update process.") + "\n" +
338 tr("This could be caused by not enough disk space or invalid permissions."));
339 return; 346 return;
340 } 347 }
341 mSettings.setValue("Software/Updater", filePath); /* So it can be deleted 348 mSettings.setValue("Software/Updater", filePath); /* So it can be deleted
342 on next start */ 349 on next start */
343 mSettings.sync(); 350 mSettings.sync();
344 351
345 bin_verify_result vres = verify_binary(filePath.toUtf8().constData(), 352 bin_verify_result vres = verify_binary(filePath.toUtf8().constData(),
346 filePath.toUtf8().size()); 353 filePath.toUtf8().size());
347 354
348 if (vres.result != VerifyValid) { 355 if (vres.result != VerifyValid) {
356 handleLTE(lteInvalidSoftware);
349 qDebug() << "Invalid software. Not installing"; 357 qDebug() << "Invalid software. Not installing";
350 return; 358 return;
351 } 359 }
360 handleLTE(lteInvalidSoftware, true);
352 QFileInfo fi(QCoreApplication::applicationFilePath()); 361 QFileInfo fi(QCoreApplication::applicationFilePath());
353 QDir installDir = fi.absoluteDir(); 362 QDir installDir = fi.absoluteDir();
354 363
355 #ifdef WIN32 364 #ifdef WIN32
356 QString parameters = QString::fromLatin1("/S /UPDATE=1 /D=") + 365 QString parameters = QString::fromLatin1("/S /UPDATE=1 /D=") +
569 checkUpdates(); 578 checkUpdates();
570 } 579 }
571 580
572 void MainWindow::downloaderError(const QString &message, SSLConnection::ErrorCode error) 581 void MainWindow::downloaderError(const QString &message, SSLConnection::ErrorCode error)
573 { 582 {
574 /* TODO (issue38) handle error according to a plan */
575 syslog_error_printf ("Failed to check for updates: %s", message.toUtf8().constData()); 583 syslog_error_printf ("Failed to check for updates: %s", message.toUtf8().constData());
584 if (error == SSLConnection::InvalidCertificate) {
585 handleLTE(lteInvalidCertificate);
586 } else {
587 handleLTE(lteNoConnection);
588 }
576 #ifdef IS_TAG_BUILD 589 #ifdef IS_TAG_BUILD
577 /* During tag build it should never happen that an url checked is not available 590 /* During tag build it should never happen that an url checked is not available
578 * during development this is normal as each revision produces a new url. */ 591 * during development this is normal as each revision produces a new url. */
579 setState(TransferError); 592 setState(TransferError);
580 if (!isVisible()) { 593 if (!isVisible()) {
1645 mSettings.setValue("lastUpdateCheck", now); 1658 mSettings.setValue("lastUpdateCheck", now);
1646 mLastUpdateCheckContents->setText(QLocale::system().toString(now, DATETIME_FORMAT)); 1659 mLastUpdateCheckContents->setText(QLocale::system().toString(now, DATETIME_FORMAT));
1647 mLastUpdateCheckContents->show(); 1660 mLastUpdateCheckContents->show();
1648 mLastUpdateCheck->show(); 1661 mLastUpdateCheck->show();
1649 syslog_info_printf(tr("Sucessfully checked for updates.").toUtf8().constData()); 1662 syslog_info_printf(tr("Sucessfully checked for updates.").toUtf8().constData());
1663 handleLTE(lteNoConnection, true); /* Reset error state */
1664 handleLTE(lteInvalidCertificate, true);
1650 } 1665 }
1651 if ((getState() != NewSoftwareAvailable && getState() != NewListAvailable && mTrayMode) 1666 if ((getState() != NewSoftwareAvailable && getState() != NewListAvailable && mTrayMode)
1652 && !isVisible()) { 1667 && !isVisible()) {
1653 qDebug() << "Shutting down as no list or Software is available."; 1668 qDebug() << "Shutting down as no list or Software is available.";
1654 closeApp(); 1669 closeApp();
1702 1717
1703 void MainWindow::showErrorMessage(const QString &msg) 1718 void MainWindow::showErrorMessage(const QString &msg)
1704 { 1719 {
1705 QMessageBox::warning(this, tr("TrustBridge error"), msg); 1720 QMessageBox::warning(this, tr("TrustBridge error"), msg);
1706 } 1721 }
1722
1723 void MainWindow::handleLTE(LongTimeErrors lte, bool reset)
1724 {
1725 QString settingPrefix;
1726 switch (lte) {
1727 case lteInvalidSoftware:
1728 settingPrefix = "LTE/invalidSW";
1729 break;
1730 case lteInvalidList:
1731 settingPrefix = "LTE/invalidList";
1732 break;
1733 case lteInvalidCertificate:
1734 settingPrefix = "LTE/invalidCertificate";
1735 break;
1736 case lteNoConnection:
1737 settingPrefix = "LTE/noConnection";
1738 break;
1739 default:
1740 qDebug() << "Unhandled error. " << lte;
1741 }
1742
1743 if (reset) {
1744 /* delete all values and be done */
1745 mSettings.remove(settingPrefix + "_lastSaved");
1746 mSettings.remove(settingPrefix + "_count");
1747 mSettings.remove(settingPrefix + "_lastMsgShown");
1748 return;
1749 }
1750
1751 QDateTime lastSaved = mSettings.value(settingPrefix + "_lastSaved").toDateTime();
1752 bool cnt_valid;
1753 int cnt = mSettings.value(settingPrefix + "_count").toInt(&cnt_valid);
1754 if (!cnt_valid) {
1755 cnt = 0;
1756 }
1757
1758 if (!lastSaved.isValid() || lastSaved.daysTo(QDateTime::currentDateTime()) >= 1) {
1759 /* The error count is increased at most once a day */
1760 mSettings.setValue(settingPrefix + "_lastSaved", QDateTime::currentDateTime());
1761 mSettings.setValue(settingPrefix + "_count", ++cnt);
1762 }
1763
1764
1765 if (cnt < 7) {
1766 /* We are done */
1767 return;
1768 }
1769 /* A week has passed. Start showing the error. */
1770 QDateTime lastShown = mSettings.value(settingPrefix + "_lastShown").toDateTime();
1771 if (lastShown.isValid() && lastShown.daysTo(QDateTime::currentDateTime()) < 1) {
1772 /* Only show the error message once a day */
1773 return;
1774 }
1775
1776 mSettings.setValue(settingPrefix + "_lastShown", QDateTime::currentDateTime());
1777
1778 switch (lte) {
1779 case lteInvalidSoftware:
1780 showErrorMessage(tr("The integrity check for the available software update has "
1781 "failed repeatedly.") + "\n" +
1782 tr("Please contact your Support or the publisher of the Software."));
1783 break;
1784 case lteInvalidList:
1785 showErrorMessage(tr("The integrity check of the available certificates has "
1786 "failed repeatedly.") + "\n" +
1787 tr("Please contact your Support or the publisher of the Software."));
1788 break;
1789 case lteInvalidCertificate:
1790 showErrorMessage(tr("The authentication of the download server has "
1791 "failed repeatedly.") + "\n" +
1792 tr("Please contact your Support or the publisher of the Software."));
1793 break;
1794 case lteNoConnection:
1795 bool useProxy = mSettings.value("UseProxy", false).toBool();
1796 if (useProxy) {
1797 showErrorMessage(tr("The connection to the download server has "
1798 "failed repeatedly.") + "\n" +
1799 tr("Please check that the Proxy Server \"%1\" is available.").arg(
1800 mSettings.value("ProxyURL").toString()));
1801 } else {
1802 showErrorMessage(tr("The connection to the download server has "
1803 "failed repeatedly.") + "\n" +
1804 tr("Please check your internet connection."));
1805 }
1806 break;
1807 }
1808 }

http://wald.intevation.org/projects/trustbridge/