diff --git a/akonadi/itemfetchjob.cpp b/akonadi/itemfetchjob.cpp index c690fd19f..b01476aba 100644 --- a/akonadi/itemfetchjob.cpp +++ b/akonadi/itemfetchjob.cpp @@ -1,280 +1,279 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "itemfetchjob.h" #include "attributefactory.h" #include "collection.h" #include "collectionselectjob.h" #include "imapparser_p.h" #include "itemfetchscope.h" #include "itemserializer.h" #include "itemserializerplugin.h" #include "job_p.h" #include "entity_p.h" #include "protocol_p.h" #include "protocolhelper.h" #include #include #include #include using namespace Akonadi; class Akonadi::ItemFetchJobPrivate : public JobPrivate { public: ItemFetchJobPrivate( ItemFetchJob *parent ) : JobPrivate( parent ) { } void timeout() { Q_Q( ItemFetchJob ); mEmitTimer->stop(); // in case we are called by result() if ( !mPendingItems.isEmpty() ) { emit q->itemsReceived( mPendingItems ); mPendingItems.clear(); } } void startFetchJob(); void selectDone( KJob * job ); Q_DECLARE_PUBLIC( ItemFetchJob ) Collection mCollection; Item mItem; Item::List mItems; ItemFetchScope mFetchScope; Item::List mPendingItems; // items pending for emitting itemsReceived() QTimer* mEmitTimer; }; void ItemFetchJobPrivate::startFetchJob() { QByteArray command = newTag(); if ( !mItem.isValid() ) command += " " AKONADI_CMD_ITEMFETCH " 1:*"; else command += " " AKONADI_CMD_UID " " AKONADI_CMD_ITEMFETCH " " + QByteArray::number( mItem.id() ); if ( mFetchScope.fullPayload() ) command += " " AKONADI_PARAM_FULLPAYLOAD; if ( mFetchScope.allAttributes() ) command += " " AKONADI_PARAM_ALLATTRIBUTES; if ( mFetchScope.cacheOnly() ) command += " " AKONADI_PARAM_CACHEONLY; - command += " (UID REMOTEID FLAGS"; + command += " (UID REMOTEID FLAGS SIZE DATETIME"; foreach ( const QByteArray &part, mFetchScope.payloadParts() ) command += ' ' + ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartPayload, part ); foreach ( const QByteArray &part, mFetchScope.attributes() ) command += ' ' + ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, part ); command += ")\n"; writeData( command ); } void ItemFetchJobPrivate::selectDone( KJob * job ) { if ( !job->error() ) // the collection is now selected, fetch the message(s) startFetchJob(); } ItemFetchJob::ItemFetchJob( const Collection &collection, QObject * parent ) : Job( new ItemFetchJobPrivate( this ), parent ) { Q_D( ItemFetchJob ); d->mEmitTimer = new QTimer( this ); d->mEmitTimer->setSingleShot( true ); d->mEmitTimer->setInterval( 100 ); connect( d->mEmitTimer, SIGNAL(timeout()), this, SLOT(timeout()) ); connect( this, SIGNAL(result(KJob*)), this, SLOT(timeout()) ); d->mCollection = collection; } ItemFetchJob::ItemFetchJob( const Item & item, QObject * parent) : Job( new ItemFetchJobPrivate( this ), parent ) { Q_D( ItemFetchJob ); d->mEmitTimer = new QTimer( this ); d->mEmitTimer->setSingleShot( true ); d->mEmitTimer->setInterval( 100 ); connect( d->mEmitTimer, SIGNAL(timeout()), this, SLOT(timeout()) ); connect( this, SIGNAL(result(KJob*)), this, SLOT(timeout()) ); d->mCollection = Collection::root(); d->mItem = item; } ItemFetchJob::~ItemFetchJob() { } void ItemFetchJob::doStart() { Q_D( ItemFetchJob ); if ( !d->mItem.isValid() ) { // collection content listing if ( d->mCollection == Collection::root() ) { setErrorText( QLatin1String("Cannot list root collection.") ); setError( Unknown ); emitResult(); } CollectionSelectJob *job = new CollectionSelectJob( d->mCollection, this ); connect( job, SIGNAL(result(KJob*)), SLOT(selectDone(KJob*)) ); addSubjob( job ); } else d->startFetchJob(); } void ItemFetchJob::doHandleResponse( const QByteArray & tag, const QByteArray & data ) { Q_D( ItemFetchJob ); if ( tag == "*" ) { int begin = data.indexOf( "FETCH" ); if ( begin >= 0 ) { // split fetch response into key/value pairs QList fetchResponse; ImapParser::parseParenthesizedList( data, fetchResponse, begin + 6 ); // create a new item object Item::Id uid = -1; int rev = -1; - qint64 size = 0; - QDateTime datetime; QString rid; QString mimeType; for ( int i = 0; i < fetchResponse.count() - 1; i += 2 ) { const QByteArray key = fetchResponse.value( i ); const QByteArray value = fetchResponse.value( i + 1 ); if ( key == "UID" ) uid = value.toLongLong(); else if ( key == "REV" ) rev = value.toInt(); - else if ( key == "SIZE" ) - size = value.toLongLong(); - else if ( key == "DATETIME" ) - ImapParser::parseDateTime( value, datetime ); else if ( key == "REMOTEID" ) rid = QString::fromUtf8( value ); else if ( key == "MIMETYPE" ) mimeType = QString::fromLatin1( value ); } - if ( uid < 0 || rev < 0 || size < 0 || datetime.isNull() || mimeType.isEmpty() ) { - kWarning( 5250 ) << "Broken fetch response: UID, RID, REV, SIZE, DATETIME or MIMETYPE missing!"; + if ( uid < 0 || rev < 0 || mimeType.isEmpty() ) { + kWarning( 5250 ) << "Broken fetch response: UID, RID, REV or MIMETYPE missing!"; return; } Item item( uid ); item.setRemoteId( rid ); item.setRevision( rev ); - item.setSize( size ); - item.setModificationTime( datetime ); item.setMimeType( mimeType ); if ( !item.isValid() ) return; // parse fetch response fields for ( int i = 0; i < fetchResponse.count() - 1; i += 2 ) { const QByteArray key = fetchResponse.value( i ); // skip stuff we dealt with already - if ( key == "UID" || key == "REV" || key == "SIZE" || key == "DATETIME" || key == "REMOTEID" || key == "MIMETYPE" ) + if ( key == "UID" || key == "REV" || key == "REMOTEID" || key == "MIMETYPE" ) continue; // flags if ( key == "FLAGS" ) { QList flags; ImapParser::parseParenthesizedList( fetchResponse[i + 1], flags ); foreach ( const QByteArray &flag, flags ) { item.setFlag( flag ); } + } else if ( key == "SIZE" ) { + const quint64 size = fetchResponse[i + 1].toLongLong(); + item.setSize( size ); + } else if ( key == "DATETIME" ) { + QDateTime datetime; + ImapParser::parseDateTime( fetchResponse[i + 1], datetime ); + item.setModificationTime( datetime ); } else { int version = 0; QByteArray plainKey( key ); ProtocolHelper::PartNamespace ns; ImapParser::splitVersionedKey( key, plainKey, version ); plainKey = ProtocolHelper::decodePartIdentifier( plainKey, ns ); switch ( ns ) { case ProtocolHelper::PartPayload: ItemSerializer::deserialize( item, plainKey, fetchResponse.value( i + 1 ), version ); break; case ProtocolHelper::PartAttribute: { Attribute* attr = AttributeFactory::createAttribute( plainKey ); Q_ASSERT( attr ); attr->deserialize( fetchResponse.value( i + 1 ) ); item.addAttribute( attr ); break; } case ProtocolHelper::PartGlobal: default: kWarning() << "Unknown item part type:" << key; } } } item.d_ptr->resetChangeLog(); d->mItems.append( item ); d->mPendingItems.append( item ); if ( !d->mEmitTimer->isActive() ) d->mEmitTimer->start(); return; } } kDebug( 5250 ) << "Unhandled response: " << tag << data; } Item::List ItemFetchJob::items() const { Q_D( const ItemFetchJob ); return d->mItems; } void ItemFetchJob::setFetchScope( ItemFetchScope &fetchScope ) { Q_D( ItemFetchJob ); d->mFetchScope = fetchScope; } ItemFetchScope &ItemFetchJob::fetchScope() { Q_D( ItemFetchJob ); return d->mFetchScope; } #include "itemfetchjob.moc" diff --git a/akonadi/session_p.h b/akonadi/session_p.h index 5b3db0fe6..b9d3e8bbc 100644 --- a/akonadi/session_p.h +++ b/akonadi/session_p.h @@ -1,111 +1,111 @@ /* Copyright (c) 2007 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_SESSION_P_H #define AKONADI_SESSION_P_H #include "session.h" #include "imapparser_p.h" #include #include #include class QLocalSocket; namespace Akonadi { /** * @internal */ class SessionPrivate { public: SessionPrivate( Session *parent ) : mParent( parent ), mConnectionSettings( 0 ), protocolVersion( 0 ) { parser = new ImapParser(); } ~SessionPrivate() { delete parser; delete mConnectionSettings; } void startNext(); void reconnect(); void socketError(); void dataReceived(); void doStartNext(); void startJob( Job* job ); void jobDone( KJob* job ); void jobWriteFinished( Akonadi::Job* job ); bool canPipelineNext(); /** * Creates a new default session for this thread with * the given @p sessionId. The session can be accessed * later by defaultSession(). * * You only need to call this method if you want that the * default session has a special custom id, otherwise a random unique * id is used automatically. */ static void createDefaultSession( const QByteArray &sessionId ); /** Associates the given Job object with this session. */ void addJob( Job* job ); /** Returns the next IMAP tag. */ int nextTag(); /** Sends the given raw data. */ void writeData( const QByteArray &data ); - static int minimumProtocolVersion() { return 5; } + static int minimumProtocolVersion() { return 6; } Session *mParent; QByteArray sessionId; QSettings *mConnectionSettings; QLocalSocket* socket; bool connected; int theNextTag; int protocolVersion; // job management QQueue queue; QQueue pipeline; Job* currentJob; bool jobRunning; // parser stuff ImapParser *parser; }; } #endif