Mercurial > trustbridge
view ui/mainwindow.cpp @ 642:dd738ef17715 trustbridge-refactor
Update the 'remove untrusted' header on list selection change.
author | Raimund Renkert <rrenkert@intevation.de> |
---|---|
date | Tue, 24 Jun 2014 17:42:57 +0200 |
parents | a7c3ab273d41 |
children | f8be956c819b |
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=2) * and comes with ABSOLUTELY NO WARRANTY! * See LICENSE.txt for details. */ #include "mainwindow.h" #include <QDebug> #include <QProcess> #include <QProgressDialog> #include <QMessageBox> #include <QSystemTrayIcon> #include <QAction> #include <QDialog> #include <QDir> #include <QMenu> #include <QApplication> #include <QFile> #include <QTimer> #include <QHBoxLayout> #include <QVBoxLayout> #include <QGroupBox> #include <QSplitter> #include <QLabel> #include <QImage> #include <QCheckBox> #include <QButtonGroup> #include <QToolButton> // The amount of time in minutes stay silent if we have // something to say #define NAG_INTERVAL_MINUTES 70 #ifndef APPNAME #define APPNAME "TrustBridge" #endif #define SERVER_URL "https://files.intevation.de:443" #define LIST_RESOURCE "/users/aheinecke/zertifikatsliste.txt" #define SW_RESOURCE "/users/aheinecke/TrustBridge.exe" #ifdef Q_OS_WIN #define SW_RESOURCE_VERSION "/users/aheinecke/TrustBridge-%1.exe" #else #define SW_RESOURCE_VERSION "/users/aheinecke/TrustBridge-%1.sh" #endif #include "certificatelist.h" #include "downloader.h" #include "helpdialog.h" #include "aboutdialog.h" #include "certificateitemdelegate.h" #include "separatoritemdelegate.h" #include "installwrapper.h" #include "util.h" #include "logging.h" MainWindow::MainWindow(bool trayMode): mTrayMode(trayMode) { mUpdatesNewSize = 0; mUpdatesRemoveSize = 0; mUpdatesManualSize = 0; createActions(); createTrayIcon(); createContent(); resize(950, 540); qRegisterMetaType<SSLConnection::ErrorCode>("SSLConnection::ErrorCode"); qRegisterMetaType<Certificate::Status>("Certificate::Status"); connect(mTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); mMessageTimer = new QTimer(this); connect(mMessageTimer, SIGNAL(timeout()), this, SLOT(showMessage())); mMessageTimer->setInterval(NAG_INTERVAL_MINUTES * 60 * 1000); mMessageTimer->start(); checkUpdates(); loadUnselectedCertificates(); loadCertificateList(); if (!trayMode) { show(); } } void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) { switch (reason) { case QSystemTrayIcon::Trigger: case QSystemTrayIcon::MiddleClick: showMessage(); break; case QSystemTrayIcon::DoubleClick: show(); break; default: ; } } void MainWindow::messageClicked() { if (mCurState == NewListAvailable) { show(); } if (mCurState == NewSoftwareAvailable) { checkUpdates(true); mCurState = DownloadingSW; } } void MainWindow::showMessage() { if (!isVisible() && !mCurMessage.isEmpty()) { mTrayIcon->showMessage(QApplication::applicationName(), mCurMessage, QSystemTrayIcon::Information, 5000); mMessageTimer->start(); // Restart the timer so that we don't spam } } void MainWindow::verifyAvailableData() { QString availableFileName = mSettings.value("List/available").toString(); QString installedFileName = mSettings.value("List/installed").toString(); QString swFileName = mSettings.value("Software/available").toString(); 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(availableFileName); mSettings.remove("List/available"); mSettings.remove("List/availableDate"); } } else { // Make sure the available notation is also removed mSettings.remove("List/available"); 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 { mSettings.remove("List/installed"); mSettings.remove("List/installedDate"); } if (!swFileName.isEmpty()) { // TODO Verify integrity of the software } else { mSettings.remove("Software/available"); mSettings.remove("Software/availableDate"); } } void MainWindow::handleNewList(const QString& fileName, const QDateTime& modDate) { qDebug() << "new list available"; mSettings.setValue("List/available", fileName); mSettings.setValue("List/availableDate", modDate); verifyAvailableData(); if (!mListToInstall.isValid()) { /* Downloader provided invalid files */ /* TODO: 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())); } else { mCurMessage = tr("An updated certificate list is available. Click here to install."); setState(NewListAvailable); showMessage(); loadCertificateList(); } } void MainWindow::handleNewSW(const QString& fileName, const QDateTime& modDate) { mCurMessage = tr("An update for %1 is available.\n" "Click here to download and install the update.").arg( QApplication::applicationName()); setState(NewSoftwareAvailable); mSettings.setValue("Software/available", fileName); mSettings.setValue("Software/availableDate", modDate); mSettings.sync(); showMessage(); } void MainWindow::installNewSW(const QString& fileName, const QDateTime& modDate) { QFileInfo instProcInfo = QFileInfo(fileName); if (!instProcInfo.isExecutable()) { qWarning() << "Downloaded file: " << fileName << " is not executable."; setState(TransferError); return; } QString filePath = QDir::toNativeSeparators(instProcInfo.absoluteFilePath()); #ifdef WIN32 SHELLEXECUTEINFOW shExecInfo; memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (filePath.utf16()); shExecInfo.fMask = SEE_MASK_NOASYNC; if (!is_admin()) { shExecInfo.lpVerb = L"open"; } else { shExecInfo.lpVerb = L"runas"; } qDebug() << "Starting process: " << filePath; if (!ShellExecuteExW(&shExecInfo)) { /* Execution failed, maybe the user aborted the UAC check? */ char* errmsg = getLastErrorMsg(); QString qerrmsg = QString::fromUtf8(errmsg); free(errmsg); qDebug() << "Failed to start process: " << qerrmsg; setState(NewSoftwareAvailable); return; } #else /* WIN32 */ qDebug() << "Starting process " << filePath; if (!QProcess::startDetached(filePath)) { qDebug() << "Failed to start process."; return; } #endif /* Installer process should now be running. We exit */ closeApp(); } void MainWindow::checkUpdates(bool downloadSW) { verifyAvailableData(); if (!mSettings.contains("Software/installedDate") || mSettings.value("Software/installedVersion").toString() != QApplication::applicationVersion()) { /* This should only happen on initial startup and after an update has * been installed */ getLastModForCurrentVersion(); return; } 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(), swInstalledLastMod, listInstalledLastMod, swResource, listResource, downloadSW); connect(downloader, SIGNAL(newListAvailable(const QString&, const QDateTime&)), this, SLOT(handleNewList(const QString&, const QDateTime&))); if (!downloadSW) { connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)), this, SLOT(handleNewSW(const QString&, const QDateTime&))); } else { connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)), this, SLOT(installNewSW(const QString&, const QDateTime&))); } connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater())); connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); downloader->start(); } void MainWindow::getLastModForCurrentVersion() { QString softwareVersion = QString::fromLatin1(SW_RESOURCE_VERSION).arg( QApplication::applicationVersion()); qDebug() << softwareVersion; QString listResource = QString::fromLatin1(LIST_RESOURCE); Downloader* downloader = new Downloader(this, QString::fromLatin1(SERVER_URL), QByteArray(), QDateTime::currentDateTime(), QDateTime::currentDateTime(), softwareVersion, listResource, false); connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater())); connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); connect(downloader, SIGNAL(lastModifiedDate(const QDateTime&)), this, SLOT(setLastModifiedSWDate(const QDateTime&))); downloader->start(); } void MainWindow::setLastModifiedSWDate(const QDateTime &date) { mSettings.beginGroup("Software"); mSettings.setValue("installedDate", date); mSettings.setValue("installedVersion", QApplication::applicationVersion()); mSettings.endGroup(); checkUpdates(); } void MainWindow::downloaderError(const QString &message, SSLConnection::ErrorCode error) { /* TODO logging and handle error according to a plan */ mCurMessage = message; showMessage(); setState(TransferError); } void MainWindow::createActions() { mCheckUpdates = new QAction(tr("Check for Updates"), this); connect(mCheckUpdates, SIGNAL(triggered()), this, SLOT(checkUpdates())); mQuitAction = new QAction(tr("Quit"), this); connect(mQuitAction, SIGNAL(triggered()), qApp, SLOT(quit())); } void MainWindow::createTrayIcon() { QIcon trayImg(":/img/tray_22.png"); mTrayMenu = new QMenu(this); mTrayMenu->addAction(mCheckUpdates); mTrayMenu->addAction(mQuitAction); mTrayIcon = new QSystemTrayIcon(this); mTrayIcon->setContextMenu(mTrayMenu); mTrayIcon->setIcon(trayImg); setWindowIcon(trayImg); mTrayIcon->show(); mTrayIcon->setToolTip(tr("TrustBridge")); connect(mTrayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked())); } void MainWindow::createContent() { // Create a central widget containing the main layout. QWidget *base = new QWidget; // Layouts and Container QVBoxLayout *mainLayout = new QVBoxLayout; QHBoxLayout *headerLayout = new QHBoxLayout; QVBoxLayout *headerTextLayout = new QVBoxLayout; QHBoxLayout *centerLayout = new QHBoxLayout; QVBoxLayout *buttonBarLayout = new QVBoxLayout; QHBoxLayout *bottomLayout = new QHBoxLayout; QHBoxLayout *containerLayout = new QHBoxLayout; QVBoxLayout *updatesPanelLayout = new QVBoxLayout; // The header (icon, about text) QImage *logoImage = new QImage(":/img/logo.png"); QLabel *logo = new QLabel; logo->setBackgroundRole(QPalette::Base); logo->setPixmap(QPixmap::fromImage(*logoImage)); QLabel *title = new QLabel("<h1>" + QString::fromLatin1(APPNAME) + "</h1>"); QLabel *subTitle = new QLabel("This Software installs and removes Certificates"); headerTextLayout->addWidget(title); headerTextLayout->addWidget(subTitle); headerLayout->addWidget(logo); headerLayout->addLayout(headerTextLayout); headerLayout->setStretch(0, 0); headerLayout->setStretch(1, 10); // Buttonbar mButtonGroup = new QButtonGroup; QToolButton *updatesButton = new QToolButton; updatesButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); updatesButton->setIcon(QIcon(":/img/view-refresh.png")); updatesButton->setIconSize(QSize(32, 32)); updatesButton->setText(tr("Updates")); updatesButton->setFixedWidth(90); updatesButton->setFixedHeight(70); updatesButton->setCheckable(true); updatesButton->setChecked(true); QToolButton *allInstallButton = new QToolButton; allInstallButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); allInstallButton->setIcon(QIcon(":/img/document-encrypt.png")); allInstallButton->setIconSize(QSize(32, 32)); allInstallButton->setText(tr("Trusted\nCertificates")); allInstallButton->setFixedWidth(90); allInstallButton->setFixedHeight(70); allInstallButton->setCheckable(true); QToolButton *allRemoveButton = new QToolButton; allRemoveButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); allRemoveButton->setIcon(QIcon(":/img/task-attempt.png")); allRemoveButton->setIconSize(QSize(32, 32)); allRemoveButton->setText(tr("Insecure\nCertificates")); allRemoveButton->setFixedWidth(90); allRemoveButton->setFixedHeight(70); allRemoveButton->setCheckable(true); QToolButton *infoButton = new QToolButton; infoButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); infoButton->setIcon(QIcon(":/img/dialog-information.png")); infoButton->setIconSize(QSize(32, 32)); infoButton->setText(tr("Information")); infoButton->setFixedWidth(90); infoButton->setFixedHeight(70); infoButton->setCheckable(true); mButtonGroup->addButton(updatesButton); mButtonGroup->addButton(allInstallButton); mButtonGroup->addButton(allRemoveButton); mButtonGroup->addButton(infoButton); mButtonGroup->setId(updatesButton, 0); mButtonGroup->setId(allInstallButton, 1); mButtonGroup->setId(allRemoveButton, 2); mButtonGroup->setId(infoButton, 3); connect(mButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(togglePages(int))); buttonBarLayout->addWidget(updatesButton); buttonBarLayout->addWidget(allInstallButton); buttonBarLayout->addWidget(allRemoveButton); buttonBarLayout->insertStretch(3, 10); buttonBarLayout->addWidget(infoButton); //The main panels. //The updates page. mUpdatesPanel = new QScrollArea; mUpdatesWidget = new QWidget; QHBoxLayout *updatesHeaderLayout = new QHBoxLayout; QVBoxLayout *updatesHeaderTextLayout = new QVBoxLayout; QVBoxLayout *updatesHeaderSettLayout = new QVBoxLayout; mUpdatesHeader = new QLabel("<h2>" + tr("Updates (%1/%2)").arg(2).arg(4)+ "</h2>"); mLastCertUpdate = new QLabel(tr("Last certificate update: %1").arg("today")); mLastSWupdate = new QLabel(tr("Last Software update: %1").arg("today")); updatesHeaderTextLayout->addWidget(mUpdatesHeader); updatesHeaderTextLayout->addWidget(mLastCertUpdate); updatesHeaderTextLayout->addWidget(mLastSWupdate); QPushButton *searchUpdates = new QPushButton(tr("Search for Updates")); connect(searchUpdates, SIGNAL(clicked()), this, SLOT(checkUpdates())); updatesHeaderSettLayout->insertStretch(0, 10); updatesHeaderSettLayout->addWidget(searchUpdates); updatesHeaderLayout->addLayout(updatesHeaderTextLayout); updatesHeaderLayout->insertStretch(1, 10); updatesHeaderLayout->addLayout(updatesHeaderSettLayout); QVBoxLayout *updatesCenterLayout = new QVBoxLayout; QHBoxLayout *updatesNewLayout = new QHBoxLayout; QHBoxLayout *updatesRemoveLayout = new QHBoxLayout; QHBoxLayout *updatesManualLayout = new QHBoxLayout; QLabel *updatesTip = new QLabel(tr("The following certificate changes are recommended.")); mUpdatesNewCertificates = new QLabel("<h3>" + tr("Install new Certificates (%1/%2)").arg(2).arg(2) + "</h3>"); QPushButton *updatesDetailsNew = new QPushButton(tr("Details")); connect(updatesDetailsNew, SIGNAL(clicked()), this, SLOT(toggleUpdatesNew())); updatesNewLayout->addWidget(mUpdatesNewCertificates); updatesNewLayout->addWidget(updatesDetailsNew); updatesNewLayout->insertStretch(2, 10); mUpdatesNew = new CertificateListWidget(this); connect(mUpdatesNew, SIGNAL(certListChanged(int)), this, SLOT(listChanged(int))); mUpdatesNew->hide(); mUpdatesRemoveCertificates = new QLabel("<h3>" + tr("Remove insecure Certificates (%1/%2)").arg(2).arg(2) + "</h3>"); QPushButton *updatesDetailsRemove = new QPushButton(tr("Details")); connect(updatesDetailsRemove, SIGNAL(clicked()), this, SLOT(toggleUpdatesRemove())); updatesRemoveLayout->addWidget(mUpdatesRemoveCertificates); updatesRemoveLayout->addWidget(updatesDetailsRemove); updatesRemoveLayout->insertStretch(2, 10); mUpdatesRemove = new CertificateListWidget(this); connect(mUpdatesRemove, SIGNAL(certListChanged(int)), this, SLOT(listChanged(int))); mUpdatesRemove->hide(); mUpdatesManualCertificates = new QLabel("<h3>" + tr("Manualy changed Certificates (%1)").arg(2) + "</h3>"); QPushButton *updatesDetailsManual = new QPushButton(tr("Details")); connect(updatesDetailsManual, SIGNAL(clicked()), this, SLOT(toggleUpdatesManual())); updatesManualLayout->addWidget(mUpdatesManualCertificates); updatesManualLayout->addWidget(updatesDetailsManual); updatesManualLayout->insertStretch(2, 10); mUpdatesManual = new CertificateListWidget(this); mUpdatesManual->hide(); connect(mUpdatesManual, SIGNAL(certChanged(bool, const Certificate&)), this, SLOT(removeFromManual(bool, const Certificate&))); QHBoxLayout *updatesBottomLayout = new QHBoxLayout; QPushButton *quitButton = new QPushButton(tr("Quit without saving")); QPushButton *installButton = new QPushButton(tr("Update")); #ifdef Q_OS_WIN if (is_admin()) { QIcon uacShield = QApplication::style()->standardIcon(QStyle::SP_VistaShield); installButton->setIcon(uacShield); } #endif connect(quitButton, SIGNAL(clicked()), this, SLOT(closeApp())); connect(installButton, SIGNAL(clicked()), this, SLOT(installCerts())); updatesBottomLayout->insertStretch(0, 10); updatesBottomLayout->addWidget(installButton); updatesBottomLayout->addWidget(quitButton); updatesBottomLayout->setAlignment(Qt::AlignBottom); updatesNewLayout->setAlignment(Qt::AlignTop); updatesRemoveLayout->setAlignment(Qt::AlignTop); updatesManualLayout->setAlignment(Qt::AlignTop); updatesCenterLayout->addWidget(updatesTip, 0, Qt::AlignTop); updatesCenterLayout->addLayout(updatesNewLayout); // updatesCenterLayout->setStretchFactor(updatesNewLayout, 100); updatesCenterLayout->addWidget(mUpdatesNew, 1, Qt::AlignTop); updatesCenterLayout->addLayout(updatesRemoveLayout); // updatesCenterLayout->setStretchFactor(updatesRemoveLayout, 100); updatesCenterLayout->addWidget(mUpdatesRemove, 1, Qt::AlignTop); updatesCenterLayout->addLayout(updatesManualLayout); // updatesCenterLayout->setStretchFactor(updatesManualLayout, 100); updatesCenterLayout->addWidget(mUpdatesManual, 1, Qt::AlignTop); updatesCenterLayout->insertStretch(7, 0); updatesCenterLayout->addLayout(updatesBottomLayout); QFrame *updatesPanelSeparator = new QFrame(); updatesPanelSeparator->setFrameShape(QFrame::HLine); updatesPanelSeparator->setFrameShadow(QFrame::Sunken); updatesPanelLayout->addLayout(updatesHeaderLayout); updatesPanelLayout->addWidget(updatesPanelSeparator); updatesPanelLayout->addLayout(updatesCenterLayout); updatesPanelLayout->setStretchFactor(updatesCenterLayout, 1); //updatesPanelLayout->insertStretch(3, 2); //updatesPanelLayout->addLayout(updatesBottomLayout); mUpdatesWidget->setLayout(updatesPanelLayout); mUpdatesWidget->setMinimumSize(QSize(820, 440)); mUpdatesPanel->setWidget(mUpdatesWidget); // Panel for trusted certificates. mInstallPanel = new QScrollArea; QVBoxLayout *installPanelLayout = new QVBoxLayout; QVBoxLayout *installHeaderLayout = new QVBoxLayout; QVBoxLayout *installCenterLayout = new QVBoxLayout; QLabel *installHeaderLabel = new QLabel("<h2>" + tr("Trusted Certificates") + "</h2>"); QLabel *installHeaderText = new QLabel(tr("The following list of root" " certificates was created by the BSI. The BSI vaidates authenticity," " security and actuality of these certificates")); installHeaderLayout->addWidget(installHeaderLabel); installHeaderLayout->addWidget(installHeaderText); QLabel *installCenterText = new QLabel(tr("Please choose the certificates" " you want to trust. TrustBridge will install these certificates for" " secure communication via email or the internet (e.g. IE, Firefox," " Thunderbird)")); installCenterLayout->addWidget(installCenterText); mInstallList = new CertificateListWidget(this); connect(mInstallList, SIGNAL(certChanged(bool, const Certificate&)), this, SLOT(toggleInManual(bool, const Certificate&))); installPanelLayout->addLayout(installHeaderLayout); installPanelLayout->addLayout(installCenterLayout); installPanelLayout->addWidget(mInstallList); mInstallPanel->setLayout(installPanelLayout); // Panel for insecure certificates. mRemovePanel = new QScrollArea; QVBoxLayout *removePanelLayout = new QVBoxLayout; QVBoxLayout *removeHeaderLayout = new QVBoxLayout; QVBoxLayout *removeCenterLayout = new QVBoxLayout; QLabel *removeHeaderLabel = new QLabel("<h2>" + tr("Insecure Certificates") + "</h2>"); QLabel *removeHeaderText = new QLabel(tr("The following list of root" " certificates was created by the BSI. The BSI validates authenticity," " security and actuality of these certificates")); removeHeaderLayout->addWidget(removeHeaderLabel); removeHeaderLayout->addWidget(removeHeaderText); QLabel *removeCenterText = new QLabel(tr("Please choose the certificates" " you want to remove. TrustBridge will remove these certificates.")); removeCenterLayout->addWidget(removeCenterText); mRemoveList = new CertificateListWidget(this); connect(mRemoveList, SIGNAL(certChanged(bool, const Certificate&)), this, SLOT(toggleInManual(bool, const Certificate&))); removePanelLayout->addLayout(removeHeaderLayout); removePanelLayout->addLayout(removeCenterLayout); removePanelLayout->addWidget(mRemoveList); mRemovePanel->setLayout(removePanelLayout); // Info panel. mInfoPanel = new QScrollArea; QVBoxLayout *infoPanelLayout = new QVBoxLayout(this); QHBoxLayout *infoHeaderLayout = new QHBoxLayout; QVBoxLayout *infoHeaderTextLayout = new QVBoxLayout; QVBoxLayout *infoCenterLayout = new QVBoxLayout; QImage *infoLogoImage = new QImage(":/img/logo.png"); QLabel *infoLogo = new QLabel; infoLogo->setBackgroundRole(QPalette::Base); infoLogo->setPixmap(QPixmap::fromImage(*infoLogoImage)); QLabel *infoTitle = new QLabel("<h1>" + tr("TrustBridge") + "</h1>"); QString infoVersion = tr("Version: "); infoVersion.append(QApplication::applicationVersion()); QLabel *appVersion = new QLabel(infoVersion); appVersion->setTextInteractionFlags( Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); QFrame *infoHeaderSeparator = new QFrame(); infoHeaderSeparator->setFrameShape(QFrame::HLine); infoHeaderSeparator->setFrameShadow(QFrame::Sunken); infoHeaderTextLayout->addWidget(infoTitle); infoHeaderTextLayout->addWidget(appVersion); infoHeaderLayout->addWidget(infoLogo); infoHeaderLayout->addLayout(infoHeaderTextLayout); infoHeaderLayout->insertStretch(2, 10); QLabel *textDesc = new QLabel(tr("TrustBridge is a root certificate" " installer for Windows and Linux.")); textDesc->setTextInteractionFlags( Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); QLabel *textManage = new QLabel(tr("The root certificate lists are managed" " by the German <a href=\"https://www.bsi.bund.de\">" "Federal Office for Information Security (BSI)</a>.\n\n")); textManage->setTextInteractionFlags( Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard); QLabel *textDevel = new QLabel(tr("The software was developed by the companies" " <a href=\"http://www.intevation.de\">Intevation GmbH</a> and " " <a href=\"http://www.dn-systems.de\">DN-Systems GmbH</a>, <br>" " contracted by the German Federal Office for Information Security (BSI).\n\n")); textDevel->setTextInteractionFlags( Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard); QLabel *textLicense = new QLabel(tr("TrustBridge is Free Software licensed" " under GNU GPL v2+.\n\nCopyright (C) 2014 by Bundesamt für Sicherheit" " in der Informationstechnik")); textLicense->setTextInteractionFlags( Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); infoCenterLayout->addWidget(infoHeaderSeparator); infoCenterLayout->addWidget(textDesc); infoCenterLayout->addWidget(textManage); infoCenterLayout->addWidget(textDevel); infoCenterLayout->addWidget(textLicense); infoCenterLayout->insertSpacing(2, 10); infoCenterLayout->insertSpacing(4, 10); infoCenterLayout->insertSpacing(6, 10); infoCenterLayout->insertStretch(8, 10); infoPanelLayout->addLayout(infoHeaderLayout); infoPanelLayout->addLayout(infoCenterLayout); mInfoPanel->setLayout(infoPanelLayout); // The main layout for pages. mInstallPanel->hide(); mRemovePanel->hide(); mInfoPanel->hide(); containerLayout->addWidget(mUpdatesPanel); containerLayout->addWidget(mInstallPanel); containerLayout->addWidget(mRemovePanel); containerLayout->addWidget(mInfoPanel); centerLayout->addLayout(buttonBarLayout); centerLayout->addLayout(containerLayout); QFrame *topSeparator = new QFrame(); topSeparator->setFrameShape(QFrame::HLine); topSeparator->setFrameShadow(QFrame::Sunken); mainLayout->addLayout(headerLayout); mainLayout->addWidget(topSeparator); mainLayout->addLayout(centerLayout); mainLayout->addLayout(bottomLayout); base->setLayout(mainLayout); setCentralWidget(base); } void MainWindow::listChanged(int selected) { mUpdatesHeader->setText("<h2>" + tr("Updates (%1/%2)") .arg(mUpdatesRemove->selectedCertCount() + mUpdatesNew->selectedCertCount()) .arg(mUpdatesRemove->certificates().size() + mUpdatesNew->certificates().size()) + "</h2>"); mUpdatesNewCertificates->setText("<h3>" + tr("Install new Certificates (%1/%2)") .arg(mUpdatesNew->selectedCertCount()) .arg(mUpdatesNew->certificates().size()) + "</h3>"); mUpdatesRemoveCertificates->setText("<h3>" + tr("Remove insecure Certificates (%1/%2)") .arg(mUpdatesRemove->selectedCertCount()) .arg(mUpdatesRemove->certificates().size()) + "</h3>"); } void MainWindow::loadCertificateList() { /* TODO: if nothing is available (neither old nor new) add some progress * indication */ mInstallList->clear(); mUpdatesNew->clear(); mRemoveList->clear(); mUpdatesRemove->clear(); QList<Certificate> newInstallCerts; QList<Certificate> newRemoveCerts; QList<Certificate> oldInstallCerts; QList<Certificate> oldRemoveCerts; if (mListToInstall.getCertificates().isEmpty()) { // No new list available, add old certificates. foreach (const Certificate &cert, mInstalledList.getCertificates()) { bool state = !mPreviouslyUnselected.contains(cert.base64Line()); if (cert.isInstallCert()) { oldInstallCerts.append(cert); mInstallList->addCertificate(cert, state); } else { oldRemoveCerts.append(cert); mRemoveList->addCertificate(cert, state, !state); } } // Set the date of the old list. // mCurrentListDate->setText(tr("Current List Date: %1") // .arg(mInstalledList.date().toString())); } else { // Sort and filter both lists. foreach (const Certificate &cert, mListToInstall.getCertificates()) { bool state = !mPreviouslyUnselected.contains(cert.base64Line()); if (cert.isInstallCert()) { // Certificate with status "install". if (mInstalledList.getCertificates().contains(cert)) { // Was in the old list. oldInstallCerts.append(cert); mInstallList->addCertificate(cert, state); } else { // Is a brand new certificate newInstallCerts.append(cert); mUpdatesNew->addCertificate(cert, state); } } else { // Certificate with status "remove". if (mInstalledList.getCertificates().contains(cert)) { // Was in the old list. oldRemoveCerts.append(cert); // Is removed, so set editable to false. mRemoveList->addCertificate(cert, state, !state); } else { // Was in the old list with status "install" and now has the // status "remove". newRemoveCerts.append(cert); mUpdatesRemove->addCertificate(cert, state); } } } mUpdatesHeader->setText("<h2>" + tr("Updates (%1/%2)") .arg(mUpdatesNew->selectedCertCount() + mUpdatesRemove->selectedCertCount()) .arg(newRemoveCerts.size() + newInstallCerts.size()) + "</h2>"); mLastCertUpdate->setText(tr("Last certificate update: %1") .arg(mInstalledList.date().toString())); /* mCurrentListDate->setText(tr("Current List Date: %1") .arg(mInstalledList.date().toString())); mNewListDate->setText(tr("New List Date: %1").arg(mListToInstall.date().toString()));*/ } mUpdatesNewCertificates->setText("<h3>" + tr("Install new Certificates (%1/%2)") .arg(mUpdatesNew->selectedCertCount()) .arg(mUpdatesNew->certificates().size()) + "</h3>"); mUpdatesRemoveCertificates->setText("<h3>" + tr("Remove insecure Certificates (%1/%2)") .arg(mUpdatesRemove->selectedCertCount()) .arg(mUpdatesRemove->certificates().size()) + "</h3>"); mUpdatesManualCertificates->setText("<h3>" + tr("Manualy changed Certificates (%1)").arg(0) + "</h3>"); } void MainWindow::installerError(const QString& errMsg) { 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); mInstalledList = mListToInstall; mListToInstall = CertificateList(); } loadCertificateList(); } void MainWindow::installCerts() { QStringList choices; QStringList unselected; choices << mUpdatesNew->selectedCertificates(); choices << mUpdatesRemove->selectedCertificates(); choices << mUpdatesManual->selectedCertificates(); QStringList unselectedManuals = mUpdatesManual->unselectedCertificates(); for(int i = 0; i < unselectedManuals.size(); i++) { if (unselectedManuals.at(i).startsWith("I:")) { QString certLine = unselectedManuals.at(i); certLine[0] = 'R'; choices << certLine; } } unselected << mUpdatesNew->unselectedCertificates(); unselected << mUpdatesRemove->unselectedCertificates(); unselected << mInstallList->unselectedCertificates(); unselected << mRemoveList->unselectedCertificates(); QProgressDialog *progress = new QProgressDialog(this); progress->setWindowModality(Qt::WindowModal); progress->setLabelText(tr("Installing certificates...")); progress->setCancelButton(0); progress->setRange(0,0); progress->setMinimumDuration(0); progress->show(); InstallWrapper *instWrap = new InstallWrapper(this, 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 &))); instWrap->start(); if (!saveUnselectedCertificates(unselected)) { qWarning() << "Failed to save previosly unselected certificates."; } } void MainWindow::loadUnselectedCertificates() { mPreviouslyUnselected.clear(); mSettings.beginGroup("unselected"); QStringList keys = mSettings.allKeys(); foreach (const QString &key, keys) { mPreviouslyUnselected << mSettings.value(key, QString()).toString(); } mSettings.endGroup(); } bool MainWindow::saveUnselectedCertificates(QStringList unselected) { mPreviouslyUnselected.clear(); mSettings.beginGroup("unselected"); mSettings.remove(""); /* Clears old choices */ for (int i = 0; i < unselected.size(); i++) { QString key = QString::fromLatin1("cert%1").arg(i); QString value = unselected.at(i); mSettings.setValue(key, value); mPreviouslyUnselected << value; } mSettings.endGroup(); mSettings.sync(); return mSettings.status() == QSettings::NoError; } void MainWindow::toggleInManual(bool state, const Certificate &cert) { if (!mUpdatesManual->contains(cert)) { mUpdatesManual->addCertificate(cert, state); } else { mUpdatesManual->removeCertificate(cert); } mUpdatesManualCertificates->setText("<h3>" + tr("Manualy changed Certificates (%1)") .arg(mUpdatesManual->certificates().size()) + "</h3>"); } void MainWindow::removeFromManual(bool state, const Certificate &cert) { mUpdatesManual->removeCertificate(cert); mUpdatesManualCertificates->setText("<h3>" + tr("Manualy changed Certificates (%1)") .arg(mUpdatesManual->certificates().size()) + "</h3>"); if (cert.isInstallCert()) { mInstallList->setCertState(state, cert); } else { mRemoveList->setCertState(state, cert); } } void MainWindow::closeApp() { qApp->quit(); } void MainWindow::togglePages(int button) { mUpdatesPanel->hide(); mInstallPanel->hide(); mRemovePanel->hide(); mInfoPanel->hide(); switch(button) { case 0: mUpdatesPanel->show(); break; case 1: mInstallPanel->show(); break; case 2: mRemovePanel->show(); break; case 3: mInfoPanel->show(); break; default: mUpdatesPanel->show(); break; } return; } void MainWindow::toggleUpdatesNew() { QSize old = mUpdatesWidget->size(); if (!mUpdatesNew->isVisible()) { mUpdatesNew->show(); if (mUpdatesNewSize == 0) { mUpdatesNewSize = mUpdatesNew->height(); } mUpdatesWidget->resize(old.width(), old.height() + mUpdatesNewSize); } else { mUpdatesWidget->resize(old.width(), old.height() - mUpdatesNew->height()); mUpdatesNew->hide(); } } void MainWindow::toggleUpdatesRemove() { QSize old = mUpdatesWidget->size(); if (!mUpdatesRemove->isVisible()) { mUpdatesRemove->show(); if (mUpdatesRemoveSize == 0) { mUpdatesRemoveSize = mUpdatesRemove->height(); } mUpdatesWidget->resize(old.width(), old.height() + mUpdatesRemoveSize); } else { mUpdatesWidget->resize(old.width(), old.height() - mUpdatesRemove->height()); mUpdatesRemove->hide(); } } void MainWindow::toggleUpdatesManual() { QSize old = mUpdatesWidget->size(); if (!mUpdatesManual->isVisible()) { mUpdatesManual->show(); if (mUpdatesManualSize == 0) { mUpdatesManualSize = mUpdatesManual->height(); } mUpdatesWidget->resize(old.width(), old.height() + mUpdatesManualSize); } else { mUpdatesWidget->resize(old.width(), old.height() - mUpdatesManual->height()); mUpdatesManual->hide(); } }