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