diff --git a/ChangeLog b/ChangeLog index 3fd14b8b4..1401d6101 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,11 @@ (-getMessageData:inMemCtx:): when a "recipients" records is available in the properties, we must return that list instead of the list of attendees since it will be the most recent one. + (_fixupAppointmentObjectWithUID::): when an appointment had been + deleted, we first attempt to resurrect it from the database before + reinstantiating it, which allows the event synchronisation to + happen properly in [SOGoAppointmentObject + updateContentWithCalendar:fromRequest:]. * OpenChange/MAPIStoreMapping.m (_updateFolderWithURL:withURL:): we retain and release "oldURL" to avoid releasing it when it diff --git a/OpenChange/MAPIStoreCalendarMessage.m b/OpenChange/MAPIStoreCalendarMessage.m index 3cc5af4f9..7371aa826 100644 --- a/OpenChange/MAPIStoreCalendarMessage.m +++ b/OpenChange/MAPIStoreCalendarMessage.m @@ -33,8 +33,11 @@ #import #import #import +#import +#import #import #import +#import #import #import #import @@ -78,6 +81,8 @@ // extern void ndr_print_AppointmentRecurrencePattern(struct ndr_print *ndr, const char *name, const struct AppointmentRecurrencePattern *r); +static Class NSArrayK; + @implementation SOGoAppointmentObject (MAPIStoreExtension) - (Class) mapistoreMessageClass @@ -89,6 +94,11 @@ @implementation MAPIStoreCalendarMessage ++ (void) initialize +{ + NSArrayK = [NSArray class]; +} + + (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP inMemCtx: (TALLOC_CTX *) memCtx { @@ -425,14 +435,61 @@ return uid; } +- (SOGoAppointmentObject *) _resurrectRecord: (NSString *) cname + fromFolder: (SOGoAppointmentFolder *) folder +{ + NSArray *records; + EOQualifier *qualifier; + EOFetchSpecification *fs; + GCSFolder *ocsFolder; + SOGoAppointmentObject *newObject; + NSMutableDictionary *newRecord; + static NSArray *childRecordFields = nil; + + if (!childRecordFields) + { + childRecordFields = [NSArray arrayWithObjects: @"c_name", + @"c_creationdate", @"c_lastmodified", + @"c_content", nil]; + [childRecordFields retain]; + } + + ocsFolder = [folder ocsFolder]; + + qualifier + = [EOQualifier qualifierWithQualifierFormat: + [NSString stringWithFormat: @"c_name='%@'", cname]]; + fs = [EOFetchSpecification fetchSpecificationWithEntityName: [ocsFolder folderName] + qualifier: qualifier + sortOrderings: nil]; + records = [ocsFolder fetchFields: childRecordFields + fetchSpecification: fs + ignoreDeleted: NO]; + if ([records isKindOfClass: NSArrayK] && [records count]) + { + newRecord = [[records objectAtIndex: 0] mutableCopy]; + [newRecord setObject: [NSNumber numberWithInt: 0] + forKey: @"c_version"]; + newObject = [SOGoAppointmentObject objectWithRecord: newRecord + inContainer: folder]; + [newRecord autorelease]; + [newObject setIsNew: NO]; + } + else + newObject = nil; + + + return newObject; +} + - (void) _fixupAppointmentObjectWithUID: (NSString *) uid { NSString *cname, *url; MAPIStoreMapping *mapping; uint64_t objectId; + WOContext *woContext; SOGoAppointmentFolder *folder; SOGoAppointmentObject *newObject; - WOContext *woContext; cname = [[container sogoObject] resourceNameForEventUID: uid]; if (cname) @@ -443,14 +500,20 @@ mapping = [self mapping]; url = [NSString stringWithFormat: @"%@%@", [container url], cname]; - folder = [container sogoObject]; + folder = [sogoObject container]; + /* reinstantiate the old sogo object and attach it to self */ woContext = [[self userContext] woContext]; if (isNew) { - newObject = [SOGoAppointmentObject objectWithName: cname - inContainer: folder]; - [newObject setIsNew: YES]; + /* event could have been deleted, let's try to resurrect it */ + newObject = [self _resurrectRecord: cname fromFolder: folder]; + if (!newObject) + { + newObject = [SOGoAppointmentObject objectWithName: cname + inContainer: folder]; + [newObject setIsNew: YES]; + } } else {