}
emit connectionMsg(msg["CoreInfo"].toString());
+#ifndef QT_NO_COMPRESS
+ if(msg["SupportsCompression"].toBool()) {
+ socket->setProperty("UseCompression", true);
+ }
+#endif
+
+ _coreMsgBuffer = msg;
#ifdef HAVE_SSL
if(coreConnectionInfo["useSsl"].toBool()) {
if(msg["SupportSsl"].toBool()) {
QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
Q_ASSERT(sslSocket);
+ connect(sslSocket, SIGNAL(encrypted()), this, SLOT(sslSocketEncrypted()));
connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrors(const QList<QSslError> &)));
+
sslSocket->startClientEncryption();
} else {
emit connectionError(tr("<b>The Quassel Core you are trying to connect to does not support SSL!</b><br />If you want to connect anyways, disable the usage of SSL in the account settings."));
disconnectFromCore();
- return;
}
+ return;
}
#endif
+ // if we use SSL we wait for the next step until every SSL warning has been cleared
+ connectionReady();
+}
-#ifndef QT_NO_COMPRESS
- if(msg["SupportsCompression"].toBool()) {
- socket->setProperty("UseCompression", true);
- }
-#endif
-
- if(!msg["Configured"].toBool()) {
+void ClientSyncer::connectionReady() {
+ if(!_coreMsgBuffer["Configured"].toBool()) {
// start wizard
- emit startCoreSetup(msg["StorageBackends"].toList());
- } else if(msg["LoginEnabled"].toBool()) {
+ emit startCoreSetup(_coreMsgBuffer["StorageBackends"].toList());
+ } else if(_coreMsgBuffer["LoginEnabled"].toBool()) {
emit startLogin();
}
+ _coreMsgBuffer.clear();
+ resetWarningsHandler();
}
void ClientSyncer::doCoreSetup(const QVariant &setupData) {
}
}
+void ClientSyncer::setWarningsHandler(const char *slot) {
+ resetWarningsHandler();
+ connect(this, SIGNAL(handleIgnoreWarnings(bool)), this, slot);
+}
+
+void ClientSyncer::resetWarningsHandler() {
+ disconnect(this, SIGNAL(handleIgnoreWarnings(bool)), this, 0);
+}
+
#ifdef HAVE_SSL
-void ClientSyncer::sslErrors(const QList<QSslError> &errors) {
- qDebug() << "SSL Errors:";
- foreach(QSslError err, errors)
- qDebug() << " " << err;
+void ClientSyncer::ignoreSslWarnings(bool permanently) {
+ QAbstractSocket *sock = qobject_cast<QAbstractSocket *>(socket);
+ if(sock) {
+ // ensure that a proper state is displayed and no longer a warning
+ emit socketStateChanged(sock->state());
+ }
+ emit connectionMsg(_coreMsgBuffer["CoreInfo"].toString());
+ connectionReady();
+}
+
+void ClientSyncer::sslSocketEncrypted() {
+ QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
+ if(socket) {
+ QByteArray digest = socket->peerCertificate().digest();
+ }
+}
+void ClientSyncer::sslErrors(const QList<QSslError> &errors) {
QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
- if(socket)
+ if(socket) {
socket->ignoreSslErrors();
+ }
+
+ QStringList warnings;
+ foreach(QSslError err, errors)
+ warnings << err.errorString();
+
+ setWarningsHandler(SLOT(ignoreSslWarnings(bool)));
+ emit connectionWarnings(warnings);
}
#endif
ClientSyncer(QObject *parent = 0);
~ClientSyncer();
+ inline const QIODevice *currentDevice() { return socket; }
+
signals:
void recvPartialItem(quint32 avail, quint32 size);
void connectionError(const QString &errorMsg);
+ void connectionWarnings(const QStringList &warnings);
void connectionMsg(const QString &msg);
void sessionProgress(quint32 part, quint32 total);
void networksProgress(quint32 part, quint32 total);
void startInternalCore(ClientSyncer *syncer);
void connectToInternalCore(SignalProxy *proxy);
+ void handleIgnoreWarnings(bool permanently);
+
public slots:
void connectToCore(const QVariantMap &);
void loginToCore(const QString &user, const QString &passwd);
void disconnectFromCore();
void useInternalCore();
+ inline void ignoreWarnings(bool permanently) { emit handleIgnoreWarnings(permanently); }
+
private slots:
void coreSocketError(QAbstractSocket::SocketError);
void coreHasData();
void internalSessionStateReceived(const QVariant &packedState);
void sessionStateReceived(const QVariantMap &state);
+ void connectionReady();
void doCoreSetup(const QVariant &setupData);
+
+ void setWarningsHandler(const char *slot);
+ void resetWarningsHandler();
+
#ifdef HAVE_SSL
- void sslErrors(const QList<QSslError> &errors);
+ void ignoreSslWarnings(bool permanently);
+ void sslSocketEncrypted();
+ void sslErrors(const QList<QSslError> &errors);
#endif
private:
QPointer<QIODevice> socket;
quint32 blockSize;
QVariantMap coreConnectionInfo;
+ QVariantMap _coreMsgBuffer;
QSet<QObject *> netsToSync;
int numNetsToSync;
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include "coreconnectdlg.h"
+
#include <QDebug>
+#include <QFormLayout>
#include <QMessageBox>
#include <QNetworkProxy>
-#include "coreconnectdlg.h"
+#ifdef HAVE_SSL
+#include <QSslSocket>
+#include <QSslCertificate>
+#endif
#include "client.h"
#include "clientsettings.h"
clientSyncer = new ClientSyncer(this);
Client::registerClientSyncer(clientSyncer);
-// connect(this, SIGNAL(newClientSyncer(ClientSyncer *)), Client::instance(), SIGNAL(newClientSyncer(ClientSyncer *)));
-// emit newClientSyncer(clientSyncer); // announce the new client syncer via the client.
wizard = 0;
connect(clientSyncer, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)),this, SLOT(initPhaseSocketState(QAbstractSocket::SocketState)));
connect(clientSyncer, SIGNAL(connectionError(const QString &)), this, SLOT(initPhaseError(const QString &)));
+ connect(clientSyncer, SIGNAL(connectionWarnings(const QStringList &)), this, SLOT(initPhaseWarnings(const QStringList &)));
connect(clientSyncer, SIGNAL(connectionMsg(const QString &)), this, SLOT(initPhaseMsg(const QString &)));
connect(clientSyncer, SIGNAL(startLogin()), this, SLOT(startLogin()));
connect(clientSyncer, SIGNAL(loginFailed(const QString &)), this, SLOT(loginFailed(const QString &)));
connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
}
+void CoreConnectDlg::initPhaseWarnings(const QStringList &warnings) {
+ doingAutoConnect = false;
+ ui.secureConnection->hide();
+ ui.connectIcon->setPixmap(BarIcon("dialog-warning"));
+ ui.connectLabel->setText(tr("<div>Errors occurred while connecting to \"%1\":</div>").arg(accountData["Host"].toString()));
+ QStringList warningItems;
+ foreach(QString warning, warnings) {
+ warningItems << QString("<li>%1</li>").arg(warning);
+ }
+ ui.coreInfoLabel->setText(QString("<ul>%1</ul>").arg(warningItems.join("")));
+ ui.loginStack->setCurrentWidget(ui.connectionWarningsPage);
+ ui.loginButtonBox->setStandardButtons(QDialogButtonBox::Cancel);
+ ui.loginButtonBox->button(QDialogButtonBox::Cancel)->setFocus();
+ disconnect(ui.loginButtonBox, 0, this, 0);
+ connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(restartPhaseNull()));
+}
+
+void CoreConnectDlg::on_viewSslCertButton_clicked() {
+#ifdef HAVE_SSL
+ const QSslSocket *socket = qobject_cast<const QSslSocket *>(clientSyncer->currentDevice());
+ if(!socket)
+ return;
+
+ SslCertDisplayDialog dialog(socket->peerName(), socket->peerCertificate());
+ dialog.exec();
+#endif
+}
+
+void CoreConnectDlg::on_ignoreWarningsButton_clicked() {
+ clientSyncer->ignoreWarnings(ui.ignoreWarningsPermanently->isChecked());
+}
+
+
void CoreConnectDlg::initPhaseMsg(const QString &msg) {
ui.coreInfoLabel->setText(msg);
}
Q_UNUSED(text);
setWidgetStates();
}
+
+
+// ========================================
+// SslCertDisplayDialog
+// ========================================
+SslCertDisplayDialog::SslCertDisplayDialog(const QString &host, const QSslCertificate &cert, QWidget *parent)
+ : QDialog(parent)
+{
+#ifndef HAVE_SSL
+ Q_UNUSED(cert)
+#else
+
+ setWindowTitle(tr("SSL Certificate used by %1").arg(host));
+
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
+
+ QGroupBox *issuerBox = new QGroupBox(tr("Issuer Info"), this);
+ QFormLayout *issuerLayout = new QFormLayout(issuerBox);
+ issuerLayout->addRow(tr("Organization:"), new QLabel(cert.issuerInfo(QSslCertificate::Organization), this));
+ issuerLayout->addRow(tr("Locality Name:"), new QLabel(cert.issuerInfo(QSslCertificate::LocalityName), this));
+ issuerLayout->addRow(tr("Organizational Unit Name:"), new QLabel(cert.issuerInfo(QSslCertificate::OrganizationalUnitName), this));
+ issuerLayout->addRow(tr("Country Name:"), new QLabel(cert.issuerInfo(QSslCertificate::CountryName), this));
+ issuerLayout->addRow(tr("State or Province Name:"), new QLabel(cert.issuerInfo(QSslCertificate::StateOrProvinceName), this));
+ mainLayout->addWidget(issuerBox);
+
+ QGroupBox *subjectBox = new QGroupBox(tr("Subject Info"), this);
+ QFormLayout *subjectLayout = new QFormLayout(subjectBox);
+ subjectLayout->addRow(tr("Organization:"), new QLabel(cert.subjectInfo(QSslCertificate::Organization), this));
+ subjectLayout->addRow(tr("Locality Name:"), new QLabel(cert.subjectInfo(QSslCertificate::LocalityName), this));
+ subjectLayout->addRow(tr("Organizational Unit Name:"), new QLabel(cert.subjectInfo(QSslCertificate::OrganizationalUnitName), this));
+ subjectLayout->addRow(tr("Country Name:"), new QLabel(cert.subjectInfo(QSslCertificate::CountryName), this));
+ subjectLayout->addRow(tr("State or Province Name:"), new QLabel(cert.subjectInfo(QSslCertificate::StateOrProvinceName), this));
+ mainLayout->addWidget(subjectBox);
+
+ QGroupBox *additionalBox = new QGroupBox(tr("Additional Info"), this);
+ QFormLayout *additionalLayout = new QFormLayout(additionalBox);
+ additionalLayout->addRow(tr("Valid From:"), new QLabel(cert.effectiveDate().toString(), this));
+ additionalLayout->addRow(tr("Valid To:"), new QLabel(cert.expiryDate().toString(), this));
+ QStringList hostnames = cert.alternateSubjectNames().values(QSsl::DnsEntry);
+ for(int i = 0; i < hostnames.count(); i++) {
+ additionalLayout->addRow(tr("Hostname %1:").arg(i + 1), new QLabel(hostnames[i], this));
+ }
+ QStringList mailaddresses = cert.alternateSubjectNames().values(QSsl::EmailEntry);
+ for(int i = 0; i < mailaddresses.count(); i++) {
+ additionalLayout->addRow(tr("E-Mail Address %1:").arg(i + 1), new QLabel(mailaddresses[i], this));
+ }
+ mainLayout->addWidget(additionalBox);
+
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, this);
+ mainLayout->addWidget(buttonBox);
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+#endif
+};
void on_editAccount_clicked();
void on_deleteAccount_clicked();
void on_useInternalCore_clicked();
+ void on_viewSslCertButton_clicked();
+ void on_ignoreWarningsButton_clicked();
void on_accountList_itemDoubleClicked(QListWidgetItem *item);
void on_accountButtonBox_accepted();
void connectToCore();
void initPhaseError(const QString &error);
+ void initPhaseWarnings(const QStringList &warnings);
void initPhaseMsg(const QString &msg);
void initPhaseSocketState(QAbstractSocket::SocketState);
CoreConfigWizard *wizard;
};
+
+// ========================================
+// CoreAccountEditDlg
+// ========================================
class CoreAccountEditDlg : public QDialog {
Q_OBJECT
QVariantMap account;
};
+// ========================================
+// SslCertDisplayDialog
+// ========================================
+class QSslCertificate;
+
+class SslCertDisplayDialog : public QDialog {
+ Q_OBJECT
+
+public:
+ SslCertDisplayDialog(const QString &host, const QSslCertificate &cert, QWidget *parent = 0);
+};
#endif
<rect>
<x>0</x>
<y>0</y>
- <width>563</width>
- <height>356</height>
+ <width>539</width>
+ <height>347</height>
</rect>
</property>
<property name="sizePolicy" >
<normaloff>:/16x16/actions/network-disconnect</normaloff>:/16x16/actions/network-disconnect</iconset>
</property>
<layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
<item>
<widget class="QStackedWidget" name="stackedWidget" >
<property name="sizePolicy" >
</sizepolicy>
</property>
<property name="currentIndex" >
- <number>0</number>
+ <number>1</number>
</property>
<widget class="QWidget" name="accountPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>539</width>
+ <height>340</height>
+ </rect>
+ </property>
<layout class="QVBoxLayout" >
<item>
<widget class="QGroupBox" name="groupBox" >
</layout>
</widget>
<widget class="QWidget" name="loginPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>539</width>
+ <height>347</height>
+ </rect>
+ </property>
<layout class="QVBoxLayout" >
<item>
<widget class="QGroupBox" name="groupBox_2" >
<string>Initializing your connection</string>
</property>
<layout class="QVBoxLayout" >
- <property name="spacing" >
- <number>0</number>
- </property>
- <property name="margin" >
- <number>4</number>
- </property>
<item>
<layout class="QGridLayout" >
<item row="0" column="0" >
</sizepolicy>
</property>
<property name="currentIndex" >
- <number>0</number>
+ <number>1</number>
</property>
<widget class="QWidget" name="loginCredentialsPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>485</width>
+ <height>135</height>
+ </rect>
+ </property>
<layout class="QVBoxLayout" >
- <item>
- <spacer>
- <property name="orientation" >
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0" >
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
+ <property name="margin" >
+ <number>0</number>
+ </property>
<item>
<spacer>
<property name="orientation" >
<string>Login</string>
</property>
<layout class="QVBoxLayout" >
- <property name="margin" >
- <number>4</number>
- </property>
<item>
<layout class="QGridLayout" >
<item row="0" column="0" >
</item>
</layout>
</widget>
+ <widget class="QWidget" name="connectionWarningsPage" >
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" >
+ <item>
+ <spacer name="horizontalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="viewSslCertButton" >
+ <property name="text" >
+ <string>view SSL Certificate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>48</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2" >
+ <item>
+ <widget class="QCheckBox" name="ignoreWarningsPermanently" >
+ <property name="text" >
+ <string>add to known hosts</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="ignoreWarningsButton" >
+ <property name="text" >
+ <string>Continue connection</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
<widget class="QWidget" name="coreConfigPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>485</width>
+ <height>135</height>
+ </rect>
+ </property>
<layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
<item>
<widget class="QGroupBox" name="groupBox_4" >
<property name="sizePolicy" >
</layout>
</item>
</layout>
+ <zorder>label_7</zorder>
+ <zorder></zorder>
</widget>
</item>
- <item>
- <spacer>
- <property name="orientation" >
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0" >
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
</layout>
</widget>
- <widget class="QWidget" name="loginEmptyPage" />
+ <widget class="QWidget" name="loginEmptyPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>485</width>
+ <height>135</height>
+ </rect>
+ </property>
+ </widget>
</widget>
</item>
</layout>
</layout>
</widget>
<widget class="QWidget" name="syncPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>100</width>
+ <height>30</height>
+ </rect>
+ </property>
<layout class="QVBoxLayout" >
<item>
<widget class="QGroupBox" name="groupBox_3" >