diff options
| -rw-r--r-- | Swift/QtUI/QtCertificateViewerDialog.cpp | 133 | ||||
| -rw-r--r-- | Swift/QtUI/QtCertificateViewerDialog.h | 44 | ||||
| -rw-r--r-- | Swift/QtUI/QtCertificateViewerDialog.ui | 131 | ||||
| -rw-r--r-- | Swift/QtUI/QtMainWindow.cpp | 4 | ||||
| -rw-r--r-- | Swift/QtUI/SConscript | 5 | 
5 files changed, 316 insertions, 1 deletions
| diff --git a/Swift/QtUI/QtCertificateViewerDialog.cpp b/Swift/QtUI/QtCertificateViewerDialog.cpp new file mode 100644 index 0000000..2a1e32a --- /dev/null +++ b/Swift/QtUI/QtCertificateViewerDialog.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "QtCertificateViewerDialog.h" +#include "ui_QtCertificateViewerDialog.h" + +#include <Swiften/Base/foreach.h> + +#include <QTreeWidgetItem> +#include <QLabel> +#include <QDateTime> + +namespace Swift { + +QtCertificateViewerDialog::QtCertificateViewerDialog(QWidget *parent) : QDialog(parent), ui(new Ui::QtCertificateViewerDialog) { +	ui->setupUi(this); +	connect(ui->certChainTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); + +	setAttribute(Qt::WA_DeleteOnClose); +} + +QtCertificateViewerDialog::~QtCertificateViewerDialog() { +	delete ui; +} + +void QtCertificateViewerDialog::setCertificateChain(const std::vector<Certificate::ref> &chain) { +	// clean widgets +	ui->certChainTreeWidget->clear(); + +	if (chain.empty()) return; + +	// convert Swift certificate chain to qt certificate chain (root goes first) +	currentChain.clear(); +	foreach(Certificate::ref cert, chain) { +		ByteArray certAsDer = cert->toDER(); +		QByteArray dataArray(reinterpret_cast<const char*>(certAsDer.data()), certAsDer.size()); +		currentChain.push_front(QSslCertificate(dataArray, QSsl::Der)); +	} + +	// fill treeWidget +	QTreeWidgetItem* root = new QTreeWidgetItem(ui->certChainTreeWidget, QStringList(currentChain.at(0).subjectInfo(QSslCertificate::CommonName))); +	root->setData(0, Qt::UserRole, QVariant(0)); +	root->setExpanded(true); +	ui->certChainTreeWidget->addTopLevelItem(root); +	if (currentChain.size() > 1) { +		QTreeWidgetItem* parent = root; +		for (int n = 1; n < currentChain.size(); n++) { +			QTreeWidgetItem* link = new QTreeWidgetItem(parent, QStringList(QString("↳ ") + currentChain.at(n).subjectInfo(QSslCertificate::CommonName))); +			link->setExpanded(true); +			link->setData(0, Qt::UserRole, QVariant(n)); +			parent = link; +		} +		ui->certChainTreeWidget->setCurrentItem(parent); +	} else { +		ui->certChainTreeWidget->setCurrentItem(root); +	} +} + +void QtCertificateViewerDialog::displayCertificateChainAsSheet(QWidget *parent, const std::vector<Certificate::ref> &chain) { +	QtCertificateViewerDialog* dialog = new QtCertificateViewerDialog(parent); +	dialog->setCertificateChain(chain); +	dialog->show(); +} + +void QtCertificateViewerDialog::currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem*) { +	setCertificateDetails(currentChain.at(current->data(0, Qt::UserRole).toInt())); +} + +#define ADD_SECTION( TITLE ) \ +	ui->certGridLayout->addWidget(new QLabel("<strong>" + TITLE + "</strong>"), rowCount++, 0, 1, 2); + +#define ADD_FIELD( TITLE, VALUE) \ +	ui->certGridLayout->addWidget(new QLabel(TITLE), rowCount, 0, 1, 1, Qt::AlignRight); \ +	valueLabel = new QLabel(VALUE); \ +	valueLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); \ +	ui->certGridLayout->addWidget(valueLabel, rowCount++, 1, 1, 1, Qt::AlignLeft); + +void QtCertificateViewerDialog::setCertificateDetails(const QSslCertificate &cert) { +	QLayoutItem* item; +	while ((item = ui->certGridLayout->takeAt(0)) != NULL ) { +		delete item->widget(); +		delete item; +	} + +	int rowCount = 0; + +	ui->certGridLayout->setColumnStretch(2, 1); + +	QLabel* valueLabel = 0; + +	ADD_SECTION(tr("General")); +	ADD_FIELD(tr("Valid From"), cert.effectiveDate().toString(Qt::TextDate)); +	ADD_FIELD(tr("Valid To"), cert.expiryDate().toString(Qt::TextDate)); +	ADD_FIELD(tr("Serial Number"), QString(cert.serialNumber().toHex())); +	ADD_FIELD(tr("Version"), QString(cert.version())); + +	ADD_SECTION(tr("Subject")); +	ADD_FIELD(tr("Organization"), cert.subjectInfo(QSslCertificate::Organization)); +	ADD_FIELD(tr("Common Name"), cert.subjectInfo(QSslCertificate::CommonName)); +	ADD_FIELD(tr("Locality"), cert.subjectInfo(QSslCertificate::LocalityName)); +	ADD_FIELD(tr("Organizational Unit"), cert.subjectInfo(QSslCertificate::OrganizationalUnitName)); +	ADD_FIELD(tr("Country"), cert.subjectInfo(QSslCertificate::CountryName)); +	ADD_FIELD(tr("State"), cert.subjectInfo(QSslCertificate::StateOrProvinceName)); + +	if (!cert.alternateSubjectNames().empty()) { +		ADD_SECTION(tr("Alternate Subject Names")); +		QMultiMap<QSsl::AlternateNameEntryType, QString> altNames = cert.alternateSubjectNames(); +		foreach (const QSsl::AlternateNameEntryType &type, altNames.uniqueKeys()) { +			foreach (QString name, altNames.values(type)) { +				if (type == QSsl::EmailEntry) { +					ADD_FIELD(tr("E-mail Address"), name); +				} else { +					ADD_FIELD(tr("DNS Name"), name); +				} +			} +		} +	} + +	ADD_SECTION(tr("Issuer")); +	ADD_FIELD(tr("Organization"), cert.issuerInfo(QSslCertificate::Organization)); +	ADD_FIELD(tr("Common Name"), cert.issuerInfo(QSslCertificate::CommonName)); +	ADD_FIELD(tr("Locality"), cert.issuerInfo(QSslCertificate::LocalityName)); +	ADD_FIELD(tr("Organizational Unit"), cert.issuerInfo(QSslCertificate::OrganizationalUnitName)); +	ADD_FIELD(tr("Country"), cert.issuerInfo(QSslCertificate::CountryName)); +	ADD_FIELD(tr("State"), cert.issuerInfo(QSslCertificate::StateOrProvinceName)); + +	ui->certGridLayout->setRowStretch(rowCount + 1, 1); +} + +} diff --git a/Swift/QtUI/QtCertificateViewerDialog.h b/Swift/QtUI/QtCertificateViewerDialog.h new file mode 100644 index 0000000..9475a83 --- /dev/null +++ b/Swift/QtUI/QtCertificateViewerDialog.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QDialog> +#include <QList> +#include <QSslCertificate> +#include <QTreeWidgetItem> + +#include <Swiften/TLS/Certificate.h> + +namespace Ui { +class QtCertificateViewerDialog; +} + +namespace Swift { + +class QtCertificateViewerDialog : public QDialog { +	Q_OBJECT +		 +	public: +		explicit QtCertificateViewerDialog(QWidget* parent = 0); +		~QtCertificateViewerDialog(); + +		void setCertificateChain(const std::vector<Certificate::ref>& chain); + +		static void displayCertificateChainAsSheet(QWidget* parent, const std::vector<Certificate::ref>& chain); + +	private slots: +		void currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*); + +	private: +		void setCertificateDetails(const QSslCertificate& cert); + +	private: +		Ui::QtCertificateViewerDialog *ui; +		QList<QSslCertificate> currentChain; +}; + +} diff --git a/Swift/QtUI/QtCertificateViewerDialog.ui b/Swift/QtUI/QtCertificateViewerDialog.ui new file mode 100644 index 0000000..63a96bf --- /dev/null +++ b/Swift/QtUI/QtCertificateViewerDialog.ui @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtCertificateViewerDialog</class> + <widget class="QDialog" name="QtCertificateViewerDialog"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>655</width> +    <height>514</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>Certificate Viewer</string> +  </property> +  <property name="sizeGripEnabled"> +   <bool>true</bool> +  </property> +  <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0"> +   <item row="3" column="0"> +    <widget class="QDialogButtonBox" name="buttonBox"> +     <property name="orientation"> +      <enum>Qt::Horizontal</enum> +     </property> +     <property name="standardButtons"> +      <set>QDialogButtonBox::Ok</set> +     </property> +    </widget> +   </item> +   <item row="1" column="0"> +    <widget class="QScrollArea" name="scrollArea"> +     <property name="autoFillBackground"> +      <bool>false</bool> +     </property> +     <property name="horizontalScrollBarPolicy"> +      <enum>Qt::ScrollBarAlwaysOff</enum> +     </property> +     <property name="widgetResizable"> +      <bool>true</bool> +     </property> +     <widget class="QWidget" name="scrollAreaWidgetContents"> +      <property name="geometry"> +       <rect> +        <x>0</x> +        <y>0</y> +        <width>629</width> +        <height>368</height> +       </rect> +      </property> +      <layout class="QVBoxLayout" name="verticalLayout"> +       <item> +        <layout class="QGridLayout" name="certGridLayout"/> +       </item> +      </layout> +     </widget> +    </widget> +   </item> +   <item row="0" column="0"> +    <widget class="QTreeWidget" name="certChainTreeWidget"> +     <property name="maximumSize"> +      <size> +       <width>16777215</width> +       <height>70</height> +      </size> +     </property> +     <property name="editTriggers"> +      <set>QAbstractItemView::NoEditTriggers</set> +     </property> +     <property name="showDropIndicator" stdset="0"> +      <bool>false</bool> +     </property> +     <property name="dragEnabled"> +      <bool>false</bool> +     </property> +     <property name="rootIsDecorated"> +      <bool>false</bool> +     </property> +     <property name="itemsExpandable"> +      <bool>false</bool> +     </property> +     <property name="expandsOnDoubleClick"> +      <bool>false</bool> +     </property> +     <attribute name="headerVisible"> +      <bool>false</bool> +     </attribute> +     <column> +      <property name="text"> +       <string notr="true">1</string> +      </property> +     </column> +    </widget> +   </item> +  </layout> + </widget> + <resources/> + <connections> +  <connection> +   <sender>buttonBox</sender> +   <signal>accepted()</signal> +   <receiver>QtCertificateViewerDialog</receiver> +   <slot>accept()</slot> +   <hints> +    <hint type="sourcelabel"> +     <x>248</x> +     <y>254</y> +    </hint> +    <hint type="destinationlabel"> +     <x>157</x> +     <y>274</y> +    </hint> +   </hints> +  </connection> +  <connection> +   <sender>buttonBox</sender> +   <signal>rejected()</signal> +   <receiver>QtCertificateViewerDialog</receiver> +   <slot>reject()</slot> +   <hints> +    <hint type="sourcelabel"> +     <x>316</x> +     <y>260</y> +    </hint> +    <hint type="destinationlabel"> +     <x>286</x> +     <y>274</y> +    </hint> +   </hints> +  </connection> + </connections> +</ui> diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index ced375f..5d50c1e 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -41,6 +41,8 @@  #include <Swift/QtUI/CocoaUIHelpers.h>  #elif defined(SWIFTEN_PLATFORM_WINDOWS)  #include <Swift/QtUI/WinUIHelpers.h> +#else +#include <Swift/QtUI/QtCertificateViewerDialog.h>  #endif  namespace Swift { @@ -309,7 +311,7 @@ void QtMainWindow::openCertificateDialog(const std::vector<Certificate::ref>& ch  #elif defined(SWIFTEN_PLATFORM_WINDOWS)  	WinUIHelpers::displayCertificateChainAsSheet(parent, chain);  #else -#pragma message ("No certificate dialog available on this platform.") +	QtCertificateViewerDialog::displayCertificateChainAsSheet(parent, chain);  #endif  } diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 27ff237..a8a87de 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -51,6 +51,9 @@ myenv.Tool("textfile", toolpath = ["#/BuildTools/SCons/Tools"])  qt4modules = ['QtCore', 'QtGui', 'QtWebKit']  if env["PLATFORM"] == "posix" :  	qt4modules += ["QtDBus"] +if env["PLATFORM"] != "win32" and env["PLATFORM"] != "darwin" : +	qt4modules += ["QtNetwork"] +  myenv.EnableQt4Modules(qt4modules, debug = False)  myenv.Append(CPPPATH = ["."]) @@ -185,6 +188,8 @@ if env["PLATFORM"] == "darwin" or env["PLATFORM"] == "win32" :    swiftProgram = myenv.Program("Swift", sources)  else :    swiftProgram = myenv.Program("swift-im", sources) +  sources += ["QtCertificateViewerDialog.cpp"]; +  myenv.Uic4("QtCertificateViewerDialog.ui");  if env["PLATFORM"] != "darwin" and env["PLATFORM"] != "win32" :  	openURIProgram = myenv.Program("swift-open-uri", "swift-open-uri.cpp") | 
 Swift
 Swift