KIMAP

imapstreamparser.h
1/*
2 SPDX-FileCopyrightText: 2006-2007 Volker Krause <vkrause@kde.org>
3 SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#pragma once
9
10#include "kimap_export.h"
11
12#include <exception>
13
14#include <QByteArray>
15#include <QList>
16#include <QString>
17
18class QIODevice;
19
20namespace KIMAP
21{
22class ImapParserException : public std::exception
23{
24public:
25 explicit ImapParserException(const char *what) throw()
26 : mWhat(what)
27 {
28 }
29 explicit ImapParserException(const QByteArray &what) throw()
30 : mWhat(what)
31 {
32 }
33 explicit ImapParserException(const QString &what) throw()
34 : mWhat(what.toUtf8())
35 {
36 }
37 ImapParserException(const ImapParserException &other) throw()
38 : std::exception(other)
39 , mWhat(other.what())
40 {
41 }
42 ~ImapParserException() throw() override
43 {
44 }
45 const char *what() const throw() override
46 {
47 return mWhat.constData();
48 }
49 virtual const char *type() const throw()
50 {
51 return "ImapParserException";
52 }
53
54private:
55 QByteArray mWhat;
56};
57
58/**
59 Parser for IMAP messages that operates on a local socket stream.
60*/
61class KIMAP_EXPORT ImapStreamParser
62{
63public:
64 /**
65 * Construct the parser.
66 * @param socket the local socket to work with.
67 * @param serverModeEnabled true if the parser has to assume we're writing a server (e.g. sends
68 * continuation message automatically)
69 */
70 explicit ImapStreamParser(QIODevice *socket, bool serverModeEnabled = false);
71
72 /**
73 * Get a string from the message. If the upcoming data is not a quoted string, unquoted string or a literal,
74 * the behavior is undefined. Use @ref hasString to be sure a string comes. This call might block.
75 * @return the next string from the message as an utf8 string
76 */
77 QString readUtf8String();
78
79 /**
80 * Same as above, but without decoding it to utf8.
81 * @return the next string from the message
82 */
83 QByteArray readString();
84
85 /**
86 * Get he next parenthesized list. If the upcoming data is not a parenthesized list,
87 * the behavior is undefined. Use @ref hasList to be sure a string comes. This call might block.
88 * @return the next parenthesized list.
89 */
90 QList<QByteArray> readParenthesizedList();
91
92 /**
93 * Get the next data as a number. This call might block.
94 * @param ok true if the data found was a number
95 * @return the number
96 */
97 qint64 readNumber(bool *ok = nullptr);
98
99 /**
100 * Check if the next data is a string or not. This call might block.
101 * @return true if a string follows
102 */
103 bool hasString();
104
105 /**
106 * Check if the next data is a literal data or not. If a literal is found, the
107 * internal position pointer is set to the beginning of the literal data.
108 * This call might block.
109 * @return true if a literal follows
110 */
111 bool hasLiteral();
112
113 /**
114 * Read the next literal sequence. This might or might not be the full data. Example code to read a literal would be:
115 * @code
116 * ImapStreamParser parser;
117 * ...
118 * if (parser.hasLiteral())
119 * {
120 * while (!parser.atLiteralEnd())
121 * {
122 * QByteArray data = parser.readLiteralPart();
123 * // do something with the data
124 * }
125 * }
126 * @endcode
127 *
128 * This call might block.
129 *
130 * @return part of a literal data
131 */
132 QByteArray readLiteralPart();
133
134 /**
135 * Check if the literal data end was reached. See @ref hasLiteral and @ref readLiteralPart .
136 * @return true if the literal was completely read.
137 */
138 bool atLiteralEnd() const;
139
140 /**
141 * Check if the next data is a parenthesized list. This call might block.
142 * @return true if a parenthesized list comes.
143 */
144 bool hasList();
145
146 /**
147 * Check if the next data is a parenthesized list end. This call might block.
148 * @return true if a parenthesized list end.
149 */
150 bool atListEnd();
151
152 /**
153 * Check if the next data is a response code. This call might block.
154 * @return true if a response code comes.
155 */
156 bool hasResponseCode();
157
158 /**
159 * Check if the next data is a response code end. This call might block.
160 * @return true if a response code end.
161 */
162 bool atResponseCodeEnd();
163
164 /**
165 * Check if the command end was reached
166 * @return true if the end of command is reached
167 */
168 bool atCommandEnd();
169
170 /**
171 * Return everything that remained from the command.
172 * @return the remaining command data
173 */
174 QByteArray readUntilCommandEnd();
175
176 /**
177 * Return all the data that was read from the socket, but not processed yet.
178 * @return the remaining unprocessed data
179 */
180 QByteArray readRemainingData();
181
182 int availableDataSize() const;
183
184 void setData(const QByteArray &data);
185
186private:
187 void stripLeadingSpaces();
188 QByteArray parseQuotedString();
189
190 /**
191 * If the condition is true, wait for more data to be available from the socket.
192 * If no data comes after a timeout (30000ms), it aborts and returns false.
193 * @param wait the condition
194 * @return true if more data is available
195 */
196 bool waitForMoreData(bool wait);
197
198 /**
199 * Inform the client to send more literal data.
200 */
201 void sendContinuationResponse(qint64 size);
202
203 /**
204 * Remove already read data from the internal buffer if necessary.
205 */
206 void trimBuffer();
207
208 QIODevice *m_socket = nullptr;
209 bool m_isServerModeEnabled = false;
210 QByteArray m_data;
211 int m_position = -1;
212 qint64 m_literalSize = -1;
213};
214
215}
Parser for IMAP messages that operates on a local socket stream.
const char * constData() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:52:37 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.