merge of 'addfe836292fcae874e765a05ef776bfe841be1d'
and 'd9c62c6e142174bc3d2adb12ee04492347c95ede' Monotone-Parent: addfe836292fcae874e765a05ef776bfe841be1d Monotone-Parent: d9c62c6e142174bc3d2adb12ee04492347c95ede Monotone-Revision: f49f7655bf5cf28a4146c61d6f0897052be0f21b Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2011-07-29T13:56:19 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
commit
5d22bac0d8
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2011-07-28 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* OpenChange/MAPIStoreSOGo.m (sogo_folder_get_deleted_fmids):
|
||||
implemented new backend method.
|
||||
|
||||
* OpenChange/MAPIStoreTable.m (-loggingPrefix): removed method as
|
||||
it was causing crashes when the parent object was deallocated.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailFolder.m (-statusForFlags:): new method
|
||||
that returns the values of flags passed as parameters.
|
||||
(-fetchUIDsOfVanishedItems:): new method that returns the list of
|
||||
UID that are reported to have vanished since the specified modseq.
|
||||
|
||||
2011-07-27 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* OpenChange/MAPIStoreGCSMessageTable.m
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
@class NSArray;
|
||||
@class NSMutableArray;
|
||||
@class NSNumber;
|
||||
@class NSURL;
|
||||
|
||||
@class EOQualifier;
|
||||
|
@ -109,6 +110,11 @@
|
|||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
- (int) deleteMessageWithMID: (uint64_t) mid
|
||||
andFlags: (uint8_t) flags;
|
||||
- (int) getDeletedFMIDs: (struct I8Array_r **) fmidsPtr
|
||||
andCN: (uint64_t *) cnPtr
|
||||
fromChangeNumber: (uint64_t) changeNum
|
||||
inTableType: (uint8_t) tableType
|
||||
inMemCtx: (TALLOC_CTX *) mem_ctx;
|
||||
|
||||
- (int) getTable: (MAPIStoreTable **) tablePtr
|
||||
andRowCount: (uint32_t *) count
|
||||
|
@ -124,6 +130,9 @@
|
|||
- (MAPIStoreMessageTable *) messageTable;
|
||||
- (NSArray *) messageKeysMatchingQualifier: (EOQualifier *) qualifier
|
||||
andSortOrderings: (NSArray *) sortOrderings;
|
||||
- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum
|
||||
andCN: (NSNumber **) cnNbr
|
||||
inTableType: (uint8_t) tableType;
|
||||
|
||||
- (NSString *) createFolder: (struct SRow *) aRow
|
||||
withFID: (uint64_t) newFID;
|
||||
|
|
|
@ -519,6 +519,64 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
return rc;
|
||||
}
|
||||
|
||||
- (int) getDeletedFMIDs: (struct I8Array_r **) fmidsPtr
|
||||
andCN: (uint64_t *) cnPtr
|
||||
fromChangeNumber: (uint64_t) changeNum
|
||||
inTableType: (uint8_t) tableType
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
int rc;
|
||||
NSString *baseURL, *format, *url;
|
||||
NSArray *keys;
|
||||
NSNumber *cnNbr;
|
||||
NSUInteger count, max;
|
||||
MAPIStoreMapping *mapping;
|
||||
struct I8Array_r *fmids;
|
||||
uint64_t fmid;
|
||||
|
||||
keys = [self getDeletedKeysFromChangeNumber: changeNum andCN: &cnNbr
|
||||
inTableType: tableType];
|
||||
if (keys)
|
||||
{
|
||||
mapping = [[self context] mapping];
|
||||
|
||||
max = [keys count];
|
||||
|
||||
fmids = talloc_zero (memCtx, struct I8Array_r);
|
||||
fmids->cValues = 0;
|
||||
fmids->lpi8 = talloc_array (fmids, int64_t, max);
|
||||
*fmidsPtr = fmids;
|
||||
if (max > 0)
|
||||
*cnPtr = [cnNbr unsignedLongLongValue];
|
||||
|
||||
baseURL = [self url];
|
||||
if ([baseURL hasSuffix: @"/"])
|
||||
format = @"%@%@";
|
||||
else
|
||||
format = @"%@/%@";
|
||||
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
url = [NSString stringWithFormat: format,
|
||||
baseURL, [keys objectAtIndex: count]];
|
||||
fmid = [mapping idFromURL: url];
|
||||
if (fmid != NSNotFound) /* if no fmid is returned, then the object
|
||||
"never existed" in the OpenChange
|
||||
databases */
|
||||
{
|
||||
fmids->lpi8[fmids->cValues] = fmid;
|
||||
fmids->cValues++;
|
||||
}
|
||||
}
|
||||
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
else
|
||||
rc = MAPISTORE_ERR_NOT_FOUND;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
- (int) getTable: (MAPIStoreTable **) tablePtr
|
||||
andRowCount: (uint32_t *) countPtr
|
||||
tableType: (uint8_t) tableType
|
||||
|
@ -928,6 +986,13 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum
|
||||
andCN: (NSNumber **) cnNbrs
|
||||
inTableType: (uint8_t) tableType
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (Class) messageClass
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
|
|
|
@ -299,6 +299,92 @@
|
|||
return changeNumber;
|
||||
}
|
||||
|
||||
- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum
|
||||
andCN: (NSNumber **) cnNbr
|
||||
inTableType: (uint8_t) tableType
|
||||
{
|
||||
NSArray *deletedKeys, *deletedCNames, *records;
|
||||
NSNumber *changeNumNbr, *lastModified;
|
||||
NSString *cName;
|
||||
NSDictionary *versionProperties;
|
||||
NSMutableDictionary *messages, *mapping;
|
||||
uint64_t newChangeNum = 0;
|
||||
EOAndQualifier *fetchQualifier;
|
||||
EOKeyValueQualifier *cDeletedQualifier, *cLastModifiedQualifier;
|
||||
EOFetchSpecification *fs;
|
||||
GCSFolder *ocsFolder;
|
||||
NSUInteger count, max;
|
||||
|
||||
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
||||
{
|
||||
deletedKeys = [NSMutableArray array];
|
||||
|
||||
changeNumNbr = [NSNumber numberWithUnsignedLongLong: changeNum];
|
||||
lastModified = [self lastModifiedFromMessageChangeNumber: changeNumNbr];
|
||||
if (lastModified)
|
||||
{
|
||||
versionProperties = [versionsMessage properties];
|
||||
messages = [versionProperties objectForKey: @"Messages"];
|
||||
|
||||
ocsFolder = [sogoObject ocsFolder];
|
||||
cLastModifiedQualifier = [[EOKeyValueQualifier alloc]
|
||||
initWithKey: @"c_lastmodified"
|
||||
operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo
|
||||
value: lastModified];
|
||||
cDeletedQualifier = [[EOKeyValueQualifier alloc]
|
||||
initWithKey: @"c_deleted"
|
||||
operatorSelector: EOQualifierOperatorEqual
|
||||
value: [NSNumber numberWithInt: 1]];
|
||||
fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers:
|
||||
cLastModifiedQualifier,
|
||||
cDeletedQualifier,
|
||||
nil];
|
||||
[fetchQualifier autorelease];
|
||||
[cLastModifiedQualifier release];
|
||||
[cDeletedQualifier release];
|
||||
|
||||
fs = [EOFetchSpecification
|
||||
fetchSpecificationWithEntityName: [ocsFolder folderName]
|
||||
qualifier: fetchQualifier
|
||||
sortOrderings: nil];
|
||||
records = [ocsFolder
|
||||
fetchFields: [NSArray arrayWithObject: @"c_name"]
|
||||
fetchSpecification: fs
|
||||
ignoreDeleted: NO];
|
||||
deletedCNames = [records objectsForKey: @"c_name" notFoundMarker: nil];
|
||||
max = [deletedCNames count];
|
||||
if (max > 0)
|
||||
{
|
||||
mapping = [versionProperties objectForKey: @"VersionsMapping"];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
cName = [deletedCNames objectAtIndex: count];
|
||||
if ([messages objectForKey: cName])
|
||||
{
|
||||
[messages removeObjectForKey: cName];
|
||||
[(NSMutableArray *) deletedKeys addObject: cName];
|
||||
newChangeNum = [[self context] getNewChangeNumber];
|
||||
}
|
||||
}
|
||||
if (newChangeNum)
|
||||
{
|
||||
changeNumNbr
|
||||
= [NSNumber numberWithUnsignedLongLong: newChangeNum];
|
||||
[mapping setObject: lastModified forKey: changeNumNbr];
|
||||
*cnNbr = changeNumNbr;
|
||||
[versionsMessage save];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
deletedKeys = [super getDeletedKeysFromChangeNumber: changeNum
|
||||
andCN: cnNbr
|
||||
inTableType: tableType];
|
||||
|
||||
return deletedKeys;
|
||||
}
|
||||
|
||||
/* subclasses */
|
||||
|
||||
- (EOQualifier *) componentQualifier
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#import <EOControl/EOSortOrdering.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGImap4/NGImap4Connection.h>
|
||||
#import <Mailer/SOGoDraftsFolder.h>
|
||||
#import <Mailer/SOGoMailAccount.h>
|
||||
#import <Mailer/SOGoMailAccounts.h>
|
||||
|
@ -97,6 +98,9 @@ static Class SOGoMailFolderK;
|
|||
accountFolder = [accountsFolder lookupName: @"0"
|
||||
inContext: woContext
|
||||
acquire: NO];
|
||||
[[accountFolder imap4Connection]
|
||||
enableExtension: @"QRESYNC"];
|
||||
|
||||
[parentContainersBag addObject: accountFolder];
|
||||
[woContext setClientObject: accountFolder];
|
||||
|
||||
|
@ -501,6 +505,61 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
|||
return changeNumber;
|
||||
}
|
||||
|
||||
- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum
|
||||
andCN: (NSNumber **) cnNbr
|
||||
inTableType: (uint8_t) tableType
|
||||
{
|
||||
NSArray *deletedKeys, *deletedUIDs;
|
||||
NSNumber *changeNumNbr;
|
||||
uint64_t modseq;
|
||||
NSDictionary *versionProperties, *status;
|
||||
NSMutableDictionary *messages, *mapping;
|
||||
NSNumber *newChangeNumNbr, *highestModseq;
|
||||
uint64_t newChangeNum;
|
||||
NSUInteger count, max;
|
||||
|
||||
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
||||
{
|
||||
changeNumNbr = [NSNumber numberWithUnsignedLongLong: changeNum];
|
||||
modseq = [[self modseqFromMessageChangeNumber: changeNumNbr]
|
||||
unsignedLongLongValue];
|
||||
if (modseq > 0)
|
||||
{
|
||||
status
|
||||
= [sogoObject
|
||||
statusForFlags: [NSArray arrayWithObject: @"HIGHESTMODSEQ"]];
|
||||
highestModseq = [status objectForKey: @"highestmodseq"];
|
||||
|
||||
versionProperties = [versionsMessage properties];
|
||||
messages = [versionProperties objectForKey: @"Messages"];
|
||||
deletedUIDs = [(SOGoMailFolder *) sogoObject
|
||||
fetchUIDsOfVanishedItems: modseq];
|
||||
deletedKeys = [deletedUIDs stringsWithFormat: @"%@.eml"];
|
||||
max = [deletedUIDs count];
|
||||
if (max > 0)
|
||||
{
|
||||
[messages removeObjectsForKeys: deletedUIDs];
|
||||
|
||||
mapping = [versionProperties objectForKey: @"VersionsMapping"];
|
||||
for (count = 0; count < max; count++)
|
||||
newChangeNum = [[self context] getNewChangeNumber];
|
||||
newChangeNumNbr = [NSNumber numberWithUnsignedLongLong: newChangeNum];
|
||||
*cnNbr = newChangeNumNbr;
|
||||
[mapping setObject: newChangeNumNbr forKey: @"SyncLastModseq"];
|
||||
[versionsMessage save];
|
||||
}
|
||||
}
|
||||
else
|
||||
deletedKeys = [NSArray array];
|
||||
}
|
||||
else
|
||||
deletedKeys = [super getDeletedKeysFromChangeNumber: changeNum
|
||||
andCN: cnNbr
|
||||
inTableType: tableType];
|
||||
|
||||
return deletedKeys;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MAPIStoreInboxFolder : MAPIStoreMailFolder
|
||||
|
|
|
@ -62,6 +62,8 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
|||
mapping = data;
|
||||
[mapping setObject: uri forKey: idNbr];
|
||||
|
||||
NSLog (@"preregistered url '%@' for id '%@'", uri, idNbr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -104,6 +106,7 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
|||
{
|
||||
idNbr = [keys objectAtIndex: count];
|
||||
uri = [mapping objectForKey: idNbr];
|
||||
[self logWithFormat: @"preregistered id '%@' for url '%@'", idNbr, uri];
|
||||
[reverseMapping setObject: idNbr forKey: uri];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -441,6 +441,39 @@ sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||
uint8_t table_type, uint64_t change_num,
|
||||
struct I8Array_r **fmidsp, uint64_t *cnp)
|
||||
{
|
||||
struct MAPIStoreTallocWrapper *wrapper;
|
||||
NSAutoreleasePool *pool;
|
||||
MAPIStoreFolder *folder;
|
||||
int rc;
|
||||
|
||||
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
|
||||
|
||||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder getDeletedFMIDs: fmidsp
|
||||
andCN: cnp
|
||||
fromChangeNumber: change_num
|
||||
inTableType: table_type
|
||||
inMemCtx: mem_ctx];
|
||||
[pool release];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog (@" UNEXPECTED WEIRDNESS: RECEIVED NO OBJECT");
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
sogo_folder_open_table(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||
uint8_t table_type, uint32_t handle_id,
|
||||
|
@ -989,6 +1022,7 @@ int mapistore_init_backend(void)
|
|||
backend.folder.open_message = sogo_folder_open_message;
|
||||
backend.folder.create_message = sogo_folder_create_message;
|
||||
backend.folder.delete_message = sogo_folder_delete_message;
|
||||
backend.folder.get_deleted_fmids = sogo_folder_get_deleted_fmids;
|
||||
backend.folder.get_child_count = sogo_folder_get_child_count;
|
||||
backend.folder.open_table = sogo_folder_open_table;
|
||||
backend.message.create_attachment = sogo_message_create_attachment;
|
||||
|
|
|
@ -916,12 +916,4 @@ static Class NSDataK, NSStringK;
|
|||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
/* logging */
|
||||
- (NSString *) loggingPrefix
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@:%p:%@>",
|
||||
NSStringFromClass (isa), self,
|
||||
[container nameInContainer]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
- (NSArray *) toOneRelationshipKeys;
|
||||
- (NSArray *) toManyRelationshipKeys;
|
||||
|
||||
- (NSDictionary *) statusForFlags: (NSArray *) flags;
|
||||
|
||||
- (NSException *) deleteUIDs: (NSArray *) uids
|
||||
useTrashFolder: (BOOL *) withTrash
|
||||
inContext: (id) context;
|
||||
|
@ -63,6 +65,7 @@
|
|||
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q sortOrdering: (id) _so;
|
||||
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q sortOrdering: (id) _so threaded: (BOOL) _threaded;
|
||||
- (NSArray *) fetchUIDs: (NSArray *) _uids parts: (NSArray *) _parts;
|
||||
- (NSArray *) fetchUIDsOfVanishedItems: (uint64_t) modseq;
|
||||
|
||||
- (WOResponse *) copyUIDs: (NSArray *) uids
|
||||
toFolder: (NSString *) destinationFolder
|
||||
|
|
|
@ -555,6 +555,24 @@ static NSString *defaultUserID = @"anyone";
|
|||
return result;
|
||||
}
|
||||
|
||||
- (NSDictionary *) statusForFlags: (NSArray *) flags
|
||||
{
|
||||
NGImap4Client *client;
|
||||
NSString *folderName;
|
||||
NSDictionary *result, *status;
|
||||
|
||||
client = [[self imap4Connection] client];
|
||||
folderName = [[self imap4Connection] imap4FolderNameForURL: [self imap4URL]];
|
||||
result = [client status: folderName flags: flags];
|
||||
if ([[result objectForKey: @"result"] boolValue])
|
||||
status = [[[result objectForKey: @"RawResponse"] objectForKey: @"status"]
|
||||
objectForKey: @"flags"];
|
||||
else
|
||||
status = nil;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
- (NSArray *) fetchUIDsMatchingQualifier: (id) _q
|
||||
sortOrdering: (id) _so
|
||||
{
|
||||
|
@ -588,6 +606,17 @@ static NSString *defaultUserID = @"anyone";
|
|||
parts: _parts];
|
||||
}
|
||||
|
||||
- (NSArray *) fetchUIDsOfVanishedItems: (uint64_t) modseq
|
||||
{
|
||||
NGImap4Client *client;
|
||||
NSDictionary *result;
|
||||
|
||||
client = [[self imap4Connection] client];
|
||||
result = [client fetchVanished: modseq];
|
||||
|
||||
return [result objectForKey: @"vanished"];
|
||||
}
|
||||
|
||||
- (NSException *) postData: (NSData *) _data
|
||||
flags: (id) _flags
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue