diff --git a/ChangeLog b/ChangeLog index 78221e0d3..c3b79c5d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,29 @@ (_contentForEditingFromKeys:): prefer the HTML part over the text part when composing HTML messages. +2012-03-20 Wolfgang Sourdeau + + * SoObjects/SOGo/SOGoUserFolder.m (-davLastName, -davFirstName): + quick and dirty implementation of those getters. + + * OpenChange/MAPIStoreAppointmentWrapper.m (-_setupITIPContext): + ensure method is uppercase. + + * OpenChange/MAPIStoreCalendarMessage.m + (-getPidLidAppointmentSequence:inMemCtx:): new getter. + (-save): properly initialize CREATED, LAST-MODIFIED, DTSTAMP and + SEQUENCE from MAPI properties. + + * OpenChange/MAPIStoreAppointmentWrapper.m + (-getPidLidAppointmentSequence:inMemCtx:): new getter. + + * OpenChange/NSDate+MAPIStore.m (-isNever): new accessor for dates + occurring in 4500. + + * OpenChange/MAPIStoreTypes.m (MAPIChangeKeyGUIDCompare): NSData + arguments passed as "id" due to the pickiness of some versions of + gcc. + 2012-03-19 Wolfgang Sourdeau * Main/SOGo+DAV.m (_fillCollections:where:matches:inContext:): diff --git a/OpenChange/MAPIStoreAppointmentWrapper.h b/OpenChange/MAPIStoreAppointmentWrapper.h index 7f68e82e0..efb5ac2a1 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.h +++ b/OpenChange/MAPIStoreAppointmentWrapper.h @@ -97,6 +97,8 @@ extern NSTimeZone *utcTZ; inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPidTagStartDate: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPidLidAppointmentSequence: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPidLidAppointmentStateFlags: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPidLidResponseStatus: (void **) data diff --git a/OpenChange/MAPIStoreAppointmentWrapper.m b/OpenChange/MAPIStoreAppointmentWrapper.m index 808acfe2b..b3eb8df02 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.m +++ b/OpenChange/MAPIStoreAppointmentWrapper.m @@ -162,6 +162,7 @@ static NSCharacterSet *hexCharacterSet = nil; method = [[event parent] method]; if ([method length] > 0) { + method = [method uppercaseString]; [method retain]; if ([method isEqualToString: @"REPLY"]) { @@ -657,6 +658,14 @@ static NSCharacterSet *hexCharacterSet = nil; return MAPISTORE_SUCCESS; } +- (int) getPidLidAppointmentSequence: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + *data = MAPILongValue (memCtx, [[event sequence] unsignedIntValue]); + + return MAPISTORE_SUCCESS; +} + - (int) getPidLidAppointmentStateFlags: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { diff --git a/OpenChange/MAPIStoreCalendarMessage.m b/OpenChange/MAPIStoreCalendarMessage.m index 150838384..004a30afc 100644 --- a/OpenChange/MAPIStoreCalendarMessage.m +++ b/OpenChange/MAPIStoreCalendarMessage.m @@ -166,6 +166,13 @@ return [[self appointmentWrapper] getPidTagStartDate: data inMemCtx: memCtx]; } +- (int) getPidLidAppointmentSequence: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [[self appointmentWrapper] getPidLidAppointmentSequence: data + inMemCtx: memCtx]; +} + - (int) getPidLidAppointmentStateFlags: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { @@ -718,14 +725,28 @@ vCalendar = [newEvent parent]; [vCalendar setProdID: @"-//Inverse inc.//OpenChange+SOGo//EN"]; [newEvent setCreated: now]; + // CREATED = PidTagCreationTime + value = [properties objectForKey: MAPIPropertyKey (PidTagCreationTime)]; + if (value) + [newEvent setCreated: value]; [newEvent setUid: uid]; content = [vCalendar versitString]; } vCalendar = [iCalCalendar parseSingleFromSource: content]; newEvent = [[vCalendar events] objectAtIndex: 0]; - [newEvent setTimeStampAsDate: now]; - [newEvent setLastModified: now]; + + // DTSTAMP = PidLidOwnerCriticalChange or PidLidAttendeeCriticalChange + value = [properties objectForKey: MAPIPropertyKey (PidLidOwnerCriticalChange)]; + if (!value || [value isNever]) + value = now; + [newEvent setTimeStampAsDate: value]; + + // LAST-MODIFIED = PidTagLastModificationTime + value = [properties objectForKey: MAPIPropertyKey (PidTagLastModificationTime)]; + if (!value) + value = now; + [newEvent setLastModified: value]; // summary value = [properties @@ -973,6 +994,11 @@ [newEvent setOrganizer: nil]; else { + // SEQUENCE = PidLidAppointmentSequence + value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentSequence)]; + if (value) + [newEvent setSequence: value]; + ownerUser = [[self userContext] sogoUser]; if (organizerIsSet) { @@ -1009,7 +1035,10 @@ } [person setParticipationStatus: newPartStat]; newParticipationStatus = [person partStatWithDefault]; - + + value = [properties objectForKey: MAPIPropertyKey (PidLidAttendeeCriticalChange)]; + if (value && ![value isNever]) + [newEvent setTimeStampAsDate: value]; // if (newPartStat // != iCalPersonPartStatUndefined // ) // { diff --git a/OpenChange/MAPIStoreTypes.h b/OpenChange/MAPIStoreTypes.h index 1fec6a6a7..286c0b298 100644 --- a/OpenChange/MAPIStoreTypes.h +++ b/OpenChange/MAPIStoreTypes.h @@ -43,7 +43,7 @@ id NSObjectFromMAPISPropValue (const struct mapi_SPropValue *); id NSObjectFromValuePointer (enum MAPITAGS, const void *); NSComparisonResult MAPICNCompare (uint64_t cn1, uint64_t cn2, void *); -NSComparisonResult MAPIChangeKeyGUIDCompare (NSData *ck1, NSData *ck2, void *); +NSComparisonResult MAPIChangeKeyGUIDCompare (id ck1, id ck2, void *); static inline NSNumber * MAPIPropertyKey (enum MAPITAGS propTag) diff --git a/OpenChange/MAPIStoreTypes.m b/OpenChange/MAPIStoreTypes.m index c294dd429..bcef90ae1 100644 --- a/OpenChange/MAPIStoreTypes.m +++ b/OpenChange/MAPIStoreTypes.m @@ -298,7 +298,8 @@ MAPICNCompare (uint64_t cn1, uint64_t cn2, void *unused) return result; } -NSComparisonResult MAPIChangeKeyGUIDCompare (NSData *ck1, NSData *ck2, void *unused) +NSComparisonResult +MAPIChangeKeyGUIDCompare (id ck1, id ck2, void *unused) { NSUInteger count; const unsigned char *ptr1, *ptr2; diff --git a/OpenChange/NSDate+MAPIStore.h b/OpenChange/NSDate+MAPIStore.h index a36fb5e16..3c7809f79 100644 --- a/OpenChange/NSDate+MAPIStore.h +++ b/OpenChange/NSDate+MAPIStore.h @@ -33,6 +33,8 @@ + (id) dateFromFileTime: (const struct FILETIME *) timeValue; - (struct FILETIME *) asFileTimeInMemCtx: (void *) memCtx; +- (BOOL) isNever; /* occurs on 4500-12-31 */ + @end #endif /* NSCALENDARDATE+MAPISTORE_H */ diff --git a/OpenChange/NSDate+MAPIStore.m b/OpenChange/NSDate+MAPIStore.m index d36ff6729..1c09fd0a2 100644 --- a/OpenChange/NSDate+MAPIStore.m +++ b/OpenChange/NSDate+MAPIStore.m @@ -114,4 +114,17 @@ _setupRefDate () return timeValue; } +- (BOOL) isNever /* occurs on 4500-12-31 */ +{ + NSCalendarDate *calDate; + + if ([self isKindOfClass: [NSCalendarDate class]]) + calDate = (NSCalendarDate *) self; + else + calDate = [NSCalendarDate dateWithTimeIntervalSince1970: + [self timeIntervalSince1970]]; + + return [calDate yearOfCommonEra] == 4500; +} + @end diff --git a/OpenChange/NSObject+MAPIStore.m b/OpenChange/NSObject+MAPIStore.m index 198e1969a..7fc75a74d 100644 --- a/OpenChange/NSObject+MAPIStore.m +++ b/OpenChange/NSObject+MAPIStore.m @@ -38,14 +38,15 @@ @implementation NSObject (MAPIStoreTallocHelpers) -static int MAPIStoreTallocWrapperDestroy (void *data) +static int +MAPIStoreTallocWrapperDestroy (void *data) { struct MAPIStoreTallocWrapper *wrapper; NSAutoreleasePool *pool; pool = [NSAutoreleasePool new]; wrapper = data; - NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject); + // NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject); [wrapper->MAPIStoreSOGoObject release]; [pool release]; @@ -57,10 +58,10 @@ static int MAPIStoreTallocWrapperDestroy (void *data) struct MAPIStoreTallocWrapper *wrapper; wrapper = talloc_zero (tallocCtx, struct MAPIStoreTallocWrapper); - wrapper->MAPIStoreSOGoObject = self; - [wrapper->MAPIStoreSOGoObject retain]; talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy); - NSLog (@"returning wrapper: %p; object: %p", wrapper, self); + wrapper->MAPIStoreSOGoObject = self; + [self retain]; + // NSLog (@"returning wrapper: %p; object: %p", wrapper, self); return wrapper; } diff --git a/SoObjects/SOGo/SOGoUserFolder.m b/SoObjects/SOGo/SOGoUserFolder.m index 862525153..c450dc0cf 100644 --- a/SoObjects/SOGo/SOGoUserFolder.m +++ b/SoObjects/SOGo/SOGoUserFolder.m @@ -635,6 +635,54 @@ getCNForUID: nameInContainer]; } +/* For firstname and lastname, we handle "Firstname Blabla Lastname" and + "Lastname, Firstname Blabla" */ +- (NSString *) davLastName +{ + NSArray *parts; + NSString *cn, *lastName; + NSRange comma; + + cn = [self davDisplayName]; + comma = [cn rangeOfString: @","]; + if (comma.location != NSNotFound) + lastName = [[cn substringToIndex: comma.location] + stringByTrimmingSpaces]; + else + { + parts = [cn componentsSeparatedByString: @" "]; + if ([parts count] > 0) + lastName = [parts lastObject]; + else + lastName = nil; + } + + return lastName; +} + +- (NSString *) davFirstName +{ + NSArray *parts; + NSString *subtext, *cn, *firstName; + NSRange comma; + + cn = [self davDisplayName]; + comma = [cn rangeOfString: @","]; + if (comma.location != NSNotFound) + subtext = [[cn substringFromIndex: comma.location] + stringByTrimmingSpaces]; + else + subtext = cn; + + parts = [subtext componentsSeparatedByString: @" "]; + if ([parts count] > 0) + firstName = [parts objectAtIndex: 0]; + else + firstName = nil; + + return firstName; +} + - (NSString *) davResourceId { return [NSString stringWithFormat: @"urn:uuid:%@", nameInContainer]; diff --git a/Version b/Version index edc60fbcd..09503ebca 100644 --- a/Version +++ b/Version @@ -2,6 +2,6 @@ # This file is included by library makefiles to set the version information # of the executable. -MAJOR_VERSION=1 -MINOR_VERSION=3 -SUBMINOR_VERSION=14 +MAJOR_VERSION=2 +MINOR_VERSION=0 +SUBMINOR_VERSION=0