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 d->mOperations.insert( ItemModifyJobPrivate::RemoteRevision );
00085 }
00086
00087 ItemModifyJob::~ItemModifyJob()
00088 {
00089 }
00090
00091 void ItemModifyJob::doStart()
00092 {
00093 Q_D( ItemModifyJob );
00094
00095 QList<QByteArray> changes;
00096 foreach ( int op, d->mOperations ) {
00097 switch ( op ) {
00098 case ItemModifyJobPrivate::RemoteId:
00099 if ( !d->mItem.remoteId().isNull() ) {
00100 changes << "REMOTEID.SILENT";
00101 changes << ImapParser::quote( d->mItem.remoteId().toUtf8() );
00102 }
00103 break;
00104 case ItemModifyJobPrivate::RemoteRevision:
00105 if ( !d->mItem.remoteRevision().isNull() ) {
00106 changes << "REMOTEREVISION.SILENT";
00107 changes << ImapParser::quote( d->mItem.remoteRevision().toUtf8() );
00108 }
00109 break;
00110 case ItemModifyJobPrivate::Dirty:
00111 changes << "DIRTY.SILENT";
00112 changes << "false";
00113 break;
00114 }
00115 }
00116
00117 if ( d->mItem.d_func()->mClearPayload )
00118 changes << "INVALIDATECACHE.SILENT";
00119
00120 if ( d->mItem.d_func()->mFlagsOverwritten ) {
00121 changes << "FLAGS.SILENT";
00122 changes << '(' + ImapParser::join( d->mItem.flags(), " " ) + ')';
00123 } else {
00124 if ( !d->mItem.d_func()->mAddedFlags.isEmpty() ) {
00125 changes << "+FLAGS.SILENT";
00126 changes << '(' + ImapParser::join( d->mItem.d_func()->mAddedFlags, " " ) + ')';
00127 }
00128 if ( !d->mItem.d_func()->mDeletedFlags.isEmpty() ) {
00129 changes << "-FLAGS.SILENT";
00130 changes << '(' + ImapParser::join( d->mItem.d_func()->mDeletedFlags, " " ) + ')';
00131 }
00132 }
00133
00134 if ( !d->mItem.d_func()->mDeletedAttributes.isEmpty() ) {
00135 changes << "-PARTS.SILENT";
00136 QList<QByteArray> attrs;
00137 foreach ( const QByteArray &attr, d->mItem.d_func()->mDeletedAttributes )
00138 attrs << ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, attr );
00139 changes << '(' + ImapParser::join( attrs, " " ) + ')';
00140 }
00141
00142
00143 if ( changes.isEmpty() && d->mParts.isEmpty() && d->mItem.attributes().isEmpty() ) {
00144 emitResult();
00145 return;
00146 }
00147
00148 d->mTag = d->newTag();
00149 QByteArray command = d->mTag;
00150 command += " UID STORE " + QByteArray::number( d->mItem.id() ) + ' ';
00151 if ( !d->mRevCheck ) {
00152 command += "NOREV ";
00153 } else {
00154 command += "REV " + QByteArray::number( d->mItem.revision() ) + ' ';
00155 }
00156
00157 if ( d->mItem.d_func()->mSizeChanged )
00158 command += "SIZE " + QByteArray::number( d->mItem.size() );
00159
00160 command += " (" + ImapParser::join( changes, " " );
00161 const QByteArray attrs = ProtocolHelper::attributesToByteArray( d->mItem, true );
00162 if ( !attrs.isEmpty() )
00163 command += ' ' + attrs;
00164 command += d->nextPartHeader();
00165 d->writeData( command );
00166 d->newTag();
00167 }
00168
00169 void ItemModifyJob::doHandleResponse(const QByteArray &_tag, const QByteArray & data)
00170 {
00171 Q_D( ItemModifyJob );
00172
00173 if ( _tag == "+" ) {
00174 d->writeData( d->mPendingData );
00175 d->writeData( d->nextPartHeader() );
00176 return;
00177 }
00178 if ( _tag == d->mTag ) {
00179 if ( data.startsWith( "OK" ) ) {
00180 QDateTime modificationDateTime;
00181 int dateTimePos = data.indexOf( "DATETIME" );
00182 if ( dateTimePos != -1 ) {
00183 int resultPos = ImapParser::parseDateTime( data, modificationDateTime, dateTimePos + 8 );
00184 if ( resultPos == (dateTimePos + 8) ) {
00185 kDebug() << "Invalid DATETIME response to STORE command: " << _tag << data;
00186 }
00187 }
00188
00189 if ( d->mItem.modificationTime() != modificationDateTime )
00190 {
00191
00192 d->mItem.setRevision( d->mItem.revision() + 1 );
00193 d->mItem.setModificationTime( modificationDateTime );
00194 } else {
00195 kDebug() << "No changes on item" << d->mItem.id();
00196 }
00197 d->mItem.d_ptr->resetChangeLog();
00198 } else {
00199 setError( Unknown );
00200 setErrorText( QString::fromUtf8( data ) );
00201 }
00202 emitResult();
00203 return;
00204 }
00205 kDebug() << "Unhandled response: " << _tag << data;
00206 }
00207
00208 void ItemModifyJob::setIgnorePayload( bool ignore )
00209 {
00210 Q_D( ItemModifyJob );
00211
00212 if ( d->mIgnorePayload == ignore )
00213 return;
00214
00215 d->mIgnorePayload = ignore;
00216 if ( d->mIgnorePayload )
00217 d->mParts = QSet<QByteArray>();
00218 else {
00219 Q_ASSERT( !d->mItem.mimeType().isEmpty() );
00220 d->mParts = d->mItem.loadedPayloadParts();
00221 }
00222 }
00223
00224 bool ItemModifyJob::ignorePayload() const
00225 {
00226 Q_D( const ItemModifyJob );
00227
00228 return d->mIgnorePayload;
00229 }
00230
00231 void ItemModifyJob::disableRevisionCheck()
00232 {
00233 Q_D( ItemModifyJob );
00234
00235 d->mRevCheck = false;
00236 }
00237
00238 Item ItemModifyJob::item() const
00239 {
00240 Q_D( const ItemModifyJob );
00241
00242 return d->mItem;
00243 }
00244
00245 #include "itemmodifyjob.moc"