24 #include "imapstreamparser.h"
29 using namespace KIMAP;
34 m_isServerModeEnabled = serverModeEnabled;
47 QString result = QString::fromUtf8( tmp );
55 if ( !waitForMoreData( m_data.length() == 0 ) ) {
56 throw ImapParserException(
"Unable to read more data" );
59 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
60 throw ImapParserException(
"Unable to read more data" );
73 return parseQuotedString();
78 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
79 throw ImapParserException(
"Unable to read more data" );
81 int savedPos = m_position;
84 m_position = savedPos;
85 if ( m_data.at( pos ) ==
'{' ) {
88 if ( m_data.at( pos ) ==
'"' ) {
91 if ( m_data.at( pos ) !=
' ' &&
92 m_data.at( pos ) !=
'(' &&
93 m_data.at( pos ) !=
')' &&
94 m_data.at( pos ) !=
'[' &&
95 m_data.at( pos ) !=
']' &&
96 m_data.at( pos ) !=
'\n' &&
97 m_data.at( pos ) !=
'\r' ) {
106 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
107 throw ImapParserException(
"Unable to read more data" );
109 int savedPos = m_position;
110 stripLeadingSpaces();
111 if ( m_data.at( m_position ) ==
'{' ) {
114 end = m_data.indexOf(
'}', m_position );
115 if ( !waitForMoreData( end == -1 ) ) {
116 throw ImapParserException(
"Unable to read more data" );
118 }
while ( end == -1 );
119 Q_ASSERT( end > m_position );
120 m_literalSize = m_data.mid( m_position + 1, end - m_position - 1 ).toInt();
122 m_position = end + 1;
124 if ( m_position < m_data.length() && m_data.at( m_position ) ==
'\r' ) {
127 if ( m_position < m_data.length() && m_data.at( m_position ) ==
'\n' ) {
132 if ( m_isServerModeEnabled && m_literalSize > 0 ) {
133 sendContinuationResponse( m_literalSize );
137 m_position = savedPos;
144 return ( m_literalSize == 0 );
149 static qint64 maxLiteralPartSize = 4096;
150 int size = qMin(maxLiteralPartSize, m_literalSize);
152 if ( !waitForMoreData( m_data.length() < m_position + size ) ) {
153 throw ImapParserException(
"Unable to read more data" );
156 if ( m_data.length() < m_position + size ) {
158 size = m_data.length() - m_position;
161 QByteArray result = m_data.mid( m_position, size );
163 m_literalSize -= size;
164 Q_ASSERT( m_literalSize >= 0 );
172 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
173 throw ImapParserException(
"Unable to read more data" );
175 int savedPos = m_position;
176 stripLeadingSpaces();
177 int pos = m_position;
178 m_position = savedPos;
179 if ( m_data.at( pos ) ==
'(' ) {
187 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
188 throw ImapParserException(
"Unable to read more data" );
190 int savedPos = m_position;
191 stripLeadingSpaces();
192 int pos = m_position;
193 m_position = savedPos;
194 if ( m_data.at( pos ) ==
')' ) {
195 m_position = pos + 1;
203 QList<QByteArray> result;
204 if ( !waitForMoreData( m_data.length() <= m_position ) ) {
205 throw ImapParserException(
"Unable to read more data" );
208 stripLeadingSpaces();
209 if ( m_data.at( m_position ) !=
'(' ) {
213 bool concatToLast =
false;
215 int sublistbegin = m_position;
216 int i = m_position + 1;
218 if ( !waitForMoreData( m_data.length() <= i ) ) {
220 throw ImapParserException(
"Unable to read more data" );
222 if ( m_data.at( i ) ==
'(' ) {
230 if ( m_data.at( i ) ==
')' ) {
236 result.append( m_data.mid( sublistbegin, i - sublistbegin + 1 ) );
242 if ( m_data.at( i ) ==
' ' ) {
246 if ( m_data.at( i ) ==
'"' ) {
254 if ( m_data.at( i ) ==
'[' ) {
256 if ( result.isEmpty() ) {
257 result.append( QByteArray() );
259 result.last() +=
'[';
263 if ( m_data.at( i ) ==
']' ) {
264 concatToLast =
false;
265 result.last() +=
']';
282 while ( ( m_position < m_data.size() ) &&
283 ( m_data.at( m_position ) ==
'\r' || m_data.at( m_position ) ==
'\n' ) ) {
288 if ( concatToLast ) {
297 throw ImapParserException(
"Something went very very wrong!" );
302 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
303 throw ImapParserException(
"Unable to read more data" );
305 int savedPos = m_position;
306 stripLeadingSpaces();
307 int pos = m_position;
308 m_position = savedPos;
309 if ( m_data.at( pos ) ==
'[' ) {
310 m_position = pos + 1;
318 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
319 throw ImapParserException(
"Unable to read more data" );
321 int savedPos = m_position;
322 stripLeadingSpaces();
323 int pos = m_position;
324 m_position = savedPos;
325 if ( m_data.at( pos ) ==
']' ) {
326 m_position = pos + 1;
332 QByteArray ImapStreamParser::parseQuotedString()
335 if ( !waitForMoreData( m_data.length() == 0 ) ) {
336 throw ImapParserException(
"Unable to read more data" );
338 stripLeadingSpaces();
339 int end = m_position;
341 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
342 throw ImapParserException(
"Unable to read more data" );
344 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
345 throw ImapParserException(
"Unable to read more data" );
348 bool foundSlash =
false;
350 if ( m_data.at( m_position ) ==
'"' ) {
354 if ( !waitForMoreData( m_data.length() <= i ) ) {
356 throw ImapParserException(
"Unable to read more data" );
358 if ( m_data.at( i ) ==
'\\' ) {
363 if ( m_data.at( i ) ==
'"' ) {
364 result = m_data.mid( m_position, i - m_position );
374 bool reachedInputEnd =
true;
377 if ( !waitForMoreData( m_data.length() <= i ) ) {
379 throw ImapParserException(
"Unable to read more data" );
381 if ( m_data.at( i ) ==
' ' ||
382 m_data.at( i ) ==
'(' ||
383 m_data.at( i ) ==
')' ||
384 m_data.at( i ) ==
'[' ||
385 m_data.at( i ) ==
']' ||
386 m_data.at( i ) ==
'\n' ||
387 m_data.at( i ) ==
'\r' ||
388 m_data.at( i ) ==
'"' ) {
390 reachedInputEnd =
false;
393 if ( m_data.at( i ) ==
'\\' ) {
398 if ( reachedInputEnd ) {
399 end = m_data.length();
402 result = m_data.mid( m_position, end - m_position );
407 while ( result.contains(
"\\\"" ) ) {
408 result.replace(
"\\\"",
"\"" );
410 while ( result.contains(
"\\\\" ) ) {
411 result.replace(
"\\\\",
"\\" );
424 if ( !waitForMoreData( m_data.length() == 0 ) ) {
425 throw ImapParserException(
"Unable to read more data" );
427 stripLeadingSpaces();
428 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
429 throw ImapParserException(
"Unable to read more data" );
431 if ( m_position >= m_data.length() ) {
432 throw ImapParserException(
"Unable to read more data" );
436 if ( !waitForMoreData( m_data.length() <= i ) ) {
438 throw ImapParserException(
"Unable to read more data" );
440 if ( !isdigit( m_data.at( i ) ) ) {
445 const QByteArray tmp = m_data.mid( m_position, i - m_position );
446 result = tmp.toLongLong( ok );
451 void ImapStreamParser::stripLeadingSpaces()
453 for (
int i = m_position; i < m_data.length(); ++i ) {
454 if ( m_data.at( i ) !=
' ' ) {
459 m_position = m_data.length();
462 bool ImapStreamParser::waitForMoreData(
bool wait )
465 if ( m_socket->bytesAvailable() > 0 ||
466 m_socket->waitForReadyRead( 30000 ) ) {
467 m_data.append( m_socket->readAll() );
475 void ImapStreamParser::setData(
const QByteArray &data )
482 return m_data.mid( m_position );
485 int ImapStreamParser::availableDataSize()
const
487 return m_socket->bytesAvailable() + m_data.size() - m_position;
492 int savedPos = m_position;
494 if ( !waitForMoreData( m_position >= m_data.length() ) ) {
495 throw ImapParserException(
"Unable to read more data" );
497 stripLeadingSpaces();
498 }
while ( m_position >= m_data.size() );
500 if ( m_data.at( m_position ) ==
'\n' || m_data.at( m_position ) ==
'\r' ) {
501 if ( m_data.at( m_position ) ==
'\r' ) {
504 if ( m_position < m_data.length() && m_data.at( m_position ) ==
'\n' ) {
513 m_position = savedPos;
521 int paranthesisBalance = 0;
523 if ( !waitForMoreData( m_data.length() <= i ) ) {
525 throw ImapParserException(
"Unable to read more data" );
527 if ( m_data.at( i ) ==
'{' ) {
530 result.append( m_data.mid( i - 1, m_position - i + 1 ) );
536 if ( m_data.at( i ) ==
'(' ) {
537 paranthesisBalance++;
539 if ( m_data.at( i ) ==
')' ) {
540 paranthesisBalance--;
542 if ( ( i == m_data.length() && paranthesisBalance == 0 ) ||
543 m_data.at( i ) ==
'\n' || m_data.at( i ) ==
'\r') {
546 result.append( m_data.at( i ) );
554 void ImapStreamParser::sendContinuationResponse( qint64 size )
556 QByteArray block =
"+ Ready for literal data (expecting " +
557 QByteArray::number( size ) +
" bytes)\r\n";
558 m_socket->write( block );
559 m_socket->waitForBytesWritten( 30000 );
562 void ImapStreamParser::trimBuffer()
564 if ( m_position < 4096 ) {
567 m_data = m_data.right( m_data.size() - m_position );
QByteArray readUntilCommandEnd()
Return everything that remained from the command.
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.
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 readString()
Same as above, but without decoding it to utf8.
bool atListEnd()
Check if the next data is a parenthesized list end.
QList< QByteArray > readParenthesizedList()
Get he next parenthesized list.
bool atResponseCodeEnd()
Check if the next data is a response code end.
QString readUtf8String()
Get a string from the message.
ImapStreamParser(QIODevice *socket, bool serverModeEnabled=false)
Construct the parser.