# HG changeset patch # User Sascha Wilde # Date 1395833890 -3600 # Node ID 56ae02b4a0fc1dd7ba81d49cd0d59f5850ddbf92 # Parent 5d380b6621983eee7df436d72d8523dff161d9af# Parent 17eb8ad43984def9166784649013f5b818531bcf Merged diff -r 5d380b662198 -r 56ae02b4a0fc cinst/windowsstore.c --- a/cinst/windowsstore.c Wed Mar 26 12:37:19 2014 +0100 +++ b/cinst/windowsstore.c Wed Mar 26 12:38:10 2014 +0100 @@ -17,7 +17,7 @@ NULL, err, 0, (LPWSTR) &bufPtr, 0, NULL); if (!bufPtr) { - HMODULE hWinhttp = GetModuleHandleW (L"winhttp"); + HMODULE hWinhttp = GetModuleHandleW (L"crypt32"); if (hWinhttp) { FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | @@ -28,7 +28,7 @@ } } if (!bufPtr) - printf ("Error getting last error\n"); + printf ("Error getting last error for code: %lx \n", err); return bufPtr; } diff -r 5d380b662198 -r 56ae02b4a0fc common/strhelp.c --- a/common/strhelp.c Wed Mar 26 12:37:19 2014 +0100 +++ b/common/strhelp.c Wed Mar 26 12:38:10 2014 +0100 @@ -175,10 +175,10 @@ ret = base64_decode((unsigned char *)*dst, dst_size, (unsigned char *)src, src_size); - if (!ret) { + if (ret) { free (*dst); *dst = NULL; - dst_size = 0; + *dst_size = 0; } return ret; } diff -r 5d380b662198 -r 56ae02b4a0fc common/strhelp.h --- a/common/strhelp.h Wed Mar 26 12:37:19 2014 +0100 +++ b/common/strhelp.h Wed Mar 26 12:38:10 2014 +0100 @@ -1,6 +1,10 @@ #ifndef STRHELP_H #define STRHELP_H +#ifdef __cplusplus +extern "C" { +#endif + #include /** @@ -89,5 +93,8 @@ */ int str_base64_decode(char **dst, size_t *dst_size, char *src, size_t src_size); +#ifdef __cplusplus +} +#endif #endif diff -r 5d380b662198 -r 56ae02b4a0fc ui/CMakeLists.txt --- a/ui/CMakeLists.txt Wed Mar 26 12:37:19 2014 +0100 +++ b/ui/CMakeLists.txt Wed Mar 26 12:38:10 2014 +0100 @@ -16,6 +16,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.cpp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/listupdatedialog.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/helpdialog.cpp ${CERTIFICATELIST_SOURCES} ${DOWNLOADER_SOURCES} ) diff -r 5d380b662198 -r 56ae02b4a0fc ui/certificate.cpp --- a/ui/certificate.cpp Wed Mar 26 12:37:19 2014 +0100 +++ b/ui/certificate.cpp Wed Mar 26 12:38:10 2014 +0100 @@ -1,15 +1,18 @@ #include "certificate.h" #include +#include #include #include +#define POLARSSL_INFO_BUF_SIZE 2000 + Certificate::Certificate(const QString& b64Line) : - mValid(false), - mShortDescription(QObject::tr("Invalid Certificate")) + mValid(false) { int ret = -1; - char buf[2000]; + char buf[POLARSSL_INFO_BUF_SIZE]; + x509_crt x509cert; /* Cut of the first two chars (e.g. I: and decode) */ @@ -26,8 +29,8 @@ return; } - ret = x509_crt_info(buf, 2000, "", &x509cert); - x509_crt_free(&x509cert); + /* Get a full details string */ + ret = x509_crt_info(buf, POLARSSL_INFO_BUF_SIZE, "", &x509cert); if (ret <= 0) { qDebug() << "Getting certificate info failed with error: " << ret; @@ -35,14 +38,46 @@ } /* In case of success the return value is the size of the information - * written into buf - * */ - + * written into buf */ mDetails = QString::fromUtf8(buf, ret); - mShortDescription = mDetails; /* TODO */ + /* Get the subject */ + ret = x509_dn_gets(buf, POLARSSL_INFO_BUF_SIZE, &(x509cert.subject)); + + if (ret <= 0) { + qDebug() << "Getting certificate subject failed with error: " << ret; + return; + } + + /* TODO check that all asn encodings are handled */ + QString subject = QString::fromUtf8(buf, ret); + + /* TODO check that escaped , are not possible */ + QStringList attrs = subject.split(", "); + + foreach (const QString& attr, attrs) { + QStringList kv = attr.split("="); + if (kv.size() != 2) { + qDebug() << "Failed to parse subject element: " << attr; + continue; + } + mSubjectAttrs.insert(kv[0], kv[1]); + } + + /* For more information to get from a x509_crt see + * https://polarssl.org/api/x509_8h.html */ + + x509_crt_free(&x509cert); mValid = true; mBaseLine = b64Line; } + +QString Certificate::getSubjectAttr (const QString& attrName) const { + return mSubjectAttrs.value(attrName); +} + +QString Certificate::shortDescription() const { + return getSubjectAttr("CN"); +} diff -r 5d380b662198 -r 56ae02b4a0fc ui/certificate.h --- a/ui/certificate.h Wed Mar 26 12:37:19 2014 +0100 +++ b/ui/certificate.h Wed Mar 26 12:38:10 2014 +0100 @@ -7,6 +7,7 @@ */ #include +#include #include #ifdef Q_OS_WIN @@ -36,7 +37,7 @@ * for this certificate * **/ - const QString& shortDescription() const {return mShortDescription;} + QString shortDescription() const; /** @brief get details for the certificate * @@ -54,11 +55,22 @@ **/ const QString& base64Line() const {return mBaseLine;} + /** @brief get a single attribute of the subject + * + * Returns a single attribute of the subject such as the + * common name. + * + * @param[in] attr the Attribute name. to get e.g. "CN" + * + * @returns the value of the attribute or a null string + **/ + QString getSubjectAttr(const QString& attr) const; + private: bool mValid; QString mDetails; - QString mShortDescription; QString mBaseLine; + QMap mSubjectAttrs; }; #endif diff -r 5d380b662198 -r 56ae02b4a0fc ui/helpdialog.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/helpdialog.cpp Wed Mar 26 12:38:10 2014 +0100 @@ -0,0 +1,28 @@ +#include "helpdialog.h" +#include +#include +#include +#include + +HelpDialog::HelpDialog(QMainWindow *parent) : + QDialog(parent) +{ + setupGUI(); +} + +void HelpDialog::setupGUI() +{ + QVBoxLayout *mainLayout = new QVBoxLayout(this); + QTextEdit *helpText = new QTextEdit; + helpText->setReadOnly(true); + helpText->setPlainText(tr("This dialog contains some text to help the user.")); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + QPushButton *closeButton = new QPushButton(tr("Close")); + connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); + buttonLayout->insertStretch(0, 10); + buttonLayout->addWidget(closeButton); + + mainLayout->addWidget(helpText); + mainLayout->addLayout(buttonLayout); +} diff -r 5d380b662198 -r 56ae02b4a0fc ui/helpdialog.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/helpdialog.h Wed Mar 26 12:38:10 2014 +0100 @@ -0,0 +1,21 @@ +#ifndef HELPDIALOG_H +#define HELPDIALOG_H + +#include +#include +/** + * @file helpdialog.h + * @brief The dialog for help text. + */ + +class HelpDialog : public QDialog +{ +public: + /** @brief Create a help dialog */ + HelpDialog(QMainWindow *parent); + +private: + void setupGUI(); + +}; +#endif // HELPDIALOG_H diff -r 5d380b662198 -r 56ae02b4a0fc ui/mainwindow.cpp --- a/ui/mainwindow.cpp Wed Mar 26 12:37:19 2014 +0100 +++ b/ui/mainwindow.cpp Wed Mar 26 12:38:10 2014 +0100 @@ -9,6 +9,11 @@ #include #include #include +#include +#include +#include +#include +#include // The amount of time in minutes stay silent if we have // something to say @@ -21,11 +26,13 @@ #include "certificatelist.h" #include "downloader.h" #include "listupdatedialog.h" +#include "helpdialog.h" MainWindow::MainWindow() { createActions(); createTrayIcon(); createMenuBar(); + createContent(); qRegisterMetaType("SSLConnection::ErrorCode"); connect(mTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), @@ -118,6 +125,7 @@ mCurMessage = tr("An updated certificate list is available. Click here to install."); setState(NewListAvailable); showMessage(); + loadCertificateList(); } } @@ -213,16 +221,88 @@ setMenuBar(mMenuBar); } -void MainWindow::showSettings() { +void MainWindow::createContent() +{ + // Create a central widget containing the main layout. + QWidget *base = new QWidget; + + QVBoxLayout *mainLayout = new QVBoxLayout; + QHBoxLayout *certLayout = new QHBoxLayout; + QHBoxLayout *bottomLayout = new QHBoxLayout; + + QGroupBox *certBox = new QGroupBox(tr("Managed Certificates")); + certificateList = new QListWidget; + connect(certificateList, SIGNAL(itemClicked(QListWidgetItem*)), + this, SLOT(showDetails(QListWidgetItem*))); + certificateDetails = new QTextEdit; + certificateDetails->setReadOnly(true); + QSplitter *splitter = new QSplitter(certBox); + splitter->addWidget(certificateList); + splitter->addWidget(certificateDetails); + certLayout->addWidget(splitter); + certBox->setLayout(certLayout); + + QPushButton *update = new QPushButton("Search for Updates"); + connect(update, SIGNAL(clicked()), this, SLOT(checkUpdates())); + bottomLayout->insertStretch(0, 10); + bottomLayout->addWidget(update); + 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 MainWindow::loadCertificateList() +{ + qDebug() << "display certificates"; + certificateList->clear(); + foreach (const Certificate &cert, mListToInstall.getInstallCertificates()) { + if (!cert.isValid()) { + qWarning() << "Invalid certificate in list"; + continue; + } + QListWidgetItem* item = new QListWidgetItem(cert.shortDescription()); + item->setData(Qt::UserRole, cert.details()); + QIcon *certIcon = new QIcon(":/img/tray_22.png"); + item->setIcon(*certIcon); + certificateList->addItem(item); + } + foreach (const Certificate& cert, mListToInstall.getRemoveCertificates()) { + if (!cert.isValid()) { + qWarning() << "Invalid certificate in list"; + continue; + } + QListWidgetItem* item = new QListWidgetItem(cert.shortDescription()); + item->setData(Qt::UserRole, cert.details()); + QIcon *certIcon = new QIcon(":/img/tray_22.png"); + item->setIcon(*certIcon); + certificateList->addItem(item); + } +} + +void MainWindow::showSettings() +{ qDebug() << "show settingsdialog"; } void MainWindow::showHelp() { qDebug() << "show helpdialog"; + HelpDialog *help = new HelpDialog(this); + help->show(); } void MainWindow::showAbout() { qDebug() << "show aboutdialog"; } + +void MainWindow::showDetails(QListWidgetItem *item) +{ + qDebug() << "show details"; + QString details = item->data(Qt::UserRole).toString(); + certificateDetails->setPlainText(details); +} diff -r 5d380b662198 -r 56ae02b4a0fc ui/mainwindow.h --- a/ui/mainwindow.h Wed Mar 26 12:37:19 2014 +0100 +++ b/ui/mainwindow.h Wed Mar 26 12:38:10 2014 +0100 @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include "downloader.h" #include "certificatelist.h" @@ -49,6 +51,7 @@ void showSettings(); void showHelp(); void showAbout(); + void showDetails(QListWidgetItem*); private: /** @brief check the integrity of available files. @@ -63,6 +66,8 @@ void createTrayIcon(); void createActions(); void createMenuBar(); + void createContent(); + void loadCertificateList(); QString mCurMessage; QString mInstalledSWVersion; @@ -79,6 +84,9 @@ QMenuBar *mMenuBar; CertificateList mListToInstall; + + QListWidget *certificateList; + QTextEdit *certificateDetails; }; #endif // MAINWINDOW_H diff -r 5d380b662198 -r 56ae02b4a0fc ui/tests/CMakeLists.txt --- a/ui/tests/CMakeLists.txt Wed Mar 26 12:37:19 2014 +0100 +++ b/ui/tests/CMakeLists.txt Wed Mar 26 12:38:10 2014 +0100 @@ -37,6 +37,7 @@ # Cinstprocess add_m13_test(cinstprocesstest.cpp "${CERTIFICATELIST_SOURCES}") +add_m13_test(commontest.cpp "") #add_m13_test(${CMAKE_SOURCE_DIR}/ui/main.cpp "${M13UI_SOURCES}") diff -r 5d380b662198 -r 56ae02b4a0fc ui/tests/commontest.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/commontest.cpp Wed Mar 26 12:38:10 2014 +0100 @@ -0,0 +1,33 @@ +#include +#include +#include + +#include "commontest.h" +#include "strhelp.h" + +void CommonTest::testStrBase64Decode() { + char garbage[1000]; + char *data = NULL; + size_t data_size = 0; + int ret; + for (int i = 0; i < 1000; i++) { + garbage[i] = (char) qrand() % 255; + } + + QByteArray ba(garbage, 1000); + + QByteArray baB64 = ba.toBase64(); + + ret = str_base64_decode(&data, &data_size, (char *)baB64.constData(), baB64.size()); + + QVERIFY(ret == 0); + QVERIFY(data_size == 1000); + QVERIFY(data); + + for (size_t i = 0; i < data_size; i++) { + QVERIFY(garbage[i] == data[i]); + } + free (data); +} + +QTEST_GUILESS_MAIN (CommonTest); diff -r 5d380b662198 -r 56ae02b4a0fc ui/tests/commontest.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/commontest.h Wed Mar 26 12:38:10 2014 +0100 @@ -0,0 +1,13 @@ +#ifndef COMMONTEST_H +#define COMMONTEST_H + +#include + +class CommonTest: public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void testStrBase64Decode(); +}; +#endif