24 #include "imapstreamparser.h"
29 using namespace KIMAP;
34 m_isServerModeEnabled = serverModeEnabled;
54 if ( !waitForMoreData( m_data.
length() == 0 ) ) {
55 throw ImapParserException(
"Unable to read more data" );
58 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
59 throw ImapParserException(
"Unable to read more data" );
72 return parseQuotedString();
77 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
78 throw ImapParserException(
"Unable to read more data" );
80 int savedPos = m_position;
83 m_position = savedPos;
84 if ( m_data.
at( pos ) ==
'{' ) {
87 if ( m_data.
at( pos ) ==
'"' ) {
90 if ( m_data.
at( pos ) !=
' ' &&
91 m_data.
at( pos ) !=
'(' &&
92 m_data.
at( pos ) !=
')' &&
93 m_data.
at( pos ) !=
'[' &&
94 m_data.
at( pos ) !=
']' &&
95 m_data.
at( pos ) !=
'\n' &&
96 m_data.
at( pos ) !=
'\r' ) {
105 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
106 throw ImapParserException(
"Unable to read more data" );
108 int savedPos = m_position;
109 stripLeadingSpaces();
110 if ( m_data.
at( m_position ) ==
'{' ) {
113 end = m_data.
indexOf(
'}', m_position );
114 if ( !waitForMoreData( end == -1 ) ) {
115 throw ImapParserException(
"Unable to read more data" );
117 }
while ( end == -1 );
118 Q_ASSERT( end > m_position );
119 m_literalSize = m_data.
mid( m_position + 1, end - m_position - 1 ).
toInt();
121 m_position = end + 1;
123 if ( !waitForMoreData( m_position + 1 >= m_data.
length() ) ) {
124 throw ImapParserException(
"Unable to read more data" );
126 if ( m_position < m_data.
length() && m_data.
at( m_position ) ==
'\r' ) {
129 if ( m_position < m_data.
length() && m_data.
at( m_position ) ==
'\n' ) {
134 if ( m_isServerModeEnabled && m_literalSize > 0 ) {
135 sendContinuationResponse( m_literalSize );
139 m_position = savedPos;
146 return ( m_literalSize == 0 );
151 static qint64 maxLiteralPartSize = 4096;
152 int size = qMin(maxLiteralPartSize, m_literalSize);
154 if ( !waitForMoreData( m_data.
length() < m_position + size ) ) {
155 throw ImapParserException(
"Unable to read more data" );
158 if ( m_data.
length() < m_position + size ) {
160 size = m_data.
length() - m_position;
165 m_literalSize -= size;
166 Q_ASSERT( m_literalSize >= 0 );
174 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
175 throw ImapParserException(
"Unable to read more data" );
177 int savedPos = m_position;
178 stripLeadingSpaces();
179 int pos = m_position;
180 m_position = savedPos;
181 if ( m_data.
at( pos ) ==
'(' ) {
189 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
190 throw ImapParserException(
"Unable to read more data" );
192 int savedPos = m_position;
193 stripLeadingSpaces();
194 int pos = m_position;
195 m_position = savedPos;
196 if ( m_data.
at( pos ) ==
')' ) {
197 m_position = pos + 1;
206 if ( !waitForMoreData( m_data.
length() <= m_position ) ) {
207 throw ImapParserException(
"Unable to read more data" );
210 stripLeadingSpaces();
211 if ( m_data.
at( m_position ) !=
'(' ) {
215 bool concatToLast =
false;
217 int sublistbegin = m_position;
218 int i = m_position + 1;
220 if ( !waitForMoreData( m_data.
length() <= i ) ) {
222 throw ImapParserException(
"Unable to read more data" );
224 if ( m_data.
at( i ) ==
'(' ) {
232 if ( m_data.
at( i ) ==
')' ) {
238 result.
append( m_data.
mid( sublistbegin, i - sublistbegin + 1 ) );
244 if ( m_data.
at( i ) ==
' ' ) {
248 if ( m_data.
at( i ) ==
'"' ) {
256 if ( m_data.
at( i ) ==
'[' ) {
261 result.
last() +=
'[';
265 if ( m_data.
at( i ) ==
']' ) {
266 concatToLast =
false;
267 result.
last() +=
']';
284 while ( ( m_position < m_data.
size() ) &&
285 ( m_data.
at( m_position ) ==
'\r' || m_data.
at( m_position ) ==
'\n' ) ) {
290 if ( concatToLast ) {
299 throw ImapParserException(
"Something went very very wrong!" );
304 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
305 throw ImapParserException(
"Unable to read more data" );
307 int savedPos = m_position;
308 stripLeadingSpaces();
309 int pos = m_position;
310 m_position = savedPos;
311 if ( m_data.
at( pos ) ==
'[' ) {
312 m_position = pos + 1;
320 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
321 throw ImapParserException(
"Unable to read more data" );
323 int savedPos = m_position;
324 stripLeadingSpaces();
325 int pos = m_position;
326 m_position = savedPos;
327 if ( m_data.
at( pos ) ==
']' ) {
328 m_position = pos + 1;
334 QByteArray ImapStreamParser::parseQuotedString()
337 if ( !waitForMoreData( m_data.
length() == 0 ) ) {
338 throw ImapParserException(
"Unable to read more data" );
340 stripLeadingSpaces();
341 int end = m_position;
343 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
344 throw ImapParserException(
"Unable to read more data" );
346 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
347 throw ImapParserException(
"Unable to read more data" );
350 bool foundSlash =
false;
352 if ( m_data.
at( m_position ) ==
'"' ) {
356 if ( !waitForMoreData( m_data.
length() <= i ) ) {
358 throw ImapParserException(
"Unable to read more data" );
360 if ( m_data.
at( i ) ==
'\\' ) {
365 if ( m_data.
at( i ) ==
'"' ) {
366 result = m_data.
mid( m_position, i - m_position );
376 bool reachedInputEnd =
true;
379 if ( !waitForMoreData( m_data.
length() <= i ) ) {
381 throw ImapParserException(
"Unable to read more data" );
383 if ( m_data.
at( i ) ==
' ' ||
384 m_data.
at( i ) ==
'(' ||
385 m_data.
at( i ) ==
')' ||
386 m_data.
at( i ) ==
'[' ||
387 m_data.
at( i ) ==
']' ||
388 m_data.
at( i ) ==
'\n' ||
389 m_data.
at( i ) ==
'\r' ||
390 m_data.
at( i ) ==
'"' ) {
392 reachedInputEnd =
false;
395 if ( m_data.
at( i ) ==
'\\' ) {
400 if ( reachedInputEnd ) {
404 result = m_data.
mid( m_position, end - m_position );
409 while ( result.
contains(
"\\\"" ) ) {
410 result.
replace(
"\\\"",
"\"" );
412 while ( result.
contains(
"\\\\" ) ) {
413 result.
replace(
"\\\\",
"\\" );
426 if ( !waitForMoreData( m_data.
length() == 0 ) ) {
427 throw ImapParserException(
"Unable to read more data" );
429 stripLeadingSpaces();
430 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
431 throw ImapParserException(
"Unable to read more data" );
433 if ( m_position >= m_data.
length() ) {
434 throw ImapParserException(
"Unable to read more data" );
438 if ( !waitForMoreData( m_data.
length() <= i ) ) {
440 throw ImapParserException(
"Unable to read more data" );
442 if ( !isdigit( m_data.
at( i ) ) ) {
447 const QByteArray tmp = m_data.
mid( m_position, i - m_position );
453 void ImapStreamParser::stripLeadingSpaces()
455 for (
int i = m_position; i < m_data.
length(); ++i ) {
456 if ( m_data.
at( i ) !=
' ' ) {
461 m_position = m_data.
length();
464 bool ImapStreamParser::waitForMoreData(
bool wait )
477 void ImapStreamParser::setData(
const QByteArray &data )
484 return m_data.
mid( m_position );
487 int ImapStreamParser::availableDataSize()
const
494 int savedPos = m_position;
496 if ( !waitForMoreData( m_position >= m_data.
length() ) ) {
497 throw ImapParserException(
"Unable to read more data" );
499 stripLeadingSpaces();
500 }
while ( m_position >= m_data.
size() );
502 if ( m_data.
at( m_position ) ==
'\n' || m_data.
at( m_position ) ==
'\r' ) {
503 if ( m_data.
at( m_position ) ==
'\r' ) {
506 if ( m_position < m_data.
length() && m_data.
at( m_position ) ==
'\n' ) {
515 m_position = savedPos;
523 int paranthesisBalance = 0;
525 if ( !waitForMoreData( m_data.
length() <= i ) ) {
527 throw ImapParserException(
"Unable to read more data" );
529 if ( m_data.
at( i ) ==
'{' ) {
532 result.
append( m_data.
mid( i - 1, m_position - i + 1 ) );
538 if ( m_data.
at( i ) ==
'(' ) {
539 paranthesisBalance++;
541 if ( m_data.
at( i ) ==
')' ) {
542 paranthesisBalance--;
544 if ( ( i == m_data.
length() && paranthesisBalance == 0 ) ||
545 m_data.
at( i ) ==
'\n' || m_data.
at( i ) ==
'\r') {
556 void ImapStreamParser::sendContinuationResponse( qint64 size )
558 QByteArray block =
"+ Ready for literal data (expecting " +
560 m_socket->
write( block );
564 void ImapStreamParser::trimBuffer()
566 if ( m_position < 4096 ) {
569 m_data = m_data.
right( m_data.
size() - m_position );
QByteArray readUntilCommandEnd()
Return everything that remained from the command.
int toInt(bool *ok, int base) const
qint64 readNumber(bool *ok=0)
Get the next data as a number.
QByteArray readLiteralPart()
Read the next literal sequence.
bool atLiteralEnd() const
Check if the literal data end was reached.
bool hasList()
Check if the next data is a parenthesized list.
bool hasString()
Check if the next data is a string or not.
bool atCommandEnd()
Check if the command end was reached.
int indexOf(char ch, int from) const
virtual bool waitForBytesWritten(int msecs)
void append(const T &value)
QString fromUtf8(const char *str, int size)
QByteArray readRemainingData()
Return all the data that was read from the socket, but not processed yet.
bool hasResponseCode()
Check if the next data is a response code.
~ImapStreamParser()
Destructor.
bool hasLiteral()
Check if the next data is a literal data or not.
QByteArray number(int n, int base)
QByteArray right(int len) const
QByteArray & replace(int pos, int len, const char *after)
virtual bool waitForReadyRead(int msecs)
QByteArray readString()
Same as above, but without decoding it to utf8.
QByteArray mid(int pos, int len) const
virtual qint64 bytesAvailable() const
QByteArray & append(char ch)
bool atListEnd()
Check if the next data is a parenthesized list end.
qlonglong toLongLong(bool *ok, int base) const
QList< QByteArray > readParenthesizedList()
Get he next parenthesized list.
bool contains(char ch) const
bool atResponseCodeEnd()
Check if the next data is a response code end.
qint64 write(const char *data, qint64 maxSize)
QString readUtf8String()
Get a string from the message.
ImapStreamParser(QIODevice *socket, bool serverModeEnabled=false)
Construct the parser.