File indexing completed on 2024-06-09 05:21:30

0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
0002 
0003    This file is part of the Trojita Qt IMAP e-mail client,
0004    http://trojita.flaska.net/
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public License as
0008    published by the Free Software Foundation; either version 2 of
0009    the License or (at your option) version 3 or any later version
0010    accepted by the membership of KDE e.V. (or its successor approved
0011    by the membership of KDE e.V.), which shall act as a proxy
0012    defined in Section 14 of version 3 of the license.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017    GNU General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 #include <QBuffer>
0024 #include <QTimer>
0025 #include "FakeSocket.h"
0026 
0027 namespace Streams {
0028 
0029 FakeSocket::FakeSocket(const Imap::ConnectionState initialState): m_initialState(initialState)
0030 {
0031     readChannel = new QBuffer(&r, this);
0032     readChannel->open(QIODevice::ReadWrite);
0033     writeChannel = new QBuffer(&w, this);
0034     writeChannel->open(QIODevice::WriteOnly);
0035     QTimer::singleShot(0, this, SLOT(slotEmitConnected()));
0036     connect(readChannel, &QIODevice::readyRead, this, &Socket::readyRead);
0037 }
0038 
0039 FakeSocket::~FakeSocket()
0040 {
0041 }
0042 
0043 void FakeSocket::slotEmitConnected()
0044 {
0045     if (m_initialState == Imap::CONN_STATE_LOGOUT) {
0046         // Special case: a fake socket factory for unconfigured accounts.
0047         emit disconnected(QString());
0048         return;
0049     }
0050 
0051     // We have to use both conventions for letting the world know that "we're finally usable"
0052     if (m_initialState != Imap::CONN_STATE_CONNECTED_PRETLS_PRECAPS)
0053         emit stateChanged(Imap::CONN_STATE_CONNECTED_PRETLS_PRECAPS, QString());
0054     emit stateChanged(m_initialState, QString());
0055 }
0056 
0057 void FakeSocket::slotEmitEncrypted()
0058 {
0059     emit encrypted();
0060 }
0061 
0062 void FakeSocket::fakeReading(const QByteArray &what)
0063 {
0064     // The position of the cursor is shared for both reading and writing, and therefore
0065     // we have to save and restore it after appending data, otherwise the pointer will
0066     // be left scrolled to after the actual data, failing further attempts to read the
0067     // data back. It's pretty obvious when you think about it, but took sime time to
0068     // debug nevertheless :).
0069     qint64 pos = readChannel->pos();
0070     if (pos > 1024 * 1024) {
0071         // There's too much stale data in the socket already, let's cut it
0072         QByteArray unProcessedData = readChannel->readAll();
0073         r.clear();
0074         readChannel->close();
0075         static_cast<QBuffer *>(readChannel)->setBuffer(&r);
0076         readChannel->open(QIODevice::ReadWrite);
0077         readChannel->write(unProcessedData);
0078         pos = unProcessedData.size();
0079     }
0080     readChannel->seek(r.size());
0081     readChannel->write(what);
0082     readChannel->seek(pos);
0083 }
0084 
0085 void FakeSocket::fakeDisconnect(const QString &message)
0086 {
0087     readChannel->write(QString::fromUtf8("[*** disconnected: %1 ***]").arg(message).toUtf8());
0088     emit disconnected(message);
0089 }
0090 
0091 bool FakeSocket::canReadLine()
0092 {
0093     return readChannel->canReadLine();
0094 }
0095 
0096 QByteArray FakeSocket::read(qint64 maxSize)
0097 {
0098     return readChannel->read(maxSize);
0099 }
0100 
0101 QByteArray FakeSocket::readLine(qint64 maxSize)
0102 {
0103     return readChannel->readLine(maxSize);
0104 }
0105 
0106 qint64 FakeSocket::write(const QByteArray &byteArray)
0107 {
0108     return writeChannel->write(byteArray);
0109 }
0110 
0111 void FakeSocket::startTls()
0112 {
0113     // fake it
0114     writeChannel->write(QByteArray("[*** STARTTLS ***]"));
0115     QTimer::singleShot(0, this, SLOT(slotEmitEncrypted()));
0116 }
0117 
0118 void FakeSocket::startDeflate()
0119 {
0120     // fake it
0121     writeChannel->write(QByteArray("[*** DEFLATE ***]"));
0122 }
0123 
0124 bool FakeSocket::isDead()
0125 {
0126     // Can't really die (yet)
0127     return false;
0128 }
0129 
0130 void FakeSocket::close()
0131 {
0132     // fake it
0133     writeChannel->write(QByteArray("[*** close ***]"));
0134 }
0135 
0136 QByteArray FakeSocket::writtenStuff()
0137 {
0138     QByteArray res = w;
0139     w.clear();
0140     writeChannel->seek(0);
0141     return res;
0142 }
0143 
0144 }