[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    kdesupport/akonadi/server
From:       Volker Krause <vkrause () kde ! org>
Date:       2010-03-22 12:42:43
Message-ID: 20100322124243.41251AC871 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1106277 by vkrause:

When a command execution was aborted, only read the remaining data that
already has been sent, don't ask for more, there is likely noone around
to provide that anymore on the client side. This fixes the parser getting
stuck on an early aborted APPEND/STORE commands.


 M  +5 -5      src/akonadiconnection.cpp  
 M  +20 -0     src/imapstreamparser.cpp  
 M  +10 -1     src/imapstreamparser.h  
 M  +20 -0     tests/unittest/imapstreamparsertest.cpp  
 M  +1 -0      tests/unittest/imapstreamparsertest.h  


--- trunk/kdesupport/akonadi/server/src/akonadiconnection.cpp #1106276:1106277
@@ -113,7 +113,7 @@
   // On Windows, calling readLiteralPart() triggers the readyRead() signal \
recursively and leads to parse errors  if ( m_currentHandler )
     return;
-    
+
   while ( m_socket->bytesAvailable() > 0 || \
!m_streamParser->readRemainingData().isEmpty() ) {  try {
       const QByteArray tag = m_streamParser->readString();
@@ -132,12 +132,12 @@
       m_currentHandler->setTag( tag );
       m_currentHandler->setStreamParser( m_streamParser );
       if ( !m_currentHandler->parseStream() ) {
-        m_streamParser->readUntilCommandEnd(); //just eat the ending newline
+        m_streamParser->skipCurrentCommand();
       }
     } catch ( const Akonadi::HandlerException &e ) {
       m_currentHandler->failureResponse( e.what() );
       try {
-        m_streamParser->readUntilCommandEnd(); //just eat the ending newline
+        m_streamParser->skipCurrentCommand();
       } catch ( ... ) {}
     } catch ( const Akonadi::Exception &e ) {
       if ( m_currentHandler ) {
@@ -145,7 +145,7 @@
           + QLatin1String( ": " ) + QString::fromLatin1( e.what()  ) );
       }
       try {
-        m_streamParser->readUntilCommandEnd(); //just eat the ending newline
+        m_streamParser->skipCurrentCommand();
       } catch ( ... ) {}
     } catch ( ... ) {
       akError() << "Unknown exception caught: " << akBacktrace();
@@ -153,7 +153,7 @@
         m_currentHandler->failureResponse( "Unknown exception caught" );
       }
       try {
-        m_streamParser->readUntilCommandEnd(); //just eat the ending newline
+        m_streamParser->skipCurrentCommand();
       } catch ( ... ) {}
     }
     delete m_currentHandler;
--- trunk/kdesupport/akonadi/server/src/imapstreamparser.cpp #1106276:1106277
@@ -745,6 +745,26 @@
   return result;
 }
 
+void ImapStreamParser::skipCurrentCommand()
+{
+  int i = m_position;
+  Q_FOREVER {
+    if ( !waitForMoreData( m_data.length() <= i ) ) {
+      m_position = i;
+      throw ImapParserException("Unable to read more data");
+    }
+    if ( m_data[i] == '\n'  || m_data[i] == '\r' )
+      break; //command end
+    ++i;
+  }
+  m_position = i + 1;
+  // We'd better empty m_data from time to time before it grows out of control
+  if ( !m_peeking ) {
+    m_data = m_data.right(m_data.size()-m_position);
+    m_position = 0;
+  }
+}
+
 void ImapStreamParser::sendContinuationResponse()
 {
   QByteArray block = "+ Ready for literal data (expecting "
--- trunk/kdesupport/akonadi/server/src/imapstreamparser.h #1106276:1106277
@@ -202,12 +202,21 @@
     bool atCommandEnd();
 
     /**
-     * Return everything that remained from the command.
+     * Return everything that remained from the command, <em>including not yet
+     * requested</em> literal parts.
      * @return the remaining command data
+     * @see skipCurrentCommand
      */
     QByteArray readUntilCommandEnd();
 
     /**
+     * This reads until the end of the <em>already sent</em> command and does not
+     * request not yet sent literal parts.
+     * @see readUntilCommandEnd
+     */
+    void skipCurrentCommand();
+
+    /**
      * Return all the data that was read from the socket, but not processed yet.
      * @return the remaining unprocessed data
      */
--- trunk/kdesupport/akonadi/server/tests/unittest/imapstreamparsertest.cpp \
#1106276:1106277 @@ -435,5 +435,25 @@
   }
 }
 
+void ImapStreamParserTest::testAbortCommand()
+{
+  QByteArray input( "12 UID STORE 63696 REV 2 (REMOTEID.SILENT \"225\" \
REMOTEREVISION.SILENT "" FLAGS.SILENT (\\SEEN ) PLD:HEAD.SILENT {2226}\nNEXTCOMMAND " \
); +  QBuffer buffer( &input, this );
+  buffer.open( QIODevice::ReadOnly );
+  ImapStreamParser parser( &buffer );
 
+  try {
+    // read some stuff and then notice that we can't process the command and abort \
early +    QCOMPARE( parser.readString(), QByteArray( "12" ) );
+    QCOMPARE( parser.readString(), QByteArray( "UID" ) );
+    QCOMPARE( parser.readString(), QByteArray( "STORE" ) );
+    qDebug() << "!!!";
+    parser.skipCurrentCommand();
+    QCOMPARE( parser.readString(), QByteArray( "NEXTCOMMAND" ) );
+  } catch ( const Akonadi::Exception &e ) {
+    qDebug() << e.type() << e.what();
+    QFAIL( "Exception caught" );
+  }  
+}
+
 #include "imapstreamparsertest.moc"
--- trunk/kdesupport/akonadi/server/tests/unittest/imapstreamparsertest.h \
#1106276:1106277 @@ -39,6 +39,7 @@
     void testParseDateTime();
     void testReadUntilCommandEnd();
     void testReadUntilCommandEnd2();
+    void testAbortCommand();
 
 };
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic