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 */
78
79 /**
80 * Same as above, but without decoding it to utf8.
81 * @return the next string from the message
82 */
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 */
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 */
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 */
175
176 /**
177 * Return all the data that was read from the socket, but not processed yet.
178 * @return the remaining unprocessed data
179 */
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}
qint64 readNumber(bool *ok=nullptr)
Get the next data as a number.
ImapStreamParser(QIODevice *socket, bool serverModeEnabled=false)
Construct the parser.
QList< QByteArray > readParenthesizedList()
Get he next parenthesized list.
bool atListEnd()
Check if the next data is a parenthesized list end.
bool hasList()
Check if the next data is a parenthesized list.
bool atResponseCodeEnd()
Check if the next data is a response code end.
bool atCommandEnd()
Check if the command end was reached.
bool atLiteralEnd() const
Check if the literal data end was reached.
QByteArray readRemainingData()
Return all the data that was read from the socket, but not processed yet.
bool hasLiteral()
Check if the next data is a literal data or not.
QByteArray readString()
Same as above, but without decoding it to utf8.
bool hasString()
Check if the next data is a string or not.
QByteArray readUntilCommandEnd()
Return everything that remained from the command.
bool hasResponseCode()
Check if the next data is a response code.
QString readUtf8String()
Get a string from the message.
QByteArray readLiteralPart()
Read the next literal sequence.
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 21 2025 11:48:52 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.