summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/QtUI')
-rw-r--r--Swift/QtUI/CocoaUIHelpers.h20
-rw-r--r--Swift/QtUI/CocoaUIHelpers.mm43
-rw-r--r--Swift/QtUI/QtMainWindow.cpp26
-rw-r--r--Swift/QtUI/QtMainWindow.h3
-rw-r--r--Swift/QtUI/QtRosterHeader.cpp19
-rw-r--r--Swift/QtUI/QtRosterHeader.h4
-rw-r--r--Swift/QtUI/SConscript2
-rw-r--r--Swift/QtUI/WinUIHelpers.cpp61
-rw-r--r--Swift/QtUI/WinUIHelpers.h20
9 files changed, 197 insertions, 1 deletions
diff --git a/Swift/QtUI/CocoaUIHelpers.h b/Swift/QtUI/CocoaUIHelpers.h
new file mode 100644
index 0000000..25da0e3
--- /dev/null
+++ b/Swift/QtUI/CocoaUIHelpers.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/TLS/Certificate.h>
+#include <QWidget>
+
+namespace Swift {
+
+class CocoaUIHelpers {
+public:
+ static void displayCertificateChainAsSheet(QWidget* parent, const std::vector<Certificate::ref>& chain);
+};
+
+}
+
diff --git a/Swift/QtUI/CocoaUIHelpers.mm b/Swift/QtUI/CocoaUIHelpers.mm
new file mode 100644
index 0000000..3cb62f3
--- /dev/null
+++ b/Swift/QtUI/CocoaUIHelpers.mm
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "CocoaUIHelpers.h"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/type_traits.hpp>
+
+#include <Cocoa/Cocoa.h>
+
+#include <Security/Security.h>
+#include <SecurityInterface/SFCertificatePanel.h>
+
+#include <Swiften/Base/foreach.h>
+
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+
+namespace Swift {
+
+void CocoaUIHelpers::displayCertificateChainAsSheet(QWidget* parent, const std::vector<Certificate::ref>& chain) {
+ NSWindow* parentWindow = [((NSView*)parent->winId()) window];
+ NSMutableArray* certificates = [[NSMutableArray alloc] init];
+ foreach(Certificate::ref cert, chain) {
+ // convert chain to SecCertificateRef
+ ByteArray certAsDER = cert->toDER();
+ boost::shared_ptr<boost::remove_pointer<CFDataRef>::type> certData(CFDataCreate(NULL, certAsDER.data(), certAsDER.size()), CFRelease);
+ boost::shared_ptr<OpaqueSecCertificateRef> macCert(SecCertificateCreateWithData(NULL, certData.get()), CFRelease);
+
+ // add to NSMutable array
+ [certificates addObject: (id)macCert.get()];
+ }
+
+
+ SFCertificatePanel* panel = [[SFCertificatePanel alloc] init];
+ //[panel setPolicies:(id)policies.get()];
+ [panel beginSheetForWindow:parentWindow modalDelegate:nil didEndSelector:NULL contextInfo:NULL certificates:certificates showGroup:YES];
+ [certificates release];
+}
+
+}
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 9a3ce6b..547f22b 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -28,32 +28,40 @@
#include <Roster/QtRosterWidget.h>
#include <Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestProfileEditorUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include <Swift/Controllers/UIEvents/RequestAdHocUIEvent.h>
#include <Swift/QtUI/QtUISettingConstants.h>
#include <Swift/Controllers/SettingConstants.h>
+#include <Swiften/Base/Platform.h>
+
+#if defined(SWIFTEN_PLATFORM_MACOSX)
+#include <Swift/QtUI/CocoaUIHelpers.h>
+#elif defined(SWIFTEN_PLATFORM_WINDOWS)
+#include <Swift/QtUI/WinUIHelpers.h>
+#endif
namespace Swift {
QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus) : QWidget(), MainWindow(false), loginMenus_(loginMenus) {
uiEventStream_ = uiEventStream;
settings_ = settings;
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this);
mainLayout->setContentsMargins(0,0,0,0);
mainLayout->setSpacing(0);
meView_ = new QtRosterHeader(settings, this);
mainLayout->addWidget(meView_);
connect(meView_, SIGNAL(onChangeStatusRequest(StatusShow::Type, const QString&)), this, SLOT(handleStatusChanged(StatusShow::Type, const QString&)));
connect(meView_, SIGNAL(onEditProfileRequest()), this, SLOT(handleEditProfileRequest()));
+ connect(meView_, SIGNAL(onShowCertificateInfo()), this, SLOT(handleShowCertificateInfo()));
tabs_ = new QtTabWidget(this);
#if QT_VERSION >= 0x040500
tabs_->setDocumentMode(true);
#endif
tabs_->setTabPosition(QTabWidget::South);
mainLayout->addWidget(tabs_);
contactsTabWidget_ = new QWidget(this);
contactsTabWidget_->setContentsMargins(0, 0, 0, 0);
@@ -147,18 +155,22 @@ QtMainWindow::~QtMainWindow() {
void QtMainWindow::handleTabChanged(int index) {
settings_->storeSetting(QtUISettingConstants::CURRENT_ROSTER_TAB, index);
}
void QtMainWindow::handleToggleRequestDeliveryReceipts(bool enabled) {
settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, enabled);
}
+void QtMainWindow::handleShowCertificateInfo() {
+ onShowCertificateRequest();
+}
+
QtEventWindow* QtMainWindow::getEventWindow() {
return eventWindow_;
}
QtChatListWindow* QtMainWindow::getChatListWindow() {
return chatListWindow_;
}
void QtMainWindow::setRosterModel(Roster* roster) {
@@ -250,18 +262,32 @@ void QtMainWindow::setMyStatusText(const std::string& status) {
void QtMainWindow::setMyStatusType(StatusShow::Type type) {
meView_->setStatusType(type);
}
void QtMainWindow::setConnecting() {
meView_->setConnecting();
}
+void QtMainWindow::setStreamEncryptionStatus(bool tlsInPlaceAndValid) {
+ meView_->setStreamEncryptionStatus(tlsInPlaceAndValid);
+}
+
+void QtMainWindow::openCertificateDialog(const std::vector<Certificate::ref>& chain) {
+#if defined(SWIFTEN_PLATFORM_MACOSX)
+ CocoaUIHelpers::displayCertificateChainAsSheet(this, chain);
+#elif defined(SWIFTEN_PLATFORM_WINDOWS)
+ WinUIHelpers::displayCertificateChainAsSheet(this,chain);
+#else
+#pragma message ("No certificate dialog available on this platform.")
+#endif
+}
+
void QtMainWindow::handleAdHocActionTriggered(bool /*checked*/) {
QAction* action = qobject_cast<QAction*>(sender());
assert(action);
DiscoItems::Item command = serverAdHocCommands_[serverAdHocCommandActions_.indexOf(action)];
uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestAdHocUIEvent(command)));
}
void QtMainWindow::setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands) {
serverAdHocCommands_ = commands;
diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h
index bef483d..c725d08 100644
--- a/Swift/QtUI/QtMainWindow.h
+++ b/Swift/QtUI/QtMainWindow.h
@@ -39,18 +39,20 @@ namespace Swift {
QtMainWindow(SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus);
virtual ~QtMainWindow();
std::vector<QMenu*> getMenus() {return menus_;}
void setMyNick(const std::string& name);
void setMyJID(const JID& jid);
void setMyAvatarPath(const std::string& path);
void setMyStatusText(const std::string& status);
void setMyStatusType(StatusShow::Type type);
void setConnecting();
+ void setStreamEncryptionStatus(bool tlsInPlaceAndValid);
+ void openCertificateDialog(const std::vector<Certificate::ref>& chain);
QtEventWindow* getEventWindow();
QtChatListWindow* getChatListWindow();
void setRosterModel(Roster* roster);
void setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands);
private slots:
void handleStatusChanged(StatusShow::Type showType, const QString &statusMessage);
void handleSettingChanged(const std::string& settingPath);
void handleShowOfflineToggled(bool);
void handleJoinMUCAction();
@@ -58,18 +60,19 @@ namespace Swift {
void handleEditProfileAction();
void handleAddUserActionTriggered(bool checked);
void handleChatUserActionTriggered(bool checked);
void handleAdHocActionTriggered(bool checked);
void handleEventCountUpdated(int count);
void handleChatCountUpdated(int count);
void handleEditProfileRequest();
void handleTabChanged(int index);
void handleToggleRequestDeliveryReceipts(bool enabled);
+ void handleShowCertificateInfo();
private:
SettingsProvider* settings_;
QtLoginWindow::QtMenus loginMenus_;
std::vector<QMenu*> menus_;
QtRosterWidget* treeWidget_;
QtRosterHeader* meView_;
QAction* addUserAction_;
QAction* editUserAction_;
diff --git a/Swift/QtUI/QtRosterHeader.cpp b/Swift/QtUI/QtRosterHeader.cpp
index 98e75c2..2bce222 100644
--- a/Swift/QtUI/QtRosterHeader.cpp
+++ b/Swift/QtUI/QtRosterHeader.cpp
@@ -39,26 +39,39 @@ QtRosterHeader::QtRosterHeader(SettingsProvider* settings, QWidget* parent) : QW
avatarLabel_->setScaledContents(false);
topLayout->addWidget(avatarLabel_);
connect(avatarLabel_, SIGNAL(clicked()), this, SIGNAL(onEditProfileRequest()));
QVBoxLayout* rightLayout = new QVBoxLayout();
rightLayout->setSpacing(4);
rightLayout->setContentsMargins(4,0,0,0);
topLayout->addLayout(rightLayout);
+ QHBoxLayout* nameAndSecurityLayout = new QHBoxLayout();
+ nameAndSecurityLayout->setContentsMargins(4,0,0,0);
+
nameWidget_ = new QtNameWidget(settings, this);
connect(nameWidget_, SIGNAL(onChangeNickRequest()), this, SIGNAL(onEditProfileRequest()));
- rightLayout->addWidget(nameWidget_);
+ nameAndSecurityLayout->addWidget(nameWidget_);
+
+ securityInfoButton_ = new QToolButton(this);
+
+ securityInfoButton_->setStyleSheet("border: none; hover: {border: 1px} pressed {border: 1px}");
+ // TODO: replace with a more appropriate icon
+ securityInfoButton_->setIcon(QIcon(":/icons/certificate.png"));
+ connect(securityInfoButton_, SIGNAL(clicked()), this, SIGNAL(onShowCertificateInfo()));
+ nameAndSecurityLayout->addWidget(securityInfoButton_);
+ rightLayout->addLayout(nameAndSecurityLayout);
statusWidget_ = new QtStatusWidget(this);
connect(statusWidget_, SIGNAL(onChangeStatusRequest(StatusShow::Type, const QString&)), this, SLOT(handleChangeStatusRequest(StatusShow::Type, const QString&)));
rightLayout->addWidget(statusWidget_);
+
show();
}
void QtRosterHeader::handleChangeStatusRequest(StatusShow::Type type, const QString& text) {
emit onChangeStatusRequest(type, text);
}
void QtRosterHeader::setStatusText(const QString& statusMessage) {
statusWidget_->setStatusText(statusMessage);
@@ -66,18 +79,22 @@ void QtRosterHeader::setStatusText(const QString& statusMessage) {
void QtRosterHeader::setStatusType(StatusShow::Type type) {
statusWidget_->setStatusType(type);
}
void QtRosterHeader::setConnecting() {
statusWidget_->setConnecting();
}
+void QtRosterHeader::setStreamEncryptionStatus(bool tlsInPlace) {
+ securityInfoButton_->setVisible(tlsInPlace);
+}
+
void QtRosterHeader::setAvatar(const QString& path) {
QString scaledAvatarPath = QtScaledAvatarCache(avatarSize_).getScaledAvatarPath(path);
QPixmap avatar;
if (QFileInfo(scaledAvatarPath).exists()) {
avatar.load(scaledAvatarPath);
}
else {
avatar = QPixmap(":/icons/avatar.png").scaled(avatarSize_, avatarSize_, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
diff --git a/Swift/QtUI/QtRosterHeader.h b/Swift/QtUI/QtRosterHeader.h
index 050460c..1132ee3 100644
--- a/Swift/QtUI/QtRosterHeader.h
+++ b/Swift/QtUI/QtRosterHeader.h
@@ -5,18 +5,19 @@
*/
#pragma once
#include <QWidget>
#include <QLabel>
#include <QPixmap>
#include <QSize>
#include <QToolBar>
+#include <QToolButton>
#include <string>
#include "Swiften/Elements/StatusShow.h"
#include "QtTextEdit.h"
class QHBoxLayout;
namespace Swift {
@@ -31,25 +32,28 @@ namespace Swift {
QtRosterHeader(SettingsProvider* settings, QWidget* parent = NULL);
void setAvatar(const QString& path);
void setJID(const QString& jid);
void setNick(const QString& nick);
void setStatusText(const QString& statusMessage);
void setStatusType(StatusShow::Type type);
void setConnecting();
+ void setStreamEncryptionStatus(bool tlsInPlace);
signals:
void onChangeStatusRequest(StatusShow::Type showType, const QString &statusMessage);
void onEditProfileRequest();
+ void onShowCertificateInfo();
private slots:
void handleChangeStatusRequest(StatusShow::Type type, const QString &statusMessage);
private:
QString name_;
QtClickableLabel* avatarLabel_;
QtNameWidget* nameWidget_;
QtTextEdit* statusEdit_;
QToolBar* toolBar_;
QtStatusWidget* statusWidget_;
+ QToolButton* securityInfoButton_;
static const int avatarSize_;
};
}
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index f944b43..4c53313 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -155,31 +155,33 @@ version_match = re.match("(\d+)\.(\d+).*", myenv["SWIFT_VERSION"])
myenv["SWIFT_VERSION_MAJOR"] = int(version_match.group(1)) if version_match else 0
myenv["SWIFT_VERSION_MINOR"] = int(version_match.group(2)) if version_match else 0
if env["PLATFORM"] == "win32" :
res = myenv.RES("#/Swift/resources/Windows/Swift.rc")
# For some reason, SCons isn't picking up the dependency correctly
# Adding it explicitly until i figure out why
myenv.Depends(res, "../Controllers/BuildVersion.h")
sources += [
+ "WinUIHelpers.cpp",
"CAPICertificateSelector.cpp",
"WindowsNotifier.cpp",
"#/Swift/resources/Windows/Swift.res"
]
if env["PLATFORM"] == "posix" :
sources += [
"FreeDesktopNotifier.cpp",
"QtDBUSURIHandler.cpp",
]
if env["PLATFORM"] == "darwin" :
sources += ["CocoaApplicationActivateHelper.mm"]
+ sources += ["CocoaUIHelpers.mm"]
if env["PLATFORM"] == "darwin" or env["PLATFORM"] == "win32" :
swiftProgram = myenv.Program("Swift", sources)
else :
swiftProgram = myenv.Program("swift", sources)
if env["PLATFORM"] != "darwin" and env["PLATFORM"] != "win32" :
openURIProgram = myenv.Program("swift-open-uri", "swift-open-uri.cpp")
else :
diff --git a/Swift/QtUI/WinUIHelpers.cpp b/Swift/QtUI/WinUIHelpers.cpp
new file mode 100644
index 0000000..edd1120
--- /dev/null
+++ b/Swift/QtUI/WinUIHelpers.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "WinUIHelpers.h"
+
+#include <windows.h>
+#include <Wincrypt.h>
+#include <cryptuiapi.h>
+#pragma comment(lib, "cryptui.lib")
+
+#include <boost/shared_ptr.hpp>
+
+#include <Swiften/Base/foreach.h>
+
+namespace Swift {
+
+void WinUIHelpers::displayCertificateChainAsSheet(QWidget* parent, const std::vector<Certificate::ref>& chain) {
+ if (chain.empty()) {
+ return;
+ }
+
+ // create certificate store to store the certificate chain in
+ HCERTSTORE chainStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL);
+ if (!chainStore) {
+ return;
+ }
+
+ ByteArray certAsDER = chain[0]->toDER();
+ boost::shared_ptr<const CERT_CONTEXT> certificate_chain;
+ {
+ PCCERT_CONTEXT certChain;
+ BOOL ok = CertAddCertificateContextToStore(chainStore, CertCreateCertificateContext(X509_ASN_ENCODING, certAsDER.data(), certAsDER.size()), CERT_STORE_ADD_ALWAYS, &certChain);
+ // maybe free the cert contex we created
+ if (!ok || !certChain) {
+ return;
+ }
+ certificate_chain.reset(certChain, CertFreeCertificateContext);
+ }
+
+ for (size_t i = 1; i < chain.size(); ++i) {
+ ByteArray certAsDER = chain[i]->toDER();
+ CertAddCertificateContextToStore(chainStore, CertCreateCertificateContext(X509_ASN_ENCODING, certAsDER.data(), certAsDER.size()), CERT_STORE_ADD_ALWAYS, NULL);
+ }
+
+ CRYPTUI_VIEWCERTIFICATE_STRUCT viewDialogProperties = { 0 };
+ viewDialogProperties.dwSize = sizeof(viewDialogProperties);
+ viewDialogProperties.hwndParent = parent->winId();
+ viewDialogProperties.dwFlags = CRYPTUI_DISABLE_EDITPROPERTIES | CRYPTUI_DISABLE_ADDTOSTORE | CRYPTUI_ENABLE_REVOCATION_CHECKING;
+ viewDialogProperties.pCertContext = certificate_chain.get();
+ viewDialogProperties.cStores = 1;
+ viewDialogProperties.rghStores = &chainStore;
+ BOOL properties_changed;
+
+ // blocking call that shows modal certificate dialog
+ BOOL rv = ::CryptUIDlgViewCertificate(&viewDialogProperties, &properties_changed);
+}
+
+}
diff --git a/Swift/QtUI/WinUIHelpers.h b/Swift/QtUI/WinUIHelpers.h
new file mode 100644
index 0000000..d34d236
--- /dev/null
+++ b/Swift/QtUI/WinUIHelpers.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 Tobias Markmann
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/TLS/Certificate.h>
+#include <QWidget>
+
+namespace Swift {
+
+class WinUIHelpers {
+public:
+ static void displayCertificateChainAsSheet(QWidget* parent, const std::vector<Certificate::ref>& chain);
+};
+
+}
+