diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ project(KIMAP VERSION ${PIM_VERSION}) +set(CMAKE_CXX_STANDARD 14) + # ECM setup set(KF5_MIN_VERSION "5.62.0") diff --git a/src/job_p.h b/src/job_p.h --- a/src/job_p.h +++ b/src/job_p.h @@ -21,7 +21,7 @@ #define KIMAP_JOB_P_H #include "session.h" -#include +#include namespace KIMAP { @@ -31,7 +31,7 @@ class JobPrivate { public: - JobPrivate(Session *session, const QString &name) : m_session(session), m_socketError(KTcpSocket::UnknownError) + JobPrivate(Session *session, const QString &name) : m_session(session) { m_name = name; } @@ -47,15 +47,15 @@ return m_session->d; } - void setSocketError(KTcpSocket::Error error) + void setSocketError(QAbstractSocket::SocketError error) { m_socketError = error; } QList tags; Session *m_session = nullptr; QString m_name; - KTcpSocket::Error m_socketError; + QAbstractSocket::SocketError m_socketError = QAbstractSocket::UnknownSocketError; }; } diff --git a/src/loginjob.cpp b/src/loginjob.cpp --- a/src/loginjob.cpp +++ b/src/loginjob.cpp @@ -21,8 +21,9 @@ #include "loginjob.h" #include +#include + #include "kimap_debug.h" -#include #include "job_p.h" #include "response_p.h" @@ -207,14 +208,14 @@ EncryptionMode encryptionMode = d->encryptionMode; const auto negotiatedEncryption = d->sessionInternal()->negotiatedEncryption(); - if (negotiatedEncryption != KTcpSocket::UnknownSslVersion) { + if (negotiatedEncryption != QSsl::UnknownProtocol) { // If the socket is already encrypted, pretend we did not want any // encryption encryptionMode = Unencrypted; } if (encryptionMode == SSLorTLS) { - d->sessionInternal()->startSsl(KTcpSocket::SecureProtocols); + d->sessionInternal()->startSsl(QSsl::SecureProtocols); } else if (encryptionMode == STARTTLS) { // Check if STARTTLS is supported d->authState = LoginJobPrivate::PreStartTlsCapability; @@ -363,7 +364,7 @@ break; case LoginJobPrivate::StartTls: - d->sessionInternal()->startSsl(KTcpSocket::SecureProtocols); + d->sessionInternal()->startSsl(QSsl::SecureProtocols); break; case LoginJobPrivate::Capability: @@ -573,7 +574,7 @@ //the TLS handshake failed and the socket was reconnected in normal mode if (d->authState != LoginJobPrivate::StartTls) { qCWarning(KIMAP_LOG) << "Connection to server lost " << d->m_socketError; - if (d->m_socketError == KTcpSocket::SslHandshakeFailedError) { + if (d->m_socketError == QAbstractSocket::SslHandshakeFailedError) { setError(KJob::UserDefinedError); setErrorText(i18n("SSL handshake failed.")); emitResult(); diff --git a/src/session.cpp b/src/session.cpp --- a/src/session.cpp +++ b/src/session.cpp @@ -37,9 +37,9 @@ #include "sessionthread_p.h" #include "rfccodecs.h" -Q_DECLARE_METATYPE(KTcpSocket::SslVersion) +Q_DECLARE_METATYPE(QSsl::SslProtocol) Q_DECLARE_METATYPE(QSslSocket::SslMode) -static const int _kimap_sslVersionId = qRegisterMetaType(); +static const int _kimap_sslVersionId = qRegisterMetaType(); using namespace KIMAP; @@ -148,7 +148,7 @@ jobRunning(false), currentJob(nullptr), tagCount(0), - sslVersion(KTcpSocket::UnknownSslVersion), + sslVersion(QSsl::UnknownProtocol), socketTimerInterval(30000) // By default timeouts on 30s { } @@ -407,7 +407,7 @@ restartSocketTimer(); } -void SessionPrivate::socketError(KTcpSocket::Error error) +void SessionPrivate::socketError(QAbstractSocket::SocketError error) { if (socketTimer.isActive()) { stopSocketTimer(); @@ -443,27 +443,27 @@ emit q->jobQueueSizeChanged(0); } -void SessionPrivate::startSsl(KTcpSocket::SslVersion version) +void SessionPrivate::startSsl(QSsl::SslProtocol protocol) { - thread->startSsl(version); + thread->startSsl(protocol); } QString Session::selectedMailBox() const { return QString::fromUtf8(d->currentMailBox); } -void SessionPrivate::onEncryptionNegotiationResult(bool isEncrypted, KTcpSocket::SslVersion version) +void SessionPrivate::onEncryptionNegotiationResult(bool isEncrypted, QSsl::SslProtocol protocol) { if (isEncrypted) { - sslVersion = version; + sslVersion = protocol; } else { - sslVersion = KTcpSocket::UnknownSslVersion; + sslVersion = QSsl::UnknownProtocol; } emit encryptionNegotiationResult(isEncrypted); } -KTcpSocket::SslVersion SessionPrivate::negotiatedEncryption() const +QSsl::SslProtocol SessionPrivate::negotiatedEncryption() const { return sslVersion; } diff --git a/src/session_p.h b/src/session_p.h --- a/src/session_p.h +++ b/src/session_p.h @@ -23,12 +23,11 @@ #include "session.h" #include "sessionuiproxy.h" -#include - #include #include #include #include +#include class KJob; @@ -52,19 +51,19 @@ void addJob(Job *job); QByteArray sendCommand(const QByteArray &command, const QByteArray &args = QByteArray()); - void startSsl(KTcpSocket::SslVersion version); + void startSsl(QSsl::SslProtocol protocol); void sendData(const QByteArray &data); - KTcpSocket::SslVersion negotiatedEncryption() const; + QSsl::SslProtocol negotiatedEncryption() const; void setSocketTimeout(int ms); int socketTimeout() const; Q_SIGNALS: void encryptionNegotiationResult(bool); private Q_SLOTS: - void onEncryptionNegotiationResult(bool isEncrypted, KTcpSocket::SslVersion sslVersion); + void onEncryptionNegotiationResult(bool isEncrypted, QSsl::SslProtocol sslVersion); void onSocketTimeout(); void doStartNext(); @@ -74,7 +73,7 @@ void socketConnected(); void socketDisconnected(); - void socketError(KTcpSocket::Error); + void socketError(QAbstractSocket::SocketError error); void socketActivity(); void handleSslError(const KSslErrorUiData &errorData); @@ -112,7 +111,7 @@ QByteArray upcomingMailBox; quint16 tagCount; - KTcpSocket::SslVersion sslVersion; + QSsl::SslProtocol sslVersion; int socketTimerInterval = 0; QTimer socketTimer; diff --git a/src/sessionthread.cpp b/src/sessionthread.cpp --- a/src/sessionthread.cpp +++ b/src/sessionthread.cpp @@ -19,25 +19,28 @@ #include "sessionthread_p.h" +#include + #include #include #include - +#include #include "kimap_debug.h" #include "imapstreamparser.h" #include "response_p.h" using namespace KIMAP; -Q_DECLARE_METATYPE(KTcpSocket::Error) Q_DECLARE_METATYPE(KSslErrorUiData) -static const int _kimap_socketErrorTypeId = qRegisterMetaType(); + +namespace { +static const int _kimap_abstractSocketError = qRegisterMetaType(); static const int _kimap_sslErrorUiData = qRegisterMetaType(); +} SessionThread::SessionThread(const QString &hostName, quint16 port) : QObject(), m_hostName(hostName), m_port(port), - m_socket(nullptr), m_stream(nullptr), m_mutex(), m_encryptedMode(false), m_useProxy(false) { @@ -168,8 +171,8 @@ if (m_socket == nullptr) { // threadQuit already called return; } - if (m_socket->state() != SessionSocket::ConnectedState && - m_socket->state() != SessionSocket::ConnectingState) { + if (m_socket->state() != QSslSocket::ConnectedState && + m_socket->state() != QSslSocket::ConnectingState) { QNetworkProxy proxy; if (!m_useProxy) { @@ -195,69 +198,65 @@ void SessionThread::threadInit() { Q_ASSERT(QThread::currentThread() == thread()); - m_socket = new SessionSocket; - m_stream = new ImapStreamParser(m_socket); - connect(m_socket, &QIODevice::readyRead, + m_socket = std::make_unique(); + m_stream = std::make_unique(m_socket.get()); + connect(m_socket.get(), &QIODevice::readyRead, this, &SessionThread::readMessage, Qt::QueuedConnection); // Delay the call to slotSocketDisconnected so that it finishes disconnecting before we call reconnect() - connect(m_socket, &KTcpSocket::disconnected, + connect(m_socket.get(), &QSslSocket::disconnected, this, &SessionThread::slotSocketDisconnected, Qt::QueuedConnection); - connect(m_socket, &KTcpSocket::connected, + connect(m_socket.get(), &QSslSocket::connected, this, &SessionThread::socketConnected); - connect(m_socket, SIGNAL(error(KTcpSocket::Error)), - this, SLOT(slotSocketError(KTcpSocket::Error))); - connect(m_socket, &QIODevice::bytesWritten, + connect(m_socket.get(), QOverload::of(&QAbstractSocket::error), + this, &SessionThread::slotSocketError); + connect(m_socket.get(), &QIODevice::bytesWritten, this, &SessionThread::socketActivity); - if (m_socket->metaObject()->indexOfSignal("encryptedBytesWritten(qint64)") > -1) { - connect(m_socket, &KTcpSocket::encryptedBytesWritten, // needs kdelibs > 4.8 - this, &SessionThread::socketActivity); - } - connect(m_socket, &QIODevice::readyRead, + connect(m_socket.get(), &QSslSocket::encryptedBytesWritten, + this, &SessionThread::socketActivity); + connect(m_socket.get(), &QIODevice::readyRead, this, &SessionThread::socketActivity); QMetaObject::invokeMethod(this, &SessionThread::reconnect, Qt::QueuedConnection); } // Called in secondary thread void SessionThread::threadQuit() { Q_ASSERT(QThread::currentThread() == thread()); - delete m_stream; - m_stream = nullptr; - delete m_socket; - m_socket = nullptr; + m_stream.reset(); + m_socket.reset(); thread()->quit(); } // Called in secondary thread void SessionThread::setUseProxyInternal(bool useProxy) { m_useProxy = useProxy; if (m_socket != nullptr) { - if (m_socket->state() != SessionSocket::UnconnectedState) { + if (m_socket->state() != QSslSocket::UnconnectedState) { m_socket->disconnectFromHost(); QMetaObject::invokeMethod(this, &SessionThread::reconnect, Qt::QueuedConnection); } } } // Called in primary thread -void SessionThread::startSsl(KTcpSocket::SslVersion version) +void SessionThread::startSsl(QSsl::SslProtocol protocol) { - QMetaObject::invokeMethod(this, [this, version]() { doStartSsl(version); }); + QMetaObject::invokeMethod(this, [this, protocol]() { doStartSsl(protocol); }); } // Called in secondary thread (via invokeMethod) -void SessionThread::doStartSsl(KTcpSocket::SslVersion version) +void SessionThread::doStartSsl(QSsl::SslProtocol protocol) { Q_ASSERT(QThread::currentThread() == thread()); if (!m_socket) { return; } - m_socket->setAdvertisedSslVersion(version); - m_socket->ignoreSslErrors(); - connect(m_socket, &KTcpSocket::encrypted, this, &SessionThread::sslConnected); + m_socket->setProtocol(protocol); + m_socket->ignoreSslErrors(); // Don't worry, errors are handled manually below + connect(m_socket.get(), &QSslSocket::encrypted, this, &SessionThread::sslConnected); m_socket->startClientEncryption(); } @@ -269,13 +268,12 @@ } // Called in secondary thread -void SessionThread::slotSocketError(KTcpSocket::Error error) +void SessionThread::slotSocketError(QAbstractSocket::SocketError error) { Q_ASSERT(QThread::currentThread() == thread()); if (!m_socket) { return; } - Q_UNUSED(error); // can be used for debugging emit socketError(error); } @@ -286,22 +284,21 @@ if (!m_socket) { return; } - KSslCipher cipher = m_socket->sessionCipher(); + QSslCipher cipher = m_socket->sessionCipher(); - if (!m_socket->sslErrors().isEmpty() || - m_socket->encryptionMode() != KTcpSocket::SslClientMode || - cipher.isNull() || cipher.usedBits() == 0) { + if (!m_socket->sslErrors().isEmpty() || !m_socket->isEncrypted() + || cipher.isNull() || cipher.usedBits() == 0) { qCDebug(KIMAP_LOG) << "Initial SSL handshake failed. cipher.isNull() is" << cipher.isNull() << ", cipher.usedBits() is" << cipher.usedBits() << ", the socket says:" << m_socket->errorString() << "and the list of SSL errors contains" << m_socket->sslErrors().count() << "items."; - KSslErrorUiData errorData(m_socket); + KSslErrorUiData errorData(m_socket.get()); emit sslError(errorData); } else { - qCDebug(KIMAP_LOG) << "TLS negotiation done."; + qCDebug(KIMAP_LOG) << "TLS negotiation done, the negotiated protocol is" << cipher.protocolString(); m_encryptedMode = true; - emit encryptionNegotiationResult(true, m_socket->negotiatedSslVersion()); + emit encryptionNegotiationResult(true, m_socket->sessionProtocol()); } } @@ -319,14 +316,14 @@ } if (response) { m_encryptedMode = true; - emit encryptionNegotiationResult(true, m_socket->negotiatedSslVersion()); + emit encryptionNegotiationResult(true, m_socket->sessionProtocol()); } else { m_encryptedMode = false; //reconnect in unencrypted mode, so new commands can be issued m_socket->disconnectFromHost(); m_socket->waitForDisconnected(); m_socket->connectToHost(m_hostName, m_port); - emit encryptionNegotiationResult(false, KTcpSocket::UnknownSslVersion); + emit encryptionNegotiationResult(false, QSsl::UnknownProtocol); } } diff --git a/src/sessionthread_p.h b/src/sessionthread_p.h --- a/src/sessionthread_p.h +++ b/src/sessionthread_p.h @@ -23,9 +23,11 @@ #include #include -#include +#include -typedef KTcpSocket SessionSocket; +#include + +class KSslErrorUiData; namespace KIMAP { @@ -56,16 +58,16 @@ public Q_SLOTS: void closeSocket(); - void startSsl(KTcpSocket::SslVersion version); + void startSsl(QSsl::SslProtocol protocol); void sslErrorHandlerResponse(bool result); Q_SIGNALS: void socketConnected(); void socketDisconnected(); void socketActivity(); - void socketError(KTcpSocket::Error); + void socketError(QAbstractSocket::SocketError); void responseReceived(const KIMAP::Response &response); - void encryptionNegotiationResult(bool, KTcpSocket::SslVersion); + void encryptionNegotiationResult(bool, QSsl::SslProtocol); void sslError(const KSslErrorUiData &); private Q_SLOTS: @@ -76,18 +78,18 @@ void writeDataQueue(); void sslConnected(); void doCloseSocket(); - void slotSocketError(KTcpSocket::Error); + void slotSocketError(QAbstractSocket::SocketError); void slotSocketDisconnected(); - void doStartSsl(KTcpSocket::SslVersion); + void doStartSsl(QSsl::SslProtocol); void doSslErrorHandlerResponse(bool result); void setUseProxyInternal(bool useProxy); private: QString m_hostName; quint16 m_port; - SessionSocket *m_socket = nullptr; - ImapStreamParser *m_stream = nullptr; + std::unique_ptr m_socket; + std::unique_ptr m_stream; QQueue m_dataQueue;