00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "itemcreatejob.h"
00022
00023 #include "collection.h"
00024 #include "imapparser_p.h"
00025 #include "item.h"
00026 #include "itemserializer_p.h"
00027 #include "job_p.h"
00028 #include "protocolhelper_p.h"
00029
00030 #include <QtCore/QDateTime>
00031
00032 #include <kdebug.h>
00033
00034 using namespace Akonadi;
00035
00036 class Akonadi::ItemCreateJobPrivate : public JobPrivate
00037 {
00038 public:
00039 ItemCreateJobPrivate( ItemCreateJob *parent )
00040 : JobPrivate( parent )
00041 {
00042 }
00043
00044 Collection mCollection;
00045 Item mItem;
00046 QSet<QByteArray> mParts;
00047 Item::Id mUid;
00048 QDateTime mDatetime;
00049 QByteArray mData;
00050 };
00051
00052 ItemCreateJob::ItemCreateJob( const Item &item, const Collection &collection, QObject * parent )
00053 : Job( new ItemCreateJobPrivate( this ), parent )
00054 {
00055 Q_D( ItemCreateJob );
00056
00057 Q_ASSERT( !item.mimeType().isEmpty() );
00058 d->mItem = item;
00059 d->mParts = d->mItem.loadedPayloadParts();
00060 d->mCollection = collection;
00061 }
00062
00063 ItemCreateJob::~ItemCreateJob()
00064 {
00065 }
00066
00067 void ItemCreateJob::doStart()
00068 {
00069 Q_D( ItemCreateJob );
00070
00071 QByteArray remoteId;
00072
00073 QList<QByteArray> flags;
00074 flags.append( "\\MimeType[" + d->mItem.mimeType().toLatin1() + ']' );
00075 if ( !d->mItem.remoteId().isEmpty() )
00076 flags.append( ImapParser::quote( "\\RemoteId[" + d->mItem.remoteId().toUtf8() + ']' ) );
00077 if ( !d->mItem.remoteRevision().isEmpty() )
00078 flags.append( ImapParser::quote( "\\RemoteRevision[" + d->mItem.remoteRevision().toUtf8() + ']' ) );
00079 flags += d->mItem.flags().toList();
00080
00081
00082 if ( d->mItem.attributes().isEmpty() && ( d->mParts.isEmpty() || (d->mParts.size() == 1 && d->mParts.contains( Item::FullPayload )) ) ) {
00083 if ( d->mItem.hasPayload() ) {
00084 int version = 0;
00085 ItemSerializer::serialize( d->mItem, Item::FullPayload, d->mData, version );
00086 }
00087 int dataSize = d->mData.size();
00088
00089 d->writeData( d->newTag() + " APPEND " + QByteArray::number( d->mCollection.id() )
00090 + ' ' + QByteArray::number( d->mItem.size() )
00091 + " (" + ImapParser::join( flags, " " ) + ") {"
00092 + QByteArray::number( dataSize ) + "}\n" );
00093 }
00094 else {
00095 QByteArray command = d->newTag() + " X-AKAPPEND " + QByteArray::number( d->mCollection.id() )
00096 + ' ' + QByteArray::number( d->mItem.size() )
00097 + " (" + ImapParser::join( flags, " " ) + ") ";
00098
00099 QList<QByteArray> partSpecs;
00100 int totalSize = 0;
00101 foreach ( const QByteArray &partName, d->mParts ) {
00102 QByteArray partData;
00103 int version = 0;
00104 ItemSerializer::serialize( d->mItem, partName, partData, version );
00105 totalSize += partData.size();
00106 const QByteArray partId = ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartPayload, partName, version );
00107 partSpecs.append( ImapParser::quote( partId ) + ':' + QByteArray::number( partData.size() ) );
00108 d->mData += partData;
00109 }
00110 foreach ( const Attribute* attr, d->mItem.attributes() ) {
00111 const QByteArray data = attr->serialized();
00112 totalSize += data.size();
00113 const QByteArray partId = ProtocolHelper::encodePartIdentifier( ProtocolHelper::PartAttribute, attr->type() );
00114 partSpecs.append( ImapParser::quote( partId ) + ':' + QByteArray::number( data.size() ) );
00115 d->mData += data;
00116 }
00117 command += '(' + ImapParser::join( partSpecs, "," ) + ") " +
00118 '{' + QByteArray::number( totalSize ) + "}\n";
00119
00120 d->writeData( command );
00121 }
00122 }
00123
00124 void ItemCreateJob::doHandleResponse( const QByteArray & tag, const QByteArray & data )
00125 {
00126 Q_D( ItemCreateJob );
00127
00128 if ( tag == "+" ) {
00129 d->writeData( d->mData );
00130 if ( !d->mData.endsWith( '\n' ) )
00131 d->writeData( "\n" );
00132 return;
00133 }
00134 if ( tag == d->tag() ) {
00135 int uidNextPos = data.indexOf( "UIDNEXT" );
00136 if ( uidNextPos != -1 ) {
00137 bool ok = false;
00138 ImapParser::parseNumber( data, d->mUid, &ok, uidNextPos + 7 );
00139 if ( !ok ) {
00140 kDebug() << "Invalid UIDNEXT response to APPEND command: "
00141 << tag << data;
00142 }
00143 }
00144 int dateTimePos = data.indexOf( "DATETIME" );
00145 if ( dateTimePos != -1 ) {
00146 int resultPos = ImapParser::parseDateTime( data, d->mDatetime, dateTimePos + 8 );
00147 if ( resultPos == (dateTimePos + 8) ) {
00148 kDebug() << "Invalid DATETIME response to APPEND command: "
00149 << tag << data;
00150 }
00151 }
00152 }
00153 }
00154
00155 Item ItemCreateJob::item() const
00156 {
00157 Q_D( const ItemCreateJob );
00158
00159 if ( d->mUid == 0 )
00160 return Item();
00161
00162 Item item( d->mItem );
00163 item.setId( d->mUid );
00164 item.setRevision( 0 );
00165 item.setModificationTime( d->mDatetime );
00166 item.setParentCollection( d->mCollection );
00167 item.setStorageCollectionId( d->mCollection.id() );
00168
00169 return item;
00170 }
00171
00172 #include "itemcreatejob.moc"