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.h"
00027 #include "job_p.h"
00028 #include "item_p.h"
00029 #include "protocolhelper.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 {" + QByteArray::number( mPendingData.size() ) + '}';
00062 if ( mPendingData.size() > 0 )
00063 command += '\n';
00064 else
00065 command += nextPartHeader();
00066 } else {
00067 command += ")\n";
00068 }
00069 return command;
00070 }
00071
00072
00073 ItemModifyJob::ItemModifyJob( const Item &item, QObject * parent )
00074 : Job( new ItemModifyJobPrivate( this, item ), parent )
00075 {
00076 Q_D( ItemModifyJob );
00077
00078 d->mOperations.insert( ItemModifyJobPrivate::RemoteId );
00079 }
00080
00081 ItemModifyJob::~ItemModifyJob()
00082 {
00083 }
00084
00085 void ItemModifyJob::doStart()
00086 {
00087 Q_D( ItemModifyJob );
00088
00089 QList<QByteArray> changes;
00090 foreach ( int op, d->mOperations ) {
00091 switch ( op ) {
00092 case ItemModifyJobPrivate::RemoteId:
00093 if ( !d->mItem.remoteId().isNull() ) {
00094 changes << "REMOTEID.SILENT";
00095 changes << ImapParser::quote( d->mItem.remoteId().toLatin1() );
00096 }
00097 break;
00098 case ItemModifyJobPrivate::Dirty:
00099 changes << "DIRTY.SILENT";
00100 changes << "false";
00101 break;
00102 }
00103 }
00104
00105 if ( d->mItem.d_func()->mFlagsOverwritten ) {
00106 changes << "FLAGS.SILENT";
00107 changes << '(' + ImapParser::join( d->mItem.flags(), " " ) + ')';
00108 } else {
00109 if ( !d->mItem.d_func()->mAddedFlags.isEmpty() ) {
00110 changes << "+FLAGS.SILENT";
00111 changes << '(' + ImapParser::join( d->mItem.d_func()->mAddedFlags, " " ) + ')';
00112 }
00113 if ( !d->mItem.d_func()->mDeletedFlags.isEmpty() ) {
00114 changes << "-FLAGS.SILENT";
00115 changes << '(' + ImapParser::join( d->mItem.d_func()->mDeletedFlags, " " ) + ')';
00116 }
00117 }
00118
00119 if ( !d->mItem.d_func()->mDeletedAttributes.isEmpty() ) {
00120 changes << "-PARTS.SILENT";
00121 QList<QByteArray> attrs;
00122 foreach ( const QByteArray &attr, d->mItem.d_func()->mDeletedAttributes )
00123 attrs << ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, attr );
00124 changes << '(' + ImapParser::join( attrs, " " ) + ')';
00125 }
00126
00127
00128 if ( changes.isEmpty() && d->mParts.isEmpty() && d->mItem.attributes().isEmpty() ) {
00129 emitResult();
00130 return;
00131 }
00132
00133 d->mTag = d->newTag();
00134 QByteArray command = d->mTag;
00135 command += " UID STORE " + QByteArray::number( d->mItem.id() ) + ' ';
00136 if ( !d->mRevCheck ) {
00137 command += "NOREV ";
00138 } else {
00139 command += "REV " + QByteArray::number( d->mItem.revision() ) + ' ';
00140 }
00141
00142 command += "SIZE " + QByteArray::number( d->mItem.size() );
00143
00144 command += " (" + ImapParser::join( changes, " " );
00145 const QByteArray attrs = ProtocolHelper::attributesToByteArray( d->mItem, true );
00146 if ( !attrs.isEmpty() )
00147 command += ' ' + attrs;
00148 command += d->nextPartHeader();
00149 d->writeData( command );
00150 d->newTag();
00151 }
00152
00153 void ItemModifyJob::doHandleResponse(const QByteArray &_tag, const QByteArray & data)
00154 {
00155 Q_D( ItemModifyJob );
00156
00157 if ( _tag == "+" ) {
00158 d->writeData( d->mPendingData );
00159 d->writeData( d->nextPartHeader() );
00160 return;
00161 }
00162 if ( _tag == d->mTag ) {
00163 if ( data.startsWith( "OK" ) ) {
00164 QDateTime modificationDateTime;
00165 if ( int pos = data.indexOf( "DATETIME" ) ) {
00166 int resultPos = ImapParser::parseDateTime( data, modificationDateTime, pos + 8 );
00167 if ( resultPos == (pos + 8) ) {
00168 kDebug( 5250 ) << "Invalid DATETIME response to STORE command: "
00169 << _tag << data;
00170 }
00171 }
00172
00173
00174 d->mItem.setRevision( d->mItem.revision() + 1 );
00175 d->mItem.setModificationTime( modificationDateTime );
00176 d->mItem.d_ptr->resetChangeLog();
00177 } else {
00178 setError( Unknown );
00179 setErrorText( QString::fromUtf8( data ) );
00180 }
00181 emitResult();
00182 return;
00183 }
00184 kDebug( 5250 ) << "Unhandled response: " << _tag << data;
00185 }
00186
00187 void ItemModifyJob::setIgnorePayload( bool ignore )
00188 {
00189 Q_D( ItemModifyJob );
00190
00191 if ( d->mIgnorePayload == ignore )
00192 return;
00193
00194 d->mIgnorePayload = ignore;
00195 if ( d->mIgnorePayload )
00196 d->mParts = QSet<QByteArray>();
00197 else {
00198 Q_ASSERT( !d->mItem.mimeType().isEmpty() );
00199 d->mParts = d->mItem.loadedPayloadParts();
00200 }
00201 }
00202
00203 bool ItemModifyJob::ignorePayload() const
00204 {
00205 Q_D( const ItemModifyJob );
00206
00207 return d->mIgnorePayload;
00208 }
00209
00210 void ItemModifyJob::disableRevisionCheck()
00211 {
00212 Q_D( ItemModifyJob );
00213
00214 d->mRevCheck = false;
00215 }
00216
00217 Item ItemModifyJob::item() const
00218 {
00219 Q_D( const ItemModifyJob );
00220
00221 return d->mItem;
00222 }
00223
00224 #include "itemmodifyjob.moc"