view ui/administratorwindow.cpp @ 1088:508c96e72f62

(issue124) Switch server URL and remove some RELEASE_BUILD options As the test server speaks ECDSA we do not need so much #ifndef RELEASE_BUILD options anymore.
author Andre Heinecke <andre.heinecke@intevation.de>
date Fri, 12 Sep 2014 15:38:42 +0200
parents 0b7bb4f68f5a
children bd2cb6bdb1c5
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 "administratorwindow.h"

#include <QDebug>
#include <QMessageBox>
#include <QAction>
#include <QMenu>
#include <QApplication>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QSplitter>
#include <QLabel>
#include <QImage>
#include <QCheckBox>
#include <QHeaderView>
#include <QFileDialog>
#include <QStandardPaths>
#include <QSortFilterProxyModel>
#include <QDesktopServices>
#include <QFileInfo>

#include "certificatetabledelegate.h"
#include "createinstallerdialog.h"
#include "createcertlistdialog.h"
#include "certificatediffdialog.h"
#include "aboutdialog.h"
#include "util.h"

#define HELP_PATH "/doc/index.html"

AdministratorWindow::AdministratorWindow() {
    setWindowTitle(tr("TrustBridge Administration"));
    QString path = QStandardPaths::locate(
        QStandardPaths::DataLocation, QString("current_certificates.txt"));
    mCertList.readList(path.toLocal8Bit());
    createActions();
    createMenuBar();
    createContent();
    loadCertificateTable();
    resize(1190, 500);
}

void AdministratorWindow::createActions()
{
}

void AdministratorWindow::createMenuBar()
{
    menuBar = new QMenuBar(this);
    QMenu *menu = new QMenu(tr("Menu"), menuBar);
    menuBar->addMenu(menu);
    QAction *createInstaller = menu->addAction(tr("Create installer ..."));
    QAction *about = menu->addAction(tr("About TrustBridge"));
    QAction *help = menu->addAction(tr("Help"));
    help->setIcon(QIcon(":/img/show-help_16.png"));
    menu->addSeparator();
    QAction *quit = menu->addAction(tr("Quit"));
    connect(createInstaller, SIGNAL(triggered()), this, SLOT(createInstaller()));
    connect(about, SIGNAL(triggered()), this, SLOT(showAbout()));
    connect(help, SIGNAL(triggered()), this, SLOT(showHelp()));
    connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
    setMenuBar(menuBar);
}

void AdministratorWindow::createContent()
{
    // Create a central widget containing the main layout.
    QWidget *base = new QWidget;

    // Layouts and Container
    QVBoxLayout *mainLayout = new QVBoxLayout;
    QVBoxLayout *certLayout = new QVBoxLayout;
    QHBoxLayout *headerLayout = new QHBoxLayout;
    QVBoxLayout *headerTextLayout = new QVBoxLayout;
    QHBoxLayout *bottomLayout = new QHBoxLayout;

    // The certificate list
    QGroupBox *certBox = new QGroupBox(
        tr("All managed root certificates of the certificate list: "));
    certificateView = new QTableView;
    certificateModel = new CertificateTabelModel();
    QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(this);
    filterModel->setSourceModel(certificateModel);
    CertificateTableDelegate *delegate = new CertificateTableDelegate(certificateView);
    certificateView->setModel(filterModel);
    certificateView->setItemDelegate(delegate);
    certificateView->horizontalHeader()->setStretchLastSection(true);
    certificateView->resizeColumnsToContents();
    certificateView->setColumnWidth(0, 60);
    certificateView->setSelectionBehavior(QAbstractItemView::SelectRows);
    connect(certificateView, SIGNAL(clicked(const QModelIndex&)), this,
        SLOT(clickedCertificate(const QModelIndex&)));
    certificateView->verticalHeader()->setVisible(false);
    certificateView->setSortingEnabled(true);
    certLayout->addWidget(certificateView);
    certBox->setLayout(certLayout);

    // 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("<h2>" + tr("TrustBridge Administration") + "</h2>");
    QLabel *subTitle = new QLabel(
        tr("Management application of the BSI certificate installer"));
    headerTextLayout->addWidget(title);
    headerTextLayout->addWidget(subTitle);
    headerLayout->addWidget(logo);
    headerLayout->addLayout(headerTextLayout);
    headerLayout->setStretch(0, 0);
    headerLayout->setStretch(1, 10);

    // The buttons.
    bottomLayout->setAlignment(Qt::AlignBottom);
    saveButton = new QPushButton(QIcon(":/img/document-save.png"), tr("Save list"));
    connect(saveButton, SIGNAL(clicked()), this, SLOT(saveCertificateFile()));
    loadButton = new QPushButton(QIcon(":/img/document-open.png"), tr("Load list"));
    connect(loadButton, SIGNAL(clicked()), this, SLOT(loadCertificateFile()));
    addButton = new QPushButton(QIcon(":/img/document-new.png"), tr("Add certificate"));
    connect(addButton, SIGNAL(clicked()), this, SLOT(addCertificates()));
    removeButton = new QPushButton(QIcon(":/img/document-close.png"), tr("Remove certificate"));
    removeButton->setEnabled(false);
    connect(removeButton, SIGNAL(clicked()), this, SLOT(removeCertificates()));
    bottomLayout->addWidget(saveButton);
    bottomLayout->addWidget(loadButton);
    bottomLayout->addWidget(addButton);
    bottomLayout->addWidget(removeButton);
    bottomLayout->insertStretch(4, 10);

    mainLayout->addLayout(headerLayout);
    mainLayout->addWidget(certBox);
    mainLayout->addLayout(bottomLayout);


    // QMainWindow allready has a layout. All child layouts and widgets are
    // managed in the central widget.
    base->setLayout(mainLayout);
    setCentralWidget(base);
}

void AdministratorWindow::loadCertificateFile()
{
    QString lastCertFile = mSettings.value("LastCertList", QDir::homePath()).toString();
    QString certFile = QFileDialog::getOpenFileName(
        this, tr("Select certificate list file"), lastCertFile, "*.txt");
    if (certFile.isNull()) {
        return;
    }
    mCertList.readList(certFile.toLocal8Bit().constData());
    if (!mCertList.isValid()) {
        QMessageBox::warning(this, tr("Error!"), tr("Failed to load the certificate list."));
    } else {
        certificateModel->removeAll();
        loadCertificateTable();
        mSettings.setValue("LastCertList", certFile);
    }
}

void AdministratorWindow::saveCertificateFile()
{
    CertificateDiffDialog *diffDialog = new CertificateDiffDialog(this);
    int ret = diffDialog->exec();
    if (ret == QDialog::Accepted) {
        CreateCertListDialog *dialog = new CreateCertListDialog(this);
        dialog->show();
    }
}

void AdministratorWindow::addCertificates()
{
    QStringList certFiles = QFileDialog::getOpenFileNames(
        this, tr("Select certificate"), QDir::homePath(), "*.pem *.der *.crt *.cer");
    for (int i = 0; i < certFiles.size(); i++) {
        QString certFile = certFiles.at(i);
        QList<Certificate> certs = Certificate::fromFileName(certFile);
        addToCertificateTable(certs);
    }
    certificateView->resizeColumnsToContents();
    certificateView->setColumnWidth(0, 60);
}

void AdministratorWindow::removeCertificates()
{
    QModelIndexList list = certificateView->selectionModel()->selectedRows();
    for (int i = list.size() -1 ; i >= 0; i--) {
        certificateModel->removeRow(list.at(i).row(), list.at(i));
    }
}

void AdministratorWindow::loadCertificateTable() {
    foreach(const Certificate &cert, mCertList.getCertificates()) {
        certificateModel->addCertificate(cert, true);
    }
    certificateView->resizeColumnsToContents();
    certificateView->setColumnWidth(0, 60);
}

void AdministratorWindow::addToCertificateTable(const QList<Certificate> &certs)
{
    foreach(const Certificate &cert, certs) {
        certificateModel->addCertificate(cert, false);
    }
}

void AdministratorWindow::showAbout()
{
    AboutDialog *dialog = new AboutDialog(this);
    dialog->show();
}

void AdministratorWindow::createInstaller()
{
    qDebug() << "create Installer";
    CreateInstallerDialog *dialog = new CreateInstallerDialog(this);
    dialog->show();
}

void AdministratorWindow::clickedCertificate(const QModelIndex &index)
{
    if (index.data(Qt::UserRole).toBool()) {
        removeButton->setEnabled(false);
    }
    else {
        removeButton->setEnabled(true);
    }
}

void AdministratorWindow::logChanges(const QString &currentCerts, const QString& keyFingerprint)
{
    QDir logDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
    QString logFilePath = logDir.filePath("log.txt");
    QFile logFile(logFilePath);

    if (!logFile.open(QIODevice::Append)) {
        QMessageBox::warning(this, tr("Error!"), tr("Failed to open log file: ") +
                logFilePath + tr(" Changes are not logged!"));
        qDebug() << "Failed to open log file: " << logFilePath;
        return;
    }

    CertificateList newCertList;
    newCertList.readList(currentCerts.toLocal8Bit());
    QByteArray entries = createLogEntries(newCertList, keyFingerprint);
    if(logFile.write(entries) != entries.size()) {
        QMessageBox::warning(this, tr("Error!"), tr("Failed to write log file: ") +
                logFilePath + tr(" Changes are not logged!"));
        return;
    }
    logFile.close();
}

QByteArray AdministratorWindow::createLogEntries(const CertificateList &list, const QString& keyFingerprint)
{
    QByteArray entries;
    QByteArray removeListEntries;

    QDateTime currentDate = QDateTime::currentDateTime();
    QDateTime newListDate = list.date();
    QDateTime listDate = mCertList.date();

    entries.append("##### " +
        currentDate.toString("yyyy-MM-dd hh:mm") +
        tr(" new certificatelist ") +
        newListDate.toString(Qt::ISODate) +
        tr(" based on list from ") +
        listDate.toString(Qt::ISODate) +
        "#####\r\n");
    entries.append(tr("signing certificate: \r\n"));
    entries.append(keyFingerprint);

    entries.append(tr("\r\nnew certificates:\r\n"));

    foreach (const Certificate& cert, list.getCertificates()) {
        if (!mCertList.getCertificates().contains(cert)) {
            QString certEntry(cert.subjectCN() + ": " + cert.base64Line() + "\r\n");
            if (cert.isInstallCert()) {
                entries.append(certEntry);
            }
            else {
                removeListEntries.append(certEntry);
            }
        }
    }

    entries.append(tr("certificates marked to remove:\r\n"));
    entries.append(removeListEntries);
    entries.append("\r\n");

    return entries;
}

QList<Certificate> AdministratorWindow::currentChanges()
{
    QList<Certificate> changed;
    foreach(const Certificate& cert, certificates()) {
        if (!mCertList.getCertificates().contains(cert)) {
            changed.append(cert);
        }
    }
    return changed;
}

void AdministratorWindow::showHelp()
{
    char *inst_dir = get_install_dir();
    if (!inst_dir) {
        qDebug() << "Failed to find install dir";
        return;
    }
    QString helpPath = QString::fromUtf8(inst_dir);
    helpPath += HELP_PATH;
    QFileInfo fiHelp(helpPath);
    qDebug() << "Opening help: " << fiHelp.absoluteFilePath();
    if (!fiHelp.exists()) {
        QMessageBox::warning(this, tr("Error!"), tr ("Failed to find the manual"));
        return;
    }
#ifdef Q_OS_WIN
    QDesktopServices::openUrl(QUrl("file:///" + fiHelp.absoluteFilePath()));
#else
    QDesktopServices::openUrl(QUrl(fiHelp.absoluteFilePath()));
#endif
    free (inst_dir);
    return;
}

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