24 #include "imapstreamparser.h"
29 using namespace KIMAP;
34 m_isServerModeEnabled = serverModeEnabled;
47 QString result = QString::fromUtf8( tmp );
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;
163 QByteArray result = m_data.mid( m_position, size );
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;
205 QList<QByteArray> result;
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 ) ==
'[' ) {
258 if ( result.isEmpty() ) {
259 result.append( QByteArray() );
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 ) {
401 end = m_data.length();
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 );
448 result = tmp.toLongLong( ok );
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 )
467 if ( m_socket->bytesAvailable() > 0 ||
468 m_socket->waitForReadyRead( 30000 ) ) {
469 m_data.append( m_socket->readAll() );
477 void ImapStreamParser::setData(
const QByteArray &data )
484 return m_data.mid( m_position );
487 int ImapStreamParser::availableDataSize()
const
489 return m_socket->bytesAvailable() + m_data.size() - m_position;
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') {
548 result.append( m_data.at( i ) );
556 void ImapStreamParser::sendContinuationResponse( qint64 size )
558 QByteArray block =
"+ Ready for literal data (expecting " +
559 QByteArray::number( size ) +
" bytes)\r\n";
560 m_socket->write( block );
561 m_socket->waitForBytesWritten( 30000 );
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.
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.