20 #include "protocolhelper_p.h"
22 #include "attributefactory.h"
23 #include "collectionstatistics.h"
25 #include "exception.h"
26 #include "itemserializer_p.h"
27 #include "itemserializerplugin.h"
29 #include <QtCore/QDateTime>
30 #include <QtCore/QFile>
31 #include <QtCore/QVarLengthArray>
36 using namespace Akonadi;
40 QVarLengthArray<QByteArray,16> params;
41 int end = Akonadi::ImapParser::parseParenthesizedList( data, params, start );
42 for (
int i = 0; i < params.count() - 1; i += 2 ) {
43 const QByteArray key = params[i];
44 const QByteArray value = params[i + 1];
46 if ( key ==
"INHERIT" )
48 else if ( key ==
"INTERVAL" )
50 else if ( key ==
"CACHETIMEOUT" )
52 else if ( key ==
"SYNCONDEMAND" )
54 else if ( key ==
"LOCALPARTS" ) {
55 QVarLengthArray<QByteArray,16> tmp;
57 Akonadi::ImapParser::parseParenthesizedList( value, tmp );
58 for (
int j=0; j<tmp.size(); j++ )
59 parts << QString::fromLatin1( tmp[j] );
68 QByteArray rv =
"CACHEPOLICY (";
72 rv +=
"INHERIT false";
74 rv +=
" CACHETIMEOUT " + QByteArray::number( policy.
cacheTimeout() );
75 rv +=
" SYNCONDEMAND " + ( policy.
syncOnDemand() ? QByteArray(
"true") : QByteArray(
"false") );
76 rv +=
" LOCALPARTS (" + policy.
localParts().join( QLatin1String(
" ") ).toLatin1() +
')';
83 ProtocolHelperValuePool *pool,
int start )
85 if ( !pool || parentCollection == -1 ) {
91 if ( pool->ancestorCollections.contains( parentCollection ) ) {
97 pool->ancestorCollections.insert( parentCollection, entity->
parentCollection() );
106 QVarLengthArray<QByteArray, 16> ancestors;
107 QVarLengthArray<QByteArray, 16> parentIds;
109 ImapParser::parseParenthesizedList( data, ancestors );
111 for (
int i = 0; i < ancestors.count(); ++i ) {
113 ImapParser::parseParenthesizedList( ancestors[ i ], parentIds );
114 if ( parentIds.size() != 2 )
118 if ( uid == rootCollectionId ) {
136 pos = ImapParser::parseNumber( data, colId, &ok, pos );
137 if ( !ok || colId <= 0 ) {
138 kDebug() <<
"Could not parse collection id from response:" << data;
143 pos = ImapParser::parseNumber( data, parentId, &ok, pos );
144 if ( !ok || parentId < 0 ) {
145 kDebug() <<
"Could not parse parent id from response:" << data;
153 QVarLengthArray<QByteArray,16> attributes;
154 pos = ImapParser::parseParenthesizedList( data, attributes, pos );
156 for (
int i = 0; i < attributes.count() - 1; i += 2 ) {
157 const QByteArray key = attributes[i];
158 const QByteArray value = attributes[i + 1];
160 if ( key ==
"NAME" ) {
161 collection.
setName( QString::fromUtf8( value ) );
162 }
else if ( key ==
"REMOTEID" ) {
163 collection.
setRemoteId( QString::fromUtf8( value ) );
164 }
else if ( key ==
"REMOTEREVISION" ) {
166 }
else if ( key ==
"RESOURCE" ) {
167 collection.
setResource( QString::fromUtf8( value ) );
168 }
else if ( key ==
"MIMETYPE" ) {
169 QVarLengthArray<QByteArray,16> ct;
170 ImapParser::parseParenthesizedList( value, ct );
172 for (
int j = 0; j < ct.size(); j++ )
173 ct2 << QString::fromLatin1( ct[j] );
175 }
else if ( key ==
"VIRTUAL" ) {
177 }
else if ( key ==
"MESSAGES" ) {
181 }
else if ( key ==
"UNSEEN" ) {
185 }
else if ( key ==
"SIZE" ) {
187 s.
setSize( value.toLongLong() );
189 }
else if ( key ==
"CACHEPOLICY" ) {
193 }
else if ( key ==
"ANCESTORS" ) {
213 return ImapParser::join( l,
" " );
218 const QByteArray versionString( version != 0 ?
'[' + QByteArray::number( version ) +
']' :
"" );
221 return label + versionString;
223 return "PLD:" + label + versionString;
225 return "ATR:" + label + versionString;
234 if ( data.startsWith(
"PLD:" ) ) {
236 return data.mid( 4 );
237 }
else if ( data.startsWith(
"ATR:" ) ) {
239 return data.mid( 4 );
249 return QByteArray(
"(0 \"\")");
253 return '(' + QByteArray::number( col.
id() ) +
' ' + ImapParser::quote( col.
remoteId().toUtf8() ) +
") " + parentHrid;
259 return '(' + QByteArray::number( item.
id() ) +
' ' + ImapParser::quote( item.
remoteId().toUtf8() ) +
") " + parentHrid;
267 command +=
" " AKONADI_PARAM_FULLPAYLOAD;
269 command +=
" " AKONADI_PARAM_ALLATTRIBUTES;
271 command +=
" " AKONADI_PARAM_CACHEONLY;
273 command +=
" " "IGNOREERRORS";
277 command +=
" ANCESTORS 1";
280 command +=
" ANCESTORS INF";
288 command +=
" " AKONADI_PARAM_EXTERNALPAYLOAD;
290 command +=
" (UID REMOTEID REMOTEREVISION COLLECTIONID FLAGS SIZE";
292 command +=
" DATETIME";
293 foreach (
const QByteArray &part, fetchScope.
payloadParts() )
295 foreach (
const QByteArray &part, fetchScope.
attributes() )
308 QString remoteRevision;
312 for (
int i = 0; i < lineTokens.count() - 1; i += 2 ) {
313 const QByteArray key = lineTokens.value( i );
314 const QByteArray value = lineTokens.value( i + 1 );
317 uid = value.toLongLong();
318 else if ( key ==
"REV" )
320 else if ( key ==
"REMOTEID" ) {
321 if ( !value.isEmpty() )
322 rid = QString::fromUtf8( value );
325 }
else if ( key ==
"REMOTEREVISION" ) {
326 remoteRevision = QString::fromUtf8( value );
327 }
else if ( key ==
"COLLECTIONID" ) {
329 }
else if ( key ==
"MIMETYPE" ) {
331 mimeType = valuePool->mimeTypePool.sharedValue( QString::fromLatin1( value ) );
333 mimeType = QString::fromLatin1( value );
337 if ( uid < 0 || rev < 0 || mimeType.isEmpty() ) {
338 kWarning() <<
"Broken fetch response: UID, RID, REV or MIMETYPE missing!";
347 item.setStorageCollectionId( cid );
352 for (
int i = 0; i < lineTokens.count() - 1; i += 2 ) {
353 const QByteArray key = lineTokens.value( i );
355 if ( key ==
"UID" || key ==
"REV" || key ==
"REMOTEID" ||
356 key ==
"MIMETYPE" || key ==
"COLLECTIONID" || key ==
"REMOTEREVISION" )
359 if ( key ==
"FLAGS" ) {
360 QList<QByteArray> flags;
361 ImapParser::parseParenthesizedList( lineTokens[i + 1], flags );
362 if ( !flags.isEmpty() ) {
364 convertedFlags.reserve( flags.size() );
365 foreach (
const QByteArray &flag, flags ) {
367 convertedFlags.insert( valuePool->flagPool.sharedValue( flag ) );
369 convertedFlags.insert( flag );
373 }
else if ( key ==
"SIZE" ) {
374 const quint64 size = lineTokens[i + 1].toLongLong();
376 }
else if ( key ==
"DATETIME" ) {
378 ImapParser::parseDateTime( lineTokens[i + 1], datetime );
380 }
else if ( key ==
"ANCESTORS" ) {
384 QByteArray plainKey( key );
387 ImapParser::splitVersionedKey( key, plainKey, version );
391 case ProtocolHelper::PartPayload:
393 bool isExternal =
false;
394 const QByteArray fileKey = lineTokens.value( i + 1 );
395 if ( fileKey ==
"[FILE]" ) {
403 case ProtocolHelper::PartAttribute:
407 if ( lineTokens.value( i + 1 ) ==
"[FILE]" ) {
409 QFile file( QString::fromUtf8( lineTokens.value( i + 1 ) ) );
410 if ( file.open( QFile::ReadOnly ) )
413 kWarning() <<
"Failed to open attribute file: " << lineTokens.value( i + 1 );
424 case ProtocolHelper::PartGlobal:
426 kWarning() <<
"Unknown item part type:" << key;
431 item.d_ptr->resetChangeLog();