1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
2
3 This file is part of the Trojita Qt IMAP e-mail client,
4 http://trojita.flaska.net/
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include <QBuffer>
24 #include <QTimer>
25 #include "FakeSocket.h"
26
27 namespace Streams {
28
FakeSocket(const Imap::ConnectionState initialState)29 FakeSocket::FakeSocket(const Imap::ConnectionState initialState): m_initialState(initialState)
30 {
31 readChannel = new QBuffer(&r, this);
32 readChannel->open(QIODevice::ReadWrite);
33 writeChannel = new QBuffer(&w, this);
34 writeChannel->open(QIODevice::WriteOnly);
35 QTimer::singleShot(0, this, SLOT(slotEmitConnected()));
36 connect(readChannel, &QIODevice::readyRead, this, &Socket::readyRead);
37 }
38
~FakeSocket()39 FakeSocket::~FakeSocket()
40 {
41 }
42
slotEmitConnected()43 void FakeSocket::slotEmitConnected()
44 {
45 if (m_initialState == Imap::CONN_STATE_LOGOUT) {
46 // Special case: a fake socket factory for unconfigured accounts.
47 emit disconnected(QString());
48 return;
49 }
50
51 // We have to use both conventions for letting the world know that "we're finally usable"
52 if (m_initialState != Imap::CONN_STATE_CONNECTED_PRETLS_PRECAPS)
53 emit stateChanged(Imap::CONN_STATE_CONNECTED_PRETLS_PRECAPS, QString());
54 emit stateChanged(m_initialState, QString());
55 }
56
slotEmitEncrypted()57 void FakeSocket::slotEmitEncrypted()
58 {
59 emit encrypted();
60 }
61
fakeReading(const QByteArray & what)62 void FakeSocket::fakeReading(const QByteArray &what)
63 {
64 // The position of the cursor is shared for both reading and writing, and therefore
65 // we have to save and restore it after appending data, otherwise the pointer will
66 // be left scrolled to after the actual data, failing further attempts to read the
67 // data back. It's pretty obvious when you think about it, but took sime time to
68 // debug nevertheless :).
69 qint64 pos = readChannel->pos();
70 if (pos > 1024 * 1024) {
71 // There's too much stale data in the socket already, let's cut it
72 QByteArray unProcessedData = readChannel->readAll();
73 r.clear();
74 readChannel->close();
75 static_cast<QBuffer *>(readChannel)->setBuffer(&r);
76 readChannel->open(QIODevice::ReadWrite);
77 readChannel->write(unProcessedData);
78 pos = unProcessedData.size();
79 }
80 readChannel->seek(r.size());
81 readChannel->write(what);
82 readChannel->seek(pos);
83 }
84
fakeDisconnect(const QString & message)85 void FakeSocket::fakeDisconnect(const QString &message)
86 {
87 readChannel->write(QString::fromUtf8("[*** disconnected: %1 ***]").arg(message).toUtf8());
88 emit disconnected(message);
89 }
90
canReadLine()91 bool FakeSocket::canReadLine()
92 {
93 return readChannel->canReadLine();
94 }
95
read(qint64 maxSize)96 QByteArray FakeSocket::read(qint64 maxSize)
97 {
98 return readChannel->read(maxSize);
99 }
100
readLine(qint64 maxSize)101 QByteArray FakeSocket::readLine(qint64 maxSize)
102 {
103 return readChannel->readLine(maxSize);
104 }
105
write(const QByteArray & byteArray)106 qint64 FakeSocket::write(const QByteArray &byteArray)
107 {
108 return writeChannel->write(byteArray);
109 }
110
startTls()111 void FakeSocket::startTls()
112 {
113 // fake it
114 writeChannel->write(QByteArray("[*** STARTTLS ***]"));
115 QTimer::singleShot(0, this, SLOT(slotEmitEncrypted()));
116 }
117
startDeflate()118 void FakeSocket::startDeflate()
119 {
120 // fake it
121 writeChannel->write(QByteArray("[*** DEFLATE ***]"));
122 }
123
isDead()124 bool FakeSocket::isDead()
125 {
126 // Can't really die (yet)
127 return false;
128 }
129
close()130 void FakeSocket::close()
131 {
132 // fake it
133 writeChannel->write(QByteArray("[*** close ***]"));
134 }
135
writtenStuff()136 QByteArray FakeSocket::writtenStuff()
137 {
138 QByteArray res = w;
139 w.clear();
140 writeChannel->seek(0);
141 return res;
142 }
143
144 }
145