setProgressMaximum(-1); // disable
setState(Disconnected);
emit connectionMsg(tr("Disconnected from core."));
+ emit encrypted(false);
+}
+
+bool CoreConnection::isEncrypted() const {
+#ifndef HAVE_SSL
+ return false;
+#else
+ QSslSocket *sock = qobject_cast<QSslSocket *>(_socket);
+ return isConnected() && sock && sock->isEncrypted();
+#endif
}
void CoreConnection::socketStateChanged(QAbstractSocket::SocketState socketState) {
switch(socketState) {
case QAbstractSocket::UnconnectedState:
- text = tr("Disconnected.");
+ text = tr("Disconnected");
break;
case QAbstractSocket::HostLookupState:
text = tr("Looking up %1...").arg(currentAccount().hostName());
text = tr("Connecting to %1...").arg(currentAccount().hostName());
break;
case QAbstractSocket::ConnectedState:
- text = tr("Connected to %1.").arg(currentAccount().hostName());
+ text = tr("Connected to %1").arg(currentAccount().hostName());
break;
case QAbstractSocket::ClosingState:
text = tr("Disconnecting from %1...").arg(currentAccount().hostName());
case QAbstractSocket::ConnectingState:
state = Connecting;
break;
- case QAbstractSocket::ConnectedState:
- state = Connected;
- break;
default:
state = Disconnected;
}
}
}
-void CoreConnection::setWarningsHandler(const char *slot) {
- resetWarningsHandler();
- connect(this, SIGNAL(handleIgnoreWarnings(bool)), this, slot);
-}
-
-void CoreConnection::resetWarningsHandler() {
- disconnect(this, SIGNAL(handleIgnoreWarnings(bool)), this, 0);
-}
-
void CoreConnection::coreSocketError(QAbstractSocket::SocketError) {
qDebug() << "coreSocketError" << _socket << _socket->errorString();
emit connectionError(_socket->errorString());
QVariantMap msg = item.toMap();
if(!msg.contains("MsgType")) {
// This core is way too old and does not even speak our init protocol...
- emit connectionError(tr("The Quassel Core you try to connect to is too old! Please consider upgrading."));
+ emit connectionErrorPopup(tr("The Quassel Core you try to connect to is too old! Please consider upgrading."));
disconnectFromCore();
return;
}
if(msg["MsgType"] == "ClientInitAck") {
clientInitAck(msg);
} else if(msg["MsgType"] == "ClientInitReject") {
- emit connectionError(msg["Error"].toString());
+ emit connectionErrorPopup(msg["Error"].toString());
disconnectFromCore();
return;
} else if(msg["MsgType"] == "CoreSetupAck") {
- //emit coreSetupSuccess();
+ emit coreSetupSuccess();
} else if(msg["MsgType"] == "CoreSetupReject") {
- //emit coreSetupFailed(msg["Error"].toString());
+ emit coreSetupFailed(msg["Error"].toString());
} else if(msg["MsgType"] == "ClientLoginReject") {
loginFailed(msg["Error"].toString());
} else if(msg["MsgType"] == "ClientLoginAck") {
sessionStateReceived(msg["SessionState"].toMap());
break; // this is definitively the last message we process here!
} else {
- emit connectionError(tr("<b>Invalid data received from core!</b><br>Disconnecting."));
- disconnectFromCore();
+ disconnectFromCore(tr("Invalid data received from core"));
return;
}
}
}
}
-void CoreConnection::disconnectFromCore() {
+void CoreConnection::disconnectFromCore(const QString &errorString) {
+ if(errorString.isEmpty())
+ emit connectionError(tr("Disconnected"));
+ else
+ emit connectionError(errorString);
+
Client::signalProxy()->removeAllPeers();
resetConnection();
}
return;
}
+ CoreAccountSettings s;
+
Q_ASSERT(!_socket);
#ifdef HAVE_SSL
QSslSocket *sock = new QSslSocket(Client::instance());
+ // make sure the warning is shown if we happen to connect without SSL support later
+ s.setAccountValue("ShowNoClientSslWarning", true);
#else
if(_account.useSsl()) {
- emit connectionError(tr("<b>This client is built without SSL Support!</b><br />Disable the usage of SSL in the account settings."));
- return;
+ if(s.accountValue("ShowNoClientSslWarning", true).toBool()) {
+ bool accepted = false;
+ emit handleNoSslInClient(&accepted);
+ if(!accepted) {
+ emit connectionError(tr("Unencrypted connection canceled"));
+ return;
+ }
+ s.setAccountValue("ShowNoClientSslWarning", false);
+ }
}
QTcpSocket *sock = new QTcpSocket(Client::instance());
#endif
// Core has accepted our version info and sent its own. Let's see if we accept it as well...
uint ver = msg["ProtocolVersion"].toUInt();
if(ver < Quassel::buildInfo().clientNeedsProtocol) {
- emit connectionError(tr("<b>The Quassel Core you are trying to connect to is too old!</b><br>"
+ emit connectionErrorPopup(tr("<b>The Quassel Core you are trying to connect to is too old!</b><br>"
"Need at least core/client protocol v%1 to connect.").arg(Quassel::buildInfo().clientNeedsProtocol));
disconnectFromCore();
return;
#endif
_coreMsgBuffer = msg;
+
#ifdef HAVE_SSL
+ CoreAccountSettings s;
if(currentAccount().useSsl()) {
if(msg["SupportSsl"].toBool()) {
+ // Make sure the warning is shown next time we don't have SSL in the core
+ s.setAccountValue("ShowNoCoreSslWarning", true);
+
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> &)));
-
+ connect(sslSocket, SIGNAL(encrypted()), SLOT(sslSocketEncrypted()));
+ connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError> &)), SLOT(sslErrors()));
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();
+ if(s.accountValue("ShowNoCoreSslWarning", true).toBool()) {
+ bool accepted = false;
+ emit handleNoSslInCore(&accepted);
+ if(!accepted) {
+ disconnectFromCore(tr("Unencrypted connection canceled"));
+ return;
+ }
+ s.setAccountValue("ShowNoCoreSslWarning", false);
+ s.setAccountValue("SslCert", QString());
+ }
+ connectionReady();
}
return;
}
#endif
// if we use SSL we wait for the next step until every SSL warning has been cleared
connectionReady();
+}
+
+#ifdef HAVE_SSL
+
+void CoreConnection::sslSocketEncrypted() {
+ QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
+ Q_ASSERT(socket);
+
+ if(!socket->sslErrors().count()) {
+ // Cert is valid, so we don't want to store it as known
+ // That way, a warning will appear in case it becomes invalid at some point
+ CoreAccountSettings s;
+ s.setAccountValue("SSLCert", QString());
+ }
+
+ emit encrypted(true);
+ connectionReady();
+}
+
+void CoreConnection::sslErrors() {
+ QSslSocket *socket = qobject_cast<QSslSocket *>(sender());
+ Q_ASSERT(socket);
+
+ CoreAccountSettings s;
+ QByteArray knownDigest = s.accountValue("SslCert").toByteArray();
+
+ if(knownDigest != socket->peerCertificate().digest()) {
+ bool accepted = false;
+ bool permanently = false;
+ emit handleSslErrors(socket, &accepted, &permanently);
+ if(!accepted) {
+ disconnectFromCore(tr("Unencrypted connection canceled"));
+ return;
+ }
+
+ if(permanently)
+ s.setAccountValue("SslCert", socket->peerCertificate().digest());
+ else
+ s.setAccountValue("SslCert", QString());
+ }
+
+ socket->ignoreSslErrors();
}
+#endif /* HAVE_SSL */
+
void CoreConnection::connectionReady() {
+ setState(Connected);
+ emit connectionMsg(tr("Connected to %1").arg(currentAccount().accountName()));
+
if(!_coreMsgBuffer["Configured"].toBool()) {
// start wizard
emit startCoreSetup(_coreMsgBuffer["StorageBackends"].toList());
loginToCore();
}
_coreMsgBuffer.clear();
- resetWarningsHandler();
+}
+
+void CoreConnection::loginToCore(const QString &user, const QString &password, bool remember) {
+ _account.setUser(user);
+ _account.setPassword(password);
+ _account.setStorePassword(remember);
+ loginToCore();
}
void CoreConnection::loginToCore(const QString &prevError) {
bool valid = false;
emit userAuthenticationRequired(&_account, &valid, prevError); // *must* be a synchronous call
if(!valid || currentAccount().user().isEmpty() || currentAccount().password().isEmpty()) {
- disconnectFromCore();
- emit connectionError(tr("Login canceled"));
+ disconnectFromCore(tr("Login canceled"));
return;
}
}
void CoreConnection::checkSyncState() {
if(_netsToSync.isEmpty()) {
setState(Synchronized);
- setProgressText(QString());
+ setProgressText(tr("Synchronized to %1").arg(currentAccount().accountName()));
setProgressMaximum(-1);
emit synchronized();
}
}
+
+void CoreConnection::doCoreSetup(const QVariant &setupData) {
+ QVariantMap setup;
+ setup["MsgType"] = "CoreSetupData";
+ setup["SetupData"] = setupData;
+ SignalProxy::writeDataToDevice(_socket, setup);
+}