akonadi
itemmodifyjob.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "itemmodifyjob.h"
00021 #include "itemmodifyjob_p.h"
00022
00023 #include "collection.h"
00024 #include "entity_p.h"
00025 #include "imapparser_p.h"
00026 #include "itemserializer_p.h"
00027 #include "job_p.h"
00028 #include "item_p.h"
00029 #include "protocolhelper_p.h"
00030
00031 #include <kdebug.h>
00032
00033 using namespace Akonadi;
00034
00035 ItemModifyJobPrivate::ItemModifyJobPrivate( ItemModifyJob *parent, const Item &item )
00036 : JobPrivate( parent ),
00037 mItem( item ),
00038 mRevCheck( true ),
00039 mIgnorePayload( false )
00040 {
00041 mParts = mItem.loadedPayloadParts();
00042 }
00043
00044 void ItemModifyJobPrivate::setClean()
00045 {
00046 mOperations.insert( Dirty );
00047 }
00048
00049 QByteArray ItemModifyJobPrivate::nextPartHeader()
00050 {
00051 QByteArray command;
00052 if ( !mParts.isEmpty() ) {
00053 QSetIterator<QByteArray> it( mParts );
00054 const QByteArray label = it.next();
00055 mParts.remove( label );
00056
00057 mPendingData.clear();
00058 int version = 0;
00059 ItemSerializer::serialize( mItem, label, mPendingData, version );
00060 command += ' ' + ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartPayload, label, version );
00061 command += ".SILENT";
00062 if ( mPendingData.size() > 0 ) {
00063 command += " {" + QByteArray::number( mPendingData.size() ) + "}\n";
00064 } else {
00065 if ( mPendingData.isNull() )
00066 command += " NIL";
00067 else
00068 command += " \"\"";
00069 command += nextPartHeader();
00070 }
00071 } else {
00072 command += ")\n";
00073 }
00074 return command;
00075 }
00076
00077
00078 ItemModifyJob::ItemModifyJob( const Item &item, QObject * parent )
00079 : Job( new ItemModifyJobPrivate( this, item ), parent )
00080 {
00081 Q_D( ItemModifyJob );
00082
00083 d->mOperations.insert( ItemModifyJobPrivate::RemoteId );
00084 }
00085
00086 ItemModifyJob::~ItemModifyJob()
00087 {
00088 }
00089
00090 void ItemModifyJob::doStart()
00091 {
00092 Q_D( ItemModifyJob );
00093
00094 QList<QByteArray> changes;
00095 foreach ( int op, d->mOperations ) {
00096 switch ( op ) {
00097 case ItemModifyJobPrivate::RemoteId:
00098 if ( !d->mItem.remoteId().isNull() ) {
00099 changes << "REMOTEID.SILENT";
00100 changes << ImapParser::quote( d->mItem.remoteId().toUtf8() );
00101 }
00102 break;
00103 case ItemModifyJobPrivate::Dirty:
00104 changes << "DIRTY.SILENT";
00105 changes << "false";
00106 break;
00107 }
00108 }
00109
00110 if ( d->mItem.d_func()->mFlagsOverwritten ) {
00111 changes << "FLAGS.SILENT";
00112 changes << '(' + ImapParser::join( d->mItem.flags(), " " ) + ')';
00113 } else {
00114 if ( !d->mItem.d_func()->mAddedFlags.isEmpty() ) {
00115 changes << "+FLAGS.SILENT";
00116 changes << '(' + ImapParser::join( d->mItem.d_func()->mAddedFlags, " " ) + ')';
00117 }
00118 if ( !d->mItem.d_func()->mDeletedFlags.isEmpty() ) {
00119 changes << "-FLAGS.SILENT";
00120 changes << '(' + ImapParser::join( d->mItem.d_func()->mDeletedFlags, " " ) + ')';
00121 }
00122 }
00123
00124 if ( !d->mItem.d_func()->mDeletedAttributes.isEmpty() ) {
00125 changes << "-PARTS.SILENT";
00126 QList<QByteArray> attrs;
00127 foreach ( const QByteArray &attr, d->mItem.d_func()->mDeletedAttributes )
00128 attrs << ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, attr );
00129 changes << '(' + ImapParser::join( attrs, " " ) + ')';
00130 }
00131
00132
00133 if ( changes.isEmpty() && d->mParts.isEmpty() && d->mItem.attributes().isEmpty() ) {
00134 emitResult();
00135 return;
00136 }
00137
00138 d->mTag = d->newTag();
00139 QByteArray command = d->mTag;
00140 command += " UID STORE " + QByteArray::number( d->mItem.id() ) + ' ';
00141 if ( !d->mRevCheck ) {
00142 command += "NOREV ";
00143 } else {
00144 command += "REV " + QByteArray::number( d->mItem.revision() ) + ' ';
00145 }
00146
00147 if ( d->mItem.d_func()->mSizeChanged )
00148 command += "SIZE " + QByteArray::number( d->mItem.size() );
00149
00150 command += " (" + ImapParser::join( changes, " " );
00151 const QByteArray attrs = ProtocolHelper::attributesToByteArray( d->mItem, true );
00152 if ( !attrs.isEmpty() )
00153 command += ' ' + attrs;
00154 command += d->nextPartHeader();
00155 d->writeData( command );
00156 d->newTag();
00157 }
00158
00159 void ItemModifyJob::doHandleResponse(const QByteArray &_tag, const QByteArray & data)
00160 {
00161 Q_D( ItemModifyJob );
00162
00163 if ( _tag == "+" ) {
00164 d->writeData( d->mPendingData );
00165 d->writeData( d->nextPartHeader() );
00166 return;
00167 }
00168 if ( _tag == d->mTag ) {
00169 if ( data.startsWith( "OK" ) ) {
00170 QDateTime modificationDateTime;
00171 int dateTimePos = data.indexOf( "DATETIME" );
00172 if ( dateTimePos != -1 ) {
00173 int resultPos = ImapParser::parseDateTime( data, modificationDateTime, dateTimePos + 8 );
00174 if ( resultPos == (dateTimePos + 8) ) {
00175 kDebug() << "Invalid DATETIME response to STORE command: " << _tag << data;
00176 }
00177 }
00178
00179
00180 d->mItem.setRevision( d->mItem.revision() + 1 );
00181 d->mItem.setModificationTime( modificationDateTime );
00182 d->mItem.d_ptr->resetChangeLog();
00183 } else {
00184 setError( Unknown );
00185 setErrorText( QString::fromUtf8( data ) );
00186 }
00187 emitResult();
00188 return;
00189 }
00190 kDebug() << "Unhandled response: " << _tag << data;
00191 }
00192
00193 void ItemModifyJob::setIgnorePayload( bool ignore )
00194 {
00195 Q_D( ItemModifyJob );
00196
00197 if ( d->mIgnorePayload == ignore )
00198 return;
00199
00200 d->mIgnorePayload = ignore;
00201 if ( d->mIgnorePayload )
00202 d->mParts = QSet<QByteArray>();
00203 else {
00204 Q_ASSERT( !d->mItem.mimeType().isEmpty() );
00205 d->mParts = d->mItem.loadedPayloadParts();
00206 }
00207 }
00208
00209 bool ItemModifyJob::ignorePayload() const
00210 {
00211 Q_D( const ItemModifyJob );
00212
00213 return d->mIgnorePayload;
00214 }
00215
00216 void ItemModifyJob::disableRevisionCheck()
00217 {
00218 Q_D( ItemModifyJob );
00219
00220 d->mRevCheck = false;
00221 }
00222
00223 Item ItemModifyJob::item() const
00224 {
00225 Q_D( const ItemModifyJob );
00226
00227 return d->mItem;
00228 }
00229
00230 #include "itemmodifyjob.moc"