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

List:       kde-commits
Subject:    kdesupport/akonadi/server/src/handler
From:       Andras Mantia <amantia () kde ! org>
Date:       2009-03-12 15:13:23
Message-ID: 1236870803.096012.24583.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 938638 by amantia:

Port fetch to imapstreamparser

 M  +219 -0    fetch.cpp  
 M  +3 -0      fetch.h  


--- trunk/kdesupport/akonadi/server/src/handler/fetch.cpp #938637:938638
@@ -30,7 +30,9 @@
 #include "storage/itemretrievalmanager.h"
 #include "storage/parthelper.h"
 #include "akdebug.h"
+#include "imapstreamparser.h"
 
+
 #include <QtCore/QStringList>
 #include <QtCore/QUuid>
 #include <QtCore/QVariant>
@@ -415,3 +417,220 @@
   // rewind item query
   mItemQuery.query().first();
 }
+
+bool Fetch::supportsStreamParser()
+{
+  return true; //partial data parsing makes sense only for external payload files
+}
+
+bool Fetch::parseStream()
+{
+  qDebug() << "Fetch::parseStream";
+  parseCommandStream();
+
+  triggerOnDemandFetch();
+
+  buildItemQuery();
+
+  // build flag query if needed
+  QueryBuilder flagQuery;
+  if ( mRequestedParts.contains( "FLAGS" ) ) {
+    flagQuery.addTable( PimItem::tableName() );
+    flagQuery.addTable( PimItemFlagRelation::tableName() );
+    flagQuery.addTable( Flag::tableName() );
+    flagQuery.addColumn( PimItem::idFullColumnName() );
+    flagQuery.addColumn( Flag::nameFullColumnName() );
+    flagQuery.addColumnCondition( PimItem::idFullColumnName(), Query::Equals, \
PimItemFlagRelation::leftFullColumnName() ); +    flagQuery.addColumnCondition( \
Flag::idFullColumnName(), Query::Equals, PimItemFlagRelation::rightFullColumnName() \
); +    ItemQueryHelper::itemSetToQuery( mSet, mIsUidFetch, connection(), flagQuery \
); +    flagQuery.addSortColumn( PimItem::idFullColumnName(), Query::Ascending );
+
+    if ( !flagQuery.exec() )
+      return failureResponse( "Unable to retrieve item flags" );
+    flagQuery.query().next();
+  }
+  const int flagQueryIdColumn = 0;
+  const int flagQueryNameColumn = 1;
+
+  // retrieve missing parts
+  QStringList partList, payloadList;
+  foreach( const QByteArray &b, mRequestedParts ) {
+    // filter out non-part attributes
+    if ( b == "REV" || b == "FLAGS" || b == "UID" || b == "REMOTEID" )
+      continue;
+    if ( b == "SIZE" ) {
+      mSizeRequested = true;
+      continue;
+    }
+    if ( b == "DATETIME" ) {
+      mMTimeRequested = true;
+      continue;
+    }
+    partList << QString::fromLatin1( b );
+    if ( b.startsWith( "PLD:" ) )
+      payloadList << QString::fromLatin1( b );
+  }
+  retrieveMissingPayloads( payloadList );
+
+  // build part query if needed
+  QueryBuilder partQuery;
+  if ( !partList.isEmpty() || mFullPayload || mAllAttrs ) {
+    partQuery = buildPartQuery( partList, mFullPayload, mAllAttrs );
+    if ( !partQuery.exec() )
+      return failureResponse( "Unable to retrieve item parts" );
+    partQuery.query().next();
+  }
+
+  // build responses
+  Response response;
+  response.setUntagged();
+  while ( mItemQuery.query().isValid() ) {
+    const qint64 pimItemId = mItemQuery.query().value( itemQueryIdColumn \
).toLongLong(); +    const int pimItemRev = mItemQuery.query().value( \
itemQueryRevColumn ).toInt(); +
+    QList<QByteArray> attributes;
+    attributes.append( "UID " + QByteArray::number( pimItemId ) );
+    attributes.append( "REV " + QByteArray::number( pimItemRev ) );
+    attributes.append( "REMOTEID " + ImapParser::quote( mItemQuery.query().value( \
itemQueryRidColumn ).toString().toUtf8() ) ); +    attributes.append( "MIMETYPE " + \
ImapParser::quote( mItemQuery.query().value( itemQueryMimeTypeColumn \
).toString().toUtf8() ) ); +
+    if ( mSizeRequested ) {
+      const qint64 pimItemSize = mItemQuery.query().value( itemQuerySizeColumn \
).toLongLong(); +      attributes.append( "SIZE " + QByteArray::number( pimItemSize ) \
); +    }
+    if ( mMTimeRequested ) {
+      const QDateTime pimItemDatetime = mItemQuery.query().value( \
itemQueryDatetimeColumn ).toDateTime(); +      // Date time is always stored in UTC \
time zone by the server. +      QString datetime = QLocale::c().toString( \
pimItemDatetime, QLatin1String( "dd-MMM-yyyy hh:mm:ss +0000" ) ); +      \
attributes.append( "DATETIME " + ImapParser::quote( datetime.toUtf8() ) ); +    }
+
+    if ( mRequestedParts.contains( "FLAGS" ) ) {
+      QList<QByteArray> flags;
+      while ( flagQuery.query().isValid() ) {
+        const qint64 id = flagQuery.query().value( flagQueryIdColumn ).toLongLong();
+        if ( id < pimItemId ) {
+          flagQuery.query().next();
+          continue;
+        } else if ( id > pimItemId ) {
+          break;
+        }
+        flags << flagQuery.query().value( flagQueryNameColumn ).toString().toUtf8();
+        flagQuery.query().next();
+      }
+      attributes.append( "FLAGS (" + ImapParser::join( flags, " " ) + ')' );
+    }
+
+    while ( partQuery.query().isValid() ) {
+      const qint64 id = partQuery.query().value( partQueryIdColumn ).toLongLong();
+      if ( id < pimItemId ) {
+        partQuery.query().next();
+        continue;
+      } else if ( id > pimItemId ) {
+        break;
+      }
+      QByteArray partName = partQuery.query().value( partQueryNameColumn \
).toString().toUtf8(); +      QByteArray part = partQuery.query().value( \
partQueryNameColumn ).toString().toUtf8(); +      QByteArray data = \
partQuery.query().value( partQueryDataColumn ).toByteArray(); +      bool \
partIsExternal = partQuery.query().value( partQueryExternalColumn ).toBool(); +      \
if ( !mExternalPayloadSupported && partIsExternal ) //external payload not supported \
by the client, translate the data +        data = PartHelper::translateData(id, data, \
partIsExternal ); +      int version = partQuery.query().value( \
partQueryVersionColumn ).toInt(); +      if ( version != 0 ) { // '0' is the default, \
so don't send it +        part += "[" + QByteArray::number( version ) + "]";
+      }
+      if (  mExternalPayloadSupported && partIsExternal ) { // external data and \
this is supported by the client +        part += " [FILE] ";
+      }
+      if ( data.isNull() ) {
+        part += " NIL";
+      } else if ( data.isEmpty() ) {
+        part += " \"\"";
+      } else {
+        part += " {" + QByteArray::number( data.length() ) + "}\n";
+        part += data;
+      }
+
+      if ( mRequestedParts.contains( partName ) || mFullPayload || mAllAttrs )
+        attributes << part;
+
+      partQuery.query().next();
+    }
+
+    // IMAP protocol violation: should actually be the sequence number
+    QByteArray attr = QByteArray::number( pimItemId ) + " FETCH (";
+    attr += ImapParser::join( attributes, " " ) + ')';
+    response.setUntagged();
+    response.setString( attr );
+    emit responseAvailable( response );
+
+    mItemQuery.query().next();
+  }
+
+  // update atime
+  updateItemAccessTime();
+
+  if ( mIsUidFetch )
+    successResponse( "UID FETCH completed" );
+  else
+    successResponse( "FETCH completed" );
+  deleteLater();
+  return true;
+}
+
+void Fetch::parseCommandStream()
+{
+  // command
+  QByteArray buffer = m_streamParser->readString();
+  if ( buffer == AKONADI_CMD_UID ) {
+    mIsUidFetch = true;
+    buffer = m_streamParser->readString();
+  } else
+  if ( buffer != "FETCH" ) {
+    //put back what was read
+    m_streamParser->insertData(' ' + buffer + ' ');
+  }
+
+
+  // sequence set
+  mSet = m_streamParser->readSequenceSet();
+  if ( mSet.isEmpty() )
+    throw HandlerException( "No items selected" );
+
+  // macro vs. attribute list
+  forever {
+    if ( m_streamParser->atCommandEnd() )
+      break;
+    if ( m_streamParser->hasList() ) {
+      QList<QByteArray> tmp =m_streamParser->readParenthesizedList();
+      mRequestedParts += tmp;
+      break;
+    } else {
+      buffer = m_streamParser->readString();
+      if ( buffer == AKONADI_PARAM_CACHEONLY ) {
+        mCacheOnly = true;
+      } else if ( buffer == AKONADI_PARAM_ALLATTRIBUTES ) {
+        mAllAttrs = true;
+      } else if ( buffer == AKONADI_PARAM_EXTERNALPAYLOAD ) {
+        mExternalPayloadSupported = true;
+      }else if ( buffer == AKONADI_PARAM_FULLPAYLOAD ) {
+        mRequestedParts << "PLD:RFC822"; // HACK: temporary workaround until we have \
support for detecting the availability of the full payload in the server +        \
mFullPayload = true; +      }
+#if 0
+      // IMAP compat stuff
+      else if ( buffer == "ALL" ) {
+                              mRequestedParts << "FLAGS" << "INTERNALDATE" << \
"RFC822.SIZE" << "ENVELOPE"; +    } else if ( buffer == "FULL" ) {
+                              mRequestedParts << "FLAGS" << "INTERNALDATE" << \
"RFC822.SIZE"; +    } else if ( buffer == "FAST" ) {
+                              mRequestedParts << "FLAGS" << "INTERNALDATE" << \
"RFC822.SIZE" << "ENVELOPE" << "BODY"; +    }
+#endif
+                              else {
+                            throw HandlerException( "Invalid command argument" );
+                              }
+    }
+  }
+}
+
--- trunk/kdesupport/akonadi/server/src/handler/fetch.h #938637:938638
@@ -44,6 +44,8 @@
     ~Fetch();
 
     bool handleLine(const QByteArray& line);
+    bool supportsStreamParser();
+    bool parseStream();
 
   private:
     void parseCommand( const QByteArray &line );
@@ -52,6 +54,7 @@
     void buildItemQuery();
     QueryBuilder buildPartQuery( const QStringList &partList, bool allPayload, bool \
allAttrs );  void retrieveMissingPayloads( const QStringList &payloadList );
+    void parseCommandStream();
 
   private:
     QueryBuilder mItemQuery;


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

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