File indexing completed on 2024-06-23 05:15:11
0001 /* 0002 SPDX-FileCopyrightText: 2006-2007 KovoKs <info@kovoks.nl> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 // Uncomment the next line for full comm debug 0008 // #define comm_debug 0009 0010 // Own 0011 #include "socket.h" 0012 0013 // Qt 0014 #include <QByteArray> 0015 #include <QNetworkProxy> 0016 // KDE 0017 #include "mailtransport_debug.h" 0018 0019 using namespace MailTransport; 0020 0021 namespace MailTransport 0022 { 0023 class SocketPrivate 0024 { 0025 public: 0026 SocketPrivate(Socket *s); 0027 Socket *const q; 0028 QSslSocket *socket = nullptr; 0029 QString server; 0030 QString protocol; 0031 int port = 0; 0032 bool secure = false; 0033 0034 // slots 0035 void slotConnected(); 0036 void slotStateChanged(QAbstractSocket::SocketState state); 0037 void slotModeChanged(QSslSocket::SslMode state); 0038 void slotSocketRead(); 0039 void slotSslErrors(const QList<QSslError> &errors); 0040 0041 private: 0042 QString m_msg; 0043 }; 0044 } 0045 0046 SocketPrivate::SocketPrivate(Socket *s) 0047 : q(s) 0048 { 0049 } 0050 0051 void SocketPrivate::slotConnected() 0052 { 0053 qCDebug(MAILTRANSPORT_LOG); 0054 0055 if (!secure) { 0056 qCDebug(MAILTRANSPORT_LOG) << "normal connect"; 0057 Q_EMIT q->connected(); 0058 } else { 0059 qCDebug(MAILTRANSPORT_LOG) << "encrypted connect"; 0060 socket->startClientEncryption(); 0061 } 0062 } 0063 0064 void SocketPrivate::slotStateChanged(QAbstractSocket::SocketState state) 0065 { 0066 #ifdef comm_debug 0067 qCDebug(MAILTRANSPORT_LOG) << "State is now:" << (int)state; 0068 #endif 0069 if (state == QAbstractSocket::UnconnectedState) { 0070 Q_EMIT q->failed(); 0071 } 0072 } 0073 0074 void SocketPrivate::slotModeChanged(QSslSocket::SslMode state) 0075 { 0076 #ifdef comm_debug 0077 qCDebug(MAILTRANSPORT_LOG) << "Mode is now:" << state; 0078 #endif 0079 if (state == QSslSocket::SslClientMode) { 0080 Q_EMIT q->tlsDone(); 0081 } 0082 } 0083 0084 void SocketPrivate::slotSocketRead() 0085 { 0086 qCDebug(MAILTRANSPORT_LOG); 0087 0088 if (!socket) { 0089 return; 0090 } 0091 0092 m_msg += QLatin1StringView(socket->readAll()); 0093 0094 if (!m_msg.endsWith(QLatin1Char('\n'))) { 0095 return; 0096 } 0097 0098 #ifdef comm_debug 0099 qCDebug(MAILTRANSPORT_LOG) << socket->isEncrypted() << m_msg.trimmed(); 0100 #endif 0101 0102 Q_EMIT q->data(m_msg); 0103 m_msg.clear(); 0104 } 0105 0106 void SocketPrivate::slotSslErrors(const QList<QSslError> &) 0107 { 0108 qCDebug(MAILTRANSPORT_LOG); 0109 /* We can safely ignore the errors, we are only interested in the 0110 capabilities. We're not sending auth info. */ 0111 socket->ignoreSslErrors(); 0112 Q_EMIT q->connected(); 0113 } 0114 0115 // ------------------ end private ---------------------------// 0116 0117 Socket::Socket(QObject *parent) 0118 : QObject(parent) 0119 , d(new SocketPrivate(this)) 0120 { 0121 qCDebug(MAILTRANSPORT_LOG); 0122 } 0123 0124 Socket::~Socket() 0125 { 0126 qCDebug(MAILTRANSPORT_LOG); 0127 } 0128 0129 void Socket::reconnect() 0130 { 0131 qCDebug(MAILTRANSPORT_LOG) << "Connecting to:" << d->server << ":" << d->port; 0132 0133 #ifdef comm_debug 0134 // qCDebug(MAILTRANSPORT_LOG) << d->protocol; 0135 #endif 0136 0137 if (d->socket) { 0138 return; 0139 } 0140 0141 d->socket = new QSslSocket(this); 0142 d->socket->setProxy(QNetworkProxy::DefaultProxy); 0143 d->socket->connectToHost(d->server, d->port); 0144 0145 d->socket->setProtocol(QSsl::AnyProtocol); 0146 0147 connect(d->socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(slotStateChanged(QAbstractSocket::SocketState))); 0148 connect(d->socket, SIGNAL(modeChanged(QSslSocket::SslMode)), SLOT(slotModeChanged(QSslSocket::SslMode))); 0149 connect(d->socket, SIGNAL(connected()), SLOT(slotConnected())); 0150 connect(d->socket, SIGNAL(readyRead()), SLOT(slotSocketRead())); 0151 connect(d->socket, &QSslSocket::encrypted, this, &Socket::connected); 0152 connect(d->socket, SIGNAL(sslErrors(QList<QSslError>)), SLOT(slotSslErrors(QList<QSslError>))); 0153 } 0154 0155 void Socket::write(const QString &text) 0156 { 0157 // qCDebug(MAILTRANSPORT_LOG); 0158 // Eat things in the queue when there is no connection. We need 0159 // to get a connection first don't we... 0160 if (!d->socket || !available()) { 0161 return; 0162 } 0163 0164 QByteArray cs = (text + QLatin1StringView("\r\n")).toLatin1(); 0165 0166 #ifdef comm_debug 0167 qCDebug(MAILTRANSPORT_LOG) << "C :" << cs; 0168 #endif 0169 0170 d->socket->write(cs.data(), cs.size()); 0171 } 0172 0173 bool Socket::available() 0174 { 0175 // qCDebug(MAILTRANSPORT_LOG); 0176 bool ok = d->socket && d->socket->state() == QAbstractSocket::ConnectedState; 0177 return ok; 0178 } 0179 0180 void Socket::startTLS() 0181 { 0182 qCDebug(MAILTRANSPORT_LOG) << objectName(); 0183 d->socket->setProtocol(QSsl::TlsV1_2OrLater); 0184 d->socket->startClientEncryption(); 0185 } 0186 0187 void Socket::setProtocol(const QString &proto) 0188 { 0189 d->protocol = proto; 0190 } 0191 0192 void Socket::setServer(const QString &server) 0193 { 0194 d->server = server; 0195 } 0196 0197 void Socket::setPort(int port) 0198 { 0199 d->port = port; 0200 } 0201 0202 int Socket::port() const 0203 { 0204 return d->port; 0205 } 0206 0207 void Socket::setSecure(bool what) 0208 { 0209 d->secure = what; 0210 } 0211 0212 #include "moc_socket.cpp"