# HG changeset patch # User Raimund Renkert # Date 1397635262 -7200 # Node ID 55cbe0a482ce684e84f54d5728f5806e10938c58 # Parent 9e6a2c2033ed55ef07474fd1a975fe40eeabd1b9# Parent ae2ef965a41b8f322ff97dcb2afa88e724b71da2 merged. diff -r 9e6a2c2033ed -r 55cbe0a482ce cinst/main.c --- a/cinst/main.c Wed Apr 16 10:00:17 2014 +0200 +++ b/cinst/main.c Wed Apr 16 10:01:02 2014 +0200 @@ -9,18 +9,18 @@ * * The first parameter to this process should be list= * of the certificate list to work on. The second parameter should - * be instruction=|uninstall + * be choices=|uninstall * - * instruction_file_name should be the absolute path to an - * instructions file formatted as: + * choices_file_name should be the absolute path to an + * choices file formatted as: * * I: * R: * - * Line breaks can be system dependent in the Instructions file. + * Line breaks can be system dependent in the Choices file. * - * It will only execute the instructions if the - * I and R instructions are also part of the signed + * It will only execute the choices if the + * I and R choices are also part of the signed * certificate list. The signature is validated with the * built in key. * @@ -42,17 +42,17 @@ #include "windowsstore.h" #include "nssstore.h" -/* The certificate list + instructions may only be so long as +/* The certificate list + choices may only be so long as * twice the accepted certificatelist size */ #define MAX_INPUT_SIZE MAX_LINE_LENGTH * MAX_LINES * 2 /* @brief Read stdin into data structures. * - * Reads instructions from an input file into the to_install + * Reads choices from an input file into the to_install * and to_remove buffers. * - * Lines starting with I: are treated as install instructions. - * Lines starting with R: are treated as remove instructions. + * Lines starting with I: are treated as install choices. + * Lines starting with R: are treated as remove choices. * Other lines are ignored. * * Terminates in OOM conditions. @@ -60,14 +60,14 @@ * The caller needs to free the memory allocated by this function * even when an error is returned. * - * @param[in] file_name absolute path to the instructions file. - * @param[out] to_install strv of installation instructions or NULL - * @param[out] to_remove strv of remove instructions or NULL + * @param[in] file_name absolute path to the choices file. + * @param[out] to_install strv of installation choices or NULL + * @param[out] to_remove strv of remove choices or NULL * * @returns: 0 on success. An error code otherwise. */ static int -read_instructions_file (char *file_name, char ***to_install, +read_choices_file (char *file_name, char ***to_install, char ***to_remove) { int lines_read = 0; @@ -144,12 +144,12 @@ * for installation. * * @param[in] all_certs strv of all valid certificates in a list - * @param[in] to_validate strv of instructions + * @param[in] to_validate strv of choices * * @returns 0 on success, an error otherwise */ int -validate_instructions (char **all_certs, char **to_validate) +validate_choices (char **all_certs, char **to_validate) { int i = 0, j = 0; @@ -199,38 +199,38 @@ char *certificate_list = NULL, *certificate_file_name = NULL, - *instruction_file_name = NULL; + *choices_file_name = NULL; size_t list_len = 0; list_status_t list_status; bool do_uninstall = false; - /* Some very static argument parsing. list= and instructions= is only + /* Some very static argument parsing. list= and choices= is only added to make it more transparent how this programm is called if a user looks at the detailed uac dialog. */ if (argc != 3 || strncmp(argv[1], "list=", 5) != 0 || - strncmp(argv[2], "instructions=", 13) != 0) + strncmp(argv[2], "choices=", 8) != 0) { ERRORPRINTF ("Invalid arguments.\n" "Expected arguments: list= \n" - " instructions=|uninstall\n"); + " choices=|uninstall\n"); return ERR_INVALID_PARAMS; } certificate_file_name = strchr(argv[1], '=') + 1; - instruction_file_name = strchr(argv[2], '=') + 1; + choices_file_name = strchr(argv[2], '=') + 1; - if (!certificate_file_name || !instruction_file_name) + if (!certificate_file_name || !choices_file_name) { ERRORPRINTF ("Invalid arguments.\n" "Expected arguments: list= \n" - " instructions=|uninstall\n"); + " choices=|uninstall\n"); return ERR_INVALID_PARAMS; } - if (strncmp(instruction_file_name, "uninstall", 9) == 0) + if (strncmp(choices_file_name, "uninstall", 9) == 0) { do_uninstall = true; - instruction_file_name = NULL; + choices_file_name = NULL; } list_status = read_and_verify_list (certificate_file_name, &certificate_list, @@ -240,9 +240,11 @@ { if (list_status == InvalidSignature) { + ERRORPRINTF ("Failed to verify signature.\n"); return ERR_INVALID_SIGNATURE; } + ERRORPRINTF ("Failed to read certificate list.\n"); return ERR_INVALID_INPUT_NO_LIST; } @@ -269,34 +271,38 @@ return ret; } - ret = read_instructions_file (instruction_file_name, &to_install, + ret = read_choices_file (choices_file_name, &to_install, &to_remove); if (ret) { + ERRORPRINTF ("Failed to read choices file\n"); return ret; } if (!strv_length (to_install) && !strv_length (to_remove) ) { + ERRORPRINTF ("Failed to read choices file\n"); return ERR_NO_INSTRUCTIONS; } - /* Check that the instructions are ok to execute */ + /* Check that the choices are ok to execute */ if (to_install) { - ret = validate_instructions (all_valid_certs, to_install); + ret = validate_choices (all_valid_certs, to_install); if (ret) { + ERRORPRINTF ("Failed to validate choices\n"); return ret; } } if (to_remove) { - ret = validate_instructions (all_valid_certs, to_remove); + ret = validate_choices (all_valid_certs, to_remove); if (ret) { + ERRORPRINTF ("Failed to validate removal choices\n"); return ret; } } @@ -312,6 +318,7 @@ if (ret != 0) { ERRORPRINTF ("Failed to write nss stores"); + DEBUGPRINTF ("Hello World"); } /* Make valgrind happy */ diff -r 9e6a2c2033ed -r 55cbe0a482ce cinst/mozilla.c --- a/cinst/mozilla.c Wed Apr 16 10:00:17 2014 +0200 +++ b/cinst/mozilla.c Wed Apr 16 10:01:02 2014 +0200 @@ -366,13 +366,15 @@ */ static char * nss_cert_name(SECItem *secitemp) -{ char *cn_str, *o_str, *name; +{ + char *cn_str, *o_str, *name; size_t name_len; cn_str = x509_parse_subject(secitemp->data, secitemp->len, CERT_OID_CN); o_str = x509_parse_subject(secitemp->data, secitemp->len, CERT_OID_O); if (!cn_str || !o_str) { DEBUGPRINTF("FATAL: Could not parse certificate!"); + DEBUGPRINTF("data len: %u \n", secitemp->len); exit(ERR_INVALID_CERT); } name_len = strlen(cn_str) + strlen(o_str) + 4; diff -r 9e6a2c2033ed -r 55cbe0a482ce cinst/nssstore_linux.c --- a/cinst/nssstore_linux.c Wed Apr 16 10:00:17 2014 +0200 +++ b/cinst/nssstore_linux.c Wed Apr 16 10:01:02 2014 +0200 @@ -11,11 +11,57 @@ #include #include #include +#include #include "nssstore.h" #include "logging.h" #include "strhelp.h" +#define NSS_PROCESS_NAME "mozilla" + +/**@brief get the current path of the executable + * + * Looks up the current executables directory. The caller + * has to free the return value. + * + * The returned value includes the last / + * + * @returns the absolute directory of the currently executed executable or NULL + */ +char * +get_exe_dir() +{ + char *retval = NULL, + *p = NULL, + buf[PATH_MAX]; + ssize_t ret; + size_t path_len = 0; + + ret = readlink ("/proc/self/exe", buf, PATH_MAX); + if (ret <= 0) + { + ERRORPRINTF ("readlink failed\n"); + return NULL; + } + + buf[ret] = '\0'; + + /* cut off the filename */ + p = strrchr (buf, '/'); + if (p == NULL) + { + ERRORPRINTF ("No filename found.\n"); + return NULL; + } + *(p + 1) = '\0'; + + path_len = strlen (buf); + retval = xmalloc (path_len + 1); + strncpy (retval, buf, path_len); + + return retval; +} + /**@brief Start the process to install / remove * * This forks the process and executes the NSS installation @@ -35,9 +81,11 @@ { int pipe_fd[2]; pid_t pid = 0; - char *argv[] = {"mozilla", NULL}, - *envp[2]; - size_t homedir_len = 0; + char *argv[2] = {NULL, NULL}, + *envp[2] = {NULL, NULL}, + *inst_dir = NULL; + size_t homedir_len = 0, + exe_path_len = 0; int ret = -1, i = 0; FILE *stream = NULL; @@ -64,7 +112,25 @@ return -1; } - DEBUGPRINTF ("Home: %s \n", envp[0]); + /* Set up the file name of the installer process */ + inst_dir = get_exe_dir(); + if (inst_dir == NULL) + { + ERRORPRINTF ("Failed to find installation directory.\n"); + xfree (envp[0]); + return -1; + } + + exe_path_len = strlen(inst_dir) + strlen(NSS_PROCESS_NAME); + argv[0] = xmalloc (exe_path_len + 1); + + ret = snprintf(argv[0], exe_path_len + 1, "%s%s", inst_dir, NSS_PROCESS_NAME); + if (ret < 0 || (size_t) ret != exe_path_len) + { + ERRORPRINTF ("Error setting executable variable.\n"); + xfree (argv[0]); + return -1; + } if (pipe (pipe_fd)) { @@ -92,7 +158,7 @@ dup2 (pipe_fd[0], 0); close (pipe_fd[0]); /* TODO find path based on current executable */ - execve ("mozilla", argv, envp); + execve (argv[0], argv, envp); exit (127); } @@ -104,6 +170,11 @@ goto done; } + /* The NSS installer may exit on error before we are done + * telling it what to do. We want to handle that rather + * then die unexpectedly. */ + signal(SIGPIPE, SIG_IGN); + /* Send the instructions */ for (i = 0; to_install && to_install[i]; i++) { @@ -129,9 +200,10 @@ if (stream) { fclose (stream); } + xfree (argv[0]); xfree (envp[0]); - close(pipe_fd[0]); - close(pipe_fd[1]); + close (pipe_fd[0]); + close (pipe_fd[1]); if (success) { @@ -171,7 +243,6 @@ ERRORPRINTF ("Waitpid failed.\n"); return -1; } - DEBUGPRINTF ("Child returned status: %i\n", WEXITSTATUS(status)); return 0; } diff -r 9e6a2c2033ed -r 55cbe0a482ce cinst/nssstore_win.c --- a/cinst/nssstore_win.c Wed Apr 16 10:00:17 2014 +0200 +++ b/cinst/nssstore_win.c Wed Apr 16 10:01:02 2014 +0200 @@ -98,7 +98,6 @@ for (i = 0; certificates[i]; i++) { int ret = 0; - DEBUGPRINTF("Writing \n"); if (remove) ret = fprintf (write_stream, "R:%s\n", certificates[i]); else @@ -111,7 +110,6 @@ } } - DEBUGPRINTF("Write done\n"); return true; } @@ -155,12 +153,15 @@ restrict token -> hChildToken */ - cmd_line_len = wcslen (lpApplicationName) + wcslen(selection_file) + 1; + cmd_line_len = wcslen (lpApplicationName) + wcslen(selection_file) + 2; lpCommandLine = xmalloc (cmd_line_len * sizeof(wchar_t)); wcscpy_s (lpCommandLine, cmd_line_len, lpApplicationName); + wcscpy_s (lpCommandLine, cmd_line_len, L" "); wcscat_s (lpCommandLine, cmd_line_len, selection_file); + DEBUGPRINTF ("Starting %S with command line %S\n", lpApplicationName, lpCommandLine); + success = CreateProcessAsUserW (hToken, lpApplicationName, lpCommandLine, /* Commandline */ diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/renameme.nsi --- a/packaging/renameme.nsi Wed Apr 16 10:00:17 2014 +0200 +++ b/packaging/renameme.nsi Wed Apr 16 10:01:02 2014 +0200 @@ -46,43 +46,72 @@ Name "${productname}" OutFile "${setupname}" InstallDir "$PROGRAMFILES\${productname_short}" -InstType "Standard" +BrandingText "${company} - ${productname}" ;-------------------------------- -;Interface Settings +; Interface Settings -BrandingText "${company} - ${productname}" -; MUI Settings / Header -!define MUI_WELCOMEPAGE_TITLE "Willkommen bei der Installation von ${productname_short}." -!define MUI_WELCOMEPAGE_TEXT "Sie sind im Begriff ${productname} \r\n\ -zu installieren. ${productname} ist eine Anwendung um Zertifikate TODO \r\n\ -auf ihrem System zu installieren und aktualisieren." -;!define MUI_HEADERIMAGE_BITMAP "" ;TODO -;!define MUI_WELCOMEFINISHPAGE_BITMAP "ressources\welcome_left.bmp" ;TODO -!define MUI_ICON "renameme_installer.ico" +; MUI Images / Icons +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_BITMAP "resources\header-install.bmp" +!define MUI_HEADERIMAGE_UNBITMAP "resources\header-uninstall.bmp" +!define MUI_WELCOMEFINISHPAGE_BITMAP "resources\wizard-install.bmp" +!define MUI_UNWELCOMEFINISHPAGE_BITMAP "resources\wizard-uninstall.bmp" +!define MUI_ICON "resources\install.ico" +!define MUI_UNICON "resources\uninstall.ico" + +; MUI welcome page text +!define MUI_WELCOMEPAGE_TITLE "Willkommen bei der Installation des ${productname}" +!define MUI_WELCOMEPAGE_TEXT "Dieser Assistent wird Sie durch die Installation von \ +${productname} begleiten. $\r$\n$\r$\n\ +Der ${productname} ist eine Anwendung um Wurzelzertifikate auf ihrem System \ +zu installieren und aktuell zu halten. $\r$\n$\r$\n\ +Klicken Sie auf Weiter, um fortzufahren." + +!define MUI_FINISHPAGE_NOAUTOCLOSE +!define MUI_UNFINISHPAGE_NOAUTOCLOSE !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\${productname_short}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" -!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder +;-------------------------------- +; Pages +!define MUI_FINISHPAGE_TITLE "Die Installation war erfolgreich" +!define MUI_FINISHPAGE_TEXT "Der ${productname} wurde auf Ihrem \ +Computer installliert. $\r$\n$\r$\n\ +Klicken Sie auf 'Fertig stellen', um den Installations-Assistenten\ +zu schließen." !define MUI_FINISHPAGE_RUN $INSTDIR\m13ui.exe +!define MUI_FINISHPAGE_RUN_TEXT "Anwendung starten" +!define MUI_FINISHPAGE_LINK "Mehr unter http://www.bsi.bund.de" +!define MUI_FINISHPAGE_LINK_LOCATION "http://www.bsi.bund.de" !insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH +!insertmacro MUI_UNPAGE_CONFIRM +!insertmacro MUI_UNPAGE_INSTFILES + + +!insertmacro MUI_LANGUAGE "German" + + ;-------------------------------- -;Install Functions +; Install Functions + Function ".onInit" !insertmacro MULTIUSER_INIT FunctionEnd ;-------------------------------- -;UnInstall Functions +; UnInstall Functions + Function "un.onInit" !insertmacro MULTIUSER_UNINIT FunctionEnd diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/renameme_installer.ico Binary file packaging/renameme_installer.ico has changed diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/resources/certificate.ico Binary file packaging/resources/certificate.ico has changed diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/resources/header-install.bmp Binary file packaging/resources/header-install.bmp has changed diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/resources/header-uninstall.bmp Binary file packaging/resources/header-uninstall.bmp has changed diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/resources/install.ico Binary file packaging/resources/install.ico has changed diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/resources/uninstall.ico Binary file packaging/resources/uninstall.ico has changed diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/resources/wizard-install.bmp Binary file packaging/resources/wizard-install.bmp has changed diff -r 9e6a2c2033ed -r 55cbe0a482ce packaging/resources/wizard-uninstall.bmp Binary file packaging/resources/wizard-uninstall.bmp has changed diff -r 9e6a2c2033ed -r 55cbe0a482ce ui/certificate.h --- a/ui/certificate.h Wed Apr 16 10:00:17 2014 +0200 +++ b/ui/certificate.h Wed Apr 16 10:01:02 2014 +0200 @@ -128,6 +128,9 @@ **/ static QList fromFileName (const QString& file_name); + friend inline bool operator==(const Certificate& lhs, const Certificate& rhs) { + return lhs.base64Line() == rhs.base64Line(); + } private: /** @brief Helper function to parse the details of a certificate **/ void parseDetails(const QByteArray& cert); diff -r 9e6a2c2033ed -r 55cbe0a482ce ui/installwrapper.cpp --- a/ui/installwrapper.cpp Wed Apr 16 10:00:17 2014 +0200 +++ b/ui/installwrapper.cpp Wed Apr 16 10:01:02 2014 +0200 @@ -69,9 +69,6 @@ return; } - QString parameters = "\"list=" + mCertListFile + - "\" \"choices=" + choicesFile.fileName() + "\""; - #ifdef WIN32 /* QProcess on Windows uses CreateProcess but we have to * use the runas shell command to get the UAC prompt if necessary. @@ -85,6 +82,10 @@ memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); + /* Windows needs each parameter packed in " */ + QString parameters = "\"list=" + mCertListFile + + "\" \"choices=" + choicesFile.fileName() + "\""; + shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; shExecInfo.lpVerb = L"runas"; @@ -125,19 +126,30 @@ QString qerrmsg = QString::fromUtf8(errmsg); free(errmsg); emit error (tr("Failed to check process status: %1").arg(qerrmsg)); + CloseHandle(shExecInfo.hProcess); + return; } CloseHandle(shExecInfo.hProcess); if (retval != 0) { /* TODO make this nicer */ emit error (tr("The process failed with return code. %1").arg(retval)); + return; } - return; #else /* WIN32 */ QProcess installerProcess; installerProcess.setProgram(cinstProcInfo.absoluteFilePath()); - installerProcess.waitForStarted(); - if (installerProcess.state() == QProcess::NotRunning) { + QStringList parameters; + + choicesFile.setAutoRemove(false); + parameters << "list=" + mCertListFile << "choices=" + choicesFile.fileName(); + installerProcess.setArguments(parameters); + + + qDebug() << "Starting process " << cinstFileName <<" params: " << parameters; + installerProcess.start(); + if (!installerProcess.waitForStarted() || + installerProcess.state() == QProcess::NotRunning) { emit error (tr("Failed to start installer process.")); return; } @@ -146,11 +158,12 @@ if (installerProcess.exitStatus() == QProcess::CrashExit) { /* Woops */ - qWarning() << "Installer process crashed"; + emit error (tr("Failed to complete installation.")); + return; } else if (installerProcess.exitStatus() != QProcess::NormalExit) { /* Can not Happen. there are only those two values but maybe * qt changed.. */ - qWarning() << "Exit status neither normal nor crash."; + emit error (tr("Failed to complete installation.")); return; } @@ -163,4 +176,5 @@ return; } #endif + emit installationSuccessful(); } diff -r 9e6a2c2033ed -r 55cbe0a482ce ui/installwrapper.h --- a/ui/installwrapper.h Wed Apr 16 10:00:17 2014 +0200 +++ b/ui/installwrapper.h Wed Apr 16 10:01:02 2014 +0200 @@ -73,6 +73,14 @@ * @param[out] message: A localized message to show. Can be empty. */ void error(const QString &message); + + /** + * @brief The installation was successful + * + * This only means the installation was successful as far as we + * can tell as there is no backchannel from the installation processes. + */ + void installationSuccessful(); }; #endif // UI_INSTALLWRAPPER_H diff -r 9e6a2c2033ed -r 55cbe0a482ce ui/mainwindow.cpp --- a/ui/mainwindow.cpp Wed Apr 16 10:00:17 2014 +0200 +++ b/ui/mainwindow.cpp Wed Apr 16 10:01:02 2014 +0200 @@ -53,10 +53,11 @@ mMessageTimer->setInterval(NAG_INTERVAL_MINUTES * 60 * 1000); mMessageTimer->start(); checkUpdates(); + loadUnselectedCertificates(); + loadCertificateList(); if (!trayMode) { show(); } - loadUnselectedCertificates(); } void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) @@ -92,17 +93,18 @@ void MainWindow::verifyAvailableData() { - QString listFileName = mSettings.value("List/available").toString(); + QString availableFileName = mSettings.value("List/available").toString(); + QString installedFileName = mSettings.value("List/installed").toString(); QString swFileName = mSettings.value("Software/available").toString(); - if (!listFileName.isEmpty()) { - mListToInstall.readList(listFileName.toLocal8Bit().constData()); + if (!availableFileName.isEmpty()) { + mListToInstall.readList(availableFileName.toLocal8Bit().constData()); if (!mListToInstall.isValid()) { 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(listFileName); + QFile::remove(availableFileName); mSettings.remove("List/available"); mSettings.remove("List/availableDate"); } @@ -112,6 +114,22 @@ mSettings.remove("List/availableDate"); } + if (!installedFileName.isEmpty()) { + mInstalledList.readList(installedFileName.toLocal8Bit().constData()); + if (!mInstalledList.isValid()) { + // 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(installedFileName); + mSettings.remove("List/installed"); + mSettings.remove("List/installedDate"); + } + } else { + // Make sure the available notation is also removed + mSettings.remove("List/installed"); + mSettings.remove("List/installedDate"); + } + if (!swFileName.isEmpty()) { // TODO } else { @@ -158,11 +176,21 @@ QDateTime listInstalledLastMod = mSettings.value("List/installedDate").toDateTime(); QDateTime swInstalledLastMod = mSettings.value("Software/installedDate").toDateTime(); + QString listResource = QString::fromLatin1(LIST_RESOURCE); + QString swResource = QString::fromLatin1(SW_RESOURCE); + +#ifndef RELEASE_BUILD + /* Use this for testing to specify another file name for updates */ + listResource = mSettings.value("List/resource", listResource).toString(); + swResource = mSettings.value("Software/resource", swResource).toString(); +#endif + + Downloader* downloader = new Downloader(this, QString::fromLatin1(SERVER_URL), QByteArray(), QDateTime::currentDateTime(), -// swInstalledLastMod, +// TODO swInstalledLastMod, listInstalledLastMod, QString::fromLatin1(SW_RESOURCE), QString::fromLatin1(LIST_RESOURCE)); @@ -319,7 +347,13 @@ { mCertListWidget->clear(); int i = 0; - foreach (const Certificate &cert, mListToInstall.getCertificates()) { + + /* TODO: if nothing is available (neither old nor new) add some progress + * indication */ + + foreach (const Certificate &cert, mListToInstall.isValid() ? + mListToInstall.getCertificates() : + mInstalledList.getCertificates()) { if (!cert.isValid()) { qWarning() << "Invalid certificate in list"; continue; @@ -330,9 +364,14 @@ item->setData(CertificateItemDelegate::B64LineRole, cert.base64Line()); Qt::CheckState checkedState = mPreviouslyUnselected.contains(cert.base64Line()) ? Qt::Unchecked : Qt::Checked; + + bool isOld = mInstalledList.getCertificates().contains(cert); + qDebug() << "Found old certificate."; + /* TODO properly work with that information. */ + if (cert.isInstallCert()) { // This if statements is for testing! @TODO Remove this! - if (i <= 2) { + if (isOld) { item->setData(CertificateItemDelegate::StatusRole, Certificate::InstallOld); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); } @@ -407,6 +446,27 @@ QMessageBox::warning(this, tr("Error executing update"), errMsg); } +void MainWindow::installerSuccess() { + if (mCurState == NewListAvailable) { + mCurState = NothingChanged; + mCurMessage = QString(); + + QString listFileName = mSettings.value("List/available").toString(); + QDateTime listFileDate = mSettings.value("List/availableDate").toDateTime(); + + mSettings.remove("List/available"); + mSettings.remove("List/availableDate"); + + if (listFileName.isEmpty() || !listFileDate.isValid()) { + qWarning() << "Error accessing settings"; + return; /* Try again with next check */ + } + + mSettings.setValue("List/installed", listFileName); + mSettings.setValue("List/installedDate", listFileDate); + } +} + void MainWindow::installCerts() { QStringList choices; @@ -432,14 +492,18 @@ progress->show(); InstallWrapper *instWrap = new InstallWrapper(this, - mListToInstall.fileName(), + mListToInstall.isValid() ? + mListToInstall.fileName() : + mInstalledList.fileName(), choices); /* Clean up object and progress dialog */ connect(instWrap, SIGNAL(finished()), instWrap, SLOT(deleteLater())); connect(instWrap, SIGNAL(finished()), progress, SLOT(deleteLater())); connect(instWrap, SIGNAL(finished()), progress, SLOT(cancel())); + connect(instWrap, SIGNAL(installationSuccessful()), + this, SLOT(installerSuccess())); connect(instWrap, SIGNAL(error(const QString &)), - this, SLOT(installerError(const QString &))); + this, SLOT(installerError(const QString &))); instWrap->start(); if (!saveUnselectedCertificates()) { diff -r 9e6a2c2033ed -r 55cbe0a482ce ui/mainwindow.h --- a/ui/mainwindow.h Wed Apr 16 10:00:17 2014 +0200 +++ b/ui/mainwindow.h Wed Apr 16 10:01:02 2014 +0200 @@ -43,7 +43,8 @@ BeforeDownload, NewListAvailable, NewSoftwareAvailable, - TransferError + TransferError, + NothingChanged }; CurrentState getState() {return mCurState;} void setState(CurrentState state) {mCurState = state;} @@ -64,6 +65,7 @@ void showDetails(QListWidgetItem*); void resizeButtons(); void installerError(const QString& errMsg); + void installerSuccess(); void installCerts(); /** @brief saves the currently unselected certificates @@ -93,8 +95,8 @@ * Do not use this as a trust check as this only works on * FileNames where the underlying files can change. This * is just meant to check if the downloaded data was somehow - * removed or corrupted. - * + * removed or corrupted. It also initializes mListToInstall + * and mInstalledList. */ void verifyAvailableData(); void createTrayIcon(); @@ -122,6 +124,8 @@ /* The current list that should be installed */ CertificateList mListToInstall; + /* The last list that we installed */ + CertificateList mInstalledList; /* Previously made "unselect" choices in the form of * base64lines with I:/R: prefix */ QStringList mPreviouslyUnselected;