[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