diff --git a/OpenChange/MAPIStoreMailFolder.h b/OpenChange/MAPIStoreMailFolder.h index 0a01476fe..2263f955b 100644 --- a/OpenChange/MAPIStoreMailFolder.h +++ b/OpenChange/MAPIStoreMailFolder.h @@ -46,6 +46,7 @@ - (BOOL) synchroniseCache; - (void) synchronizeUpdatedFolder: (NSNumber *) lastModseq withMapping: (NSMutableDictionary *) mapping; +- (BOOL) synchroniseCacheForUID: (NSString *) messageUID; - (NSNumber *) modseqFromMessageChangeNumber: (NSString *) changeNum; - (NSString *) messageUIDFromMessageKey: (NSString *) messageKey; - (NSString *) changeNumberForMessageUID: (NSString *) messageUid; diff --git a/OpenChange/MAPIStoreMailFolder.m b/OpenChange/MAPIStoreMailFolder.m index c9e168d81..2d4a20fbb 100644 --- a/OpenChange/MAPIStoreMailFolder.m +++ b/OpenChange/MAPIStoreMailFolder.m @@ -734,6 +734,70 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) talloc_free(local_mem_ctx); } +- (BOOL) synchroniseCacheForUID: (NSString *) messageUID +{ + /* Try to synchronise old UIDs in versions.plist cache using an + specific UID. It returns a boolean indicating if the + synchronisation were done. + + It should be used as last resort, keeping synchroniseCache to main + sync entry point. + */ + NSMutableDictionary *currentProperties, *messages, *messageEntry, *mapping; + NSArray *fetchResults; + uint64_t changeNumber; + NSDictionary *result; + NSNumber *modseq; + NSString *changeNumberStr; + NSData *changeKey; + + [versionsMessage reloadIfNeeded]; + currentProperties = [versionsMessage properties]; + messages = [currentProperties objectForKey: @"Messages"]; + messageEntry = [messages objectForKey: messageUID]; + if (!messageEntry) + { + [messages removeObjectForKey: messageUID]; + changeNumber = [[self context] getNewChangeNumber]; + fetchResults = [(NSDictionary *) [sogoObject fetchUIDs: [NSArray arrayWithObject: messageUID] + parts: [NSArray arrayWithObject: @"modseq"]] + objectForKey: @"fetch"]; + if ([fetchResults count] == 1) + { + result = [fetchResults objectAtIndex: 0]; + modseq = [result objectForKey: @"modseq"]; + changeNumberStr = [NSString stringWithUnsignedLongLong: changeNumber]; + + /* Create new message entry in Messages dict */ + messageEntry = [NSMutableDictionary new]; + [messages setObject: messageEntry forKey: messageUID]; + [messageEntry release]; + + /* Store the modseq and change number */ + [messageEntry setObject: modseq forKey: @"modseq"]; + [messageEntry setObject: changeNumberStr forKey: @"version"]; + + /* Store the change key */ + changeKey = [self getReplicaKeyFromGlobCnt: changeNumber >> 16]; + [self _setChangeKey: changeKey forMessageEntry: messageEntry]; + + /* Store the changeNumber -> modseq mapping */ + mapping = [currentProperties objectForKey: @"VersionMapping"]; + [mapping setObject: modseq forKey: changeNumberStr]; + + /* Save the message */ + [versionsMessage save]; + return YES; + } + else + { + return NO; + } + } + /* If message entry exists, then synchroniseCache did its job */ + return YES; +} + - (NSNumber *) modseqFromMessageChangeNumber: (NSString *) changeNum { NSDictionary *mapping; diff --git a/OpenChange/MAPIStoreMailMessage.m b/OpenChange/MAPIStoreMailMessage.m index c64f60c22..f2ab615a1 100644 --- a/OpenChange/MAPIStoreMailMessage.m +++ b/OpenChange/MAPIStoreMailMessage.m @@ -369,6 +369,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) { uint64_t version = ULLONG_MAX; NSString *uid, *changeNumber; + BOOL synced; uid = [(MAPIStoreMailFolder *) container messageUIDFromMessageKey: [self nameInContainer]]; @@ -387,8 +388,19 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) [self logWithFormat: @"got one"]; else { - [self errorWithFormat: @"still nothing. We crash!"]; - abort(); + [self warnWithFormat: @"attempting to get change number" + @" by synchronising this specific message..."]; + synced = [(MAPIStoreMailFolder *) container synchroniseCacheForUID: uid]; + if (synced) + { + changeNumber = [(MAPIStoreMailFolder *) container + changeNumberForMessageUID: uid]; + } + else + { + [self errorWithFormat: @"still nothing. We crash!"]; + abort(); + } } } version = [changeNumber unsignedLongLongValue] >> 16;