Monotone-Parent: 48c9c37f78835c3255c4103136b86bdfcaaca051
Monotone-Revision: d9c62c6e142174bc3d2adb12ee04492347c95ede Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2011-07-29T02:13:39 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
aaa7559ff0
commit
7a5f67babe
|
@ -1,5 +1,8 @@
|
|||
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.
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue