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 );