From 376e717f459d1a74f90ba8da6471b9d80e30722d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Vall=C3=A9s?= Date: Wed, 16 Dec 2015 18:49:09 +0100 Subject: [PATCH] oc-calendar: Use the calendar's time zone if it is present If the event was created by the MAPI client, the client's time zone (if present) is assigned to the event's calendar in iCalEvent+MAPIStore. This way, we can use it to deliver the event's properties correctly. --- OpenChange/MAPIStoreAppointmentWrapper.h | 5 +- OpenChange/MAPIStoreAppointmentWrapper.m | 149 ++++++------------ OpenChange/MAPIStoreCalendarEmbeddedMessage.m | 1 - OpenChange/MAPIStoreCalendarMessage.m | 1 - OpenChange/MAPIStoreMailMessage.m | 1 - OpenChange/MAPIStoreRecurrenceUtils.h | 5 - OpenChange/MAPIStoreRecurrenceUtils.m | 6 +- OpenChange/iCalTimeZone+MAPIStore.h | 2 + OpenChange/iCalTimeZone+MAPIStore.m | 22 +++ 9 files changed, 73 insertions(+), 119 deletions(-) diff --git a/OpenChange/MAPIStoreAppointmentWrapper.h b/OpenChange/MAPIStoreAppointmentWrapper.h index aecf2200f..d114076fe 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.h +++ b/OpenChange/MAPIStoreAppointmentWrapper.h @@ -24,6 +24,7 @@ #define MAPISTORECALENDARWRAPPER_H #import +#import #import #import "MAPIStoreObjectProxy.h" @@ -42,7 +43,7 @@ iCalCalendar *calendar; iCalEvent *firstEvent; iCalEvent *event; - NSTimeZone *timeZone; + iCalTimeZone *timeZone; SOGoUser *user; NSString *senderEmail; NSData *globalObjectId; @@ -57,12 +58,10 @@ + (id) wrapperWithICalEvent: (iCalEvent *) newEvent andUser: (SOGoUser *) newUser andSenderEmail: (NSString *) newSenderEmail - inTimeZone: (NSTimeZone *) newTimeZone withConnectionInfo: (struct mapistore_connection_info *) newConnInfo; - (id) initWithICalEvent: (iCalEvent *) newEvent andUser: (SOGoUser *) newUser andSenderEmail: (NSString *) newSenderEmail - inTimeZone: (NSTimeZone *) newTimeZone withConnectionInfo: (struct mapistore_connection_info *) newConnInfo; /* getters */ diff --git a/OpenChange/MAPIStoreAppointmentWrapper.m b/OpenChange/MAPIStoreAppointmentWrapper.m index c8c6560fb..11a189500 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.m +++ b/OpenChange/MAPIStoreAppointmentWrapper.m @@ -37,7 +37,9 @@ #import #import #import +#import #import +#import #import #import @@ -80,7 +82,6 @@ static NSCharacterSet *hexCharacterSet = nil; + (id) wrapperWithICalEvent: (iCalEvent *) newEvent andUser: (SOGoUser *) newUser andSenderEmail: (NSString *) newSenderEmail - inTimeZone: (NSTimeZone *) newTimeZone withConnectionInfo: (struct mapistore_connection_info *) newConnInfo { MAPIStoreAppointmentWrapper *wrapper; @@ -88,7 +89,6 @@ static NSCharacterSet *hexCharacterSet = nil; wrapper = [[self alloc] initWithICalEvent: newEvent andUser: newUser andSenderEmail: newSenderEmail - inTimeZone: newTimeZone withConnectionInfo: newConnInfo]; [wrapper autorelease]; @@ -182,10 +182,10 @@ static NSCharacterSet *hexCharacterSet = nil; - (id) initWithICalEvent: (iCalEvent *) newEvent andUser: (SOGoUser *) newUser andSenderEmail: (NSString *) newSenderEmail - inTimeZone: (NSTimeZone *) newTimeZone withConnectionInfo: (struct mapistore_connection_info *) newConnInfo { NSArray *events; + iCalTimeZone *tz; if ((self = [self init])) { @@ -194,9 +194,20 @@ static NSCharacterSet *hexCharacterSet = nil; event = newEvent; events = [calendar events]; firstEvent = [events objectAtIndex: 0]; - ASSIGN (timeZone, newTimeZone); ASSIGN (user, newUser); ASSIGN (senderEmail, newSenderEmail); + /* If newEvent comes from the client, we set its time zone in + updateFromMAPIProperties. If it is not present, we use the + time zone of the user */ + tz = (iCalTimeZone *) [calendar firstChildWithTag: @"vtimezone"]; + if (!tz) + { + tz = [iCalTimeZone timeZoneForName: [[[user userDefaults] timeZone] name]]; + if (!tz) + [self logWithFormat: @"no time zone could be set"]; + } + ASSIGN (timeZone, tz); + [self _setupITIPContext]; } @@ -721,22 +732,15 @@ static NSCharacterSet *hexCharacterSet = nil; inMemCtx: (TALLOC_CTX *) memCtx { NSCalendarDate *dateValue; - NSInteger offset; // if ([event isRecurrent]) // dateValue = [event firstRecurrenceStartDate]; // else dateValue = [event startDate]; if ([event isAllDay]) - { - offset = -[timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - } - [dateValue setTimeZone: utcTZ]; + dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; *data = [dateValue asFileTimeInMemCtx: memCtx]; - + return MAPISTORE_SUCCESS; } @@ -749,22 +753,14 @@ static NSCharacterSet *hexCharacterSet = nil; exceptions, where it is the normal start date for the day of the exception. */ NSCalendarDate *dateValue; - NSInteger offset; dateValue = [event recurrenceId]; if (!dateValue) dateValue = [event startDate]; - [dateValue setTimeZone: timeZone]; if ([event isAllDay]) - { - offset = -[timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - } - [dateValue setTimeZone: utcTZ]; + dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; *data = [dateValue asFileTimeInMemCtx: memCtx]; - + return MAPISTORE_SUCCESS; } @@ -772,19 +768,12 @@ static NSCharacterSet *hexCharacterSet = nil; inMemCtx: (TALLOC_CTX *) memCtx { NSCalendarDate *dateValue; - NSInteger offset; dateValue = [firstEvent startDate]; if ([firstEvent isAllDay]) - { - offset = -[timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - } - [dateValue setTimeZone: utcTZ]; + dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; *data = [dateValue asFileTimeInMemCtx: memCtx]; - + return MAPISTORE_SUCCESS; } @@ -804,8 +793,8 @@ static NSCharacterSet *hexCharacterSet = nil; month: [start monthOfYear] day: [start dayOfMonth] hour: 0 minute: 0 second: 0 - timeZone: timeZone]; - [dateValue setTimeZone: utcTZ]; + timeZone: utcTZ]; + dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; *data = [dateValue asFileTimeInMemCtx: memCtx]; rc = MAPISTORE_SUCCESS; } @@ -829,7 +818,7 @@ static NSCharacterSet *hexCharacterSet = nil; dateValue = [event startDate]; offset = [event durationAsTimeInterval]; if ([event isAllDay]) - offset -= [timeZone secondsFromGMTForDate: dateValue]; + offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT]; dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: offset]; @@ -847,15 +836,14 @@ static NSCharacterSet *hexCharacterSet = nil; dateValue = [event recurrenceId]; if (!dateValue) dateValue = [event startDate]; - [dateValue setTimeZone: timeZone]; offset = [firstEvent durationAsTimeInterval]; if ([firstEvent isAllDay]) - offset -= [timeZone secondsFromGMTForDate: dateValue]; + offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT]; dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: offset]; *data = [dateValue asFileTimeInMemCtx: memCtx]; - + return MAPISTORE_SUCCESS; } @@ -871,7 +859,7 @@ static NSCharacterSet *hexCharacterSet = nil; dateValue = [firstEvent startDate]; offset = [firstEvent durationAsTimeInterval]; if ([event isAllDay]) - offset -= [timeZone secondsFromGMTForDate: dateValue]; + offset -= [[timeZone periodForDate: dateValue] secondsOffsetFromGMT]; dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: offset]; @@ -885,23 +873,14 @@ static NSCharacterSet *hexCharacterSet = nil; { enum mapistore_error rc; NSCalendarDate *dateValue; - NSInteger offset; iCalRecurrenceRule *rrule; if ([event isRecurrent]) { rrule = [[event recurrenceRules] objectAtIndex: 0]; dateValue = [rrule untilDate]; - if (dateValue) - { - if ([event isAllDay]) - offset = -[timeZone secondsFromGMTForDate: dateValue]; - else - offset = 0; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - } + if (dateValue && [event isAllDay]) + dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; else dateValue = [NSCalendarDate dateWithYear: 4500 month: 8 day: 31 hour: 23 minute: 59 second: 00 @@ -1338,21 +1317,14 @@ static NSCharacterSet *hexCharacterSet = nil; { enum mapistore_error rc; NSCalendarDate *dateValue; - NSInteger offset; dateValue = [event recurrenceId]; if (dateValue) { rc = MAPISTORE_SUCCESS; - + if ([event isAllDay]) - { - offset = -[timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; - } - [dateValue setTimeZone: utcTZ]; + dateValue = [timeZone shiftedCalendarDateForDate: dateValue]; *data = [dateValue asFileTimeInMemCtx: memCtx]; } else @@ -1377,7 +1349,6 @@ static NSCharacterSet *hexCharacterSet = nil; iCalEventChanges *changes; NSArray *changedProperties; NSCalendarDate *dateValue; - NSInteger offset; changes = [iCalEventChanges changesFromEvent: event toEvent: exceptionEvent]; @@ -1385,28 +1356,17 @@ static NSCharacterSet *hexCharacterSet = nil; memset (extendedException, 0, sizeof (struct ExtendedException)); extendedException->ChangeHighlight.Size = sizeof (uint32_t); - dateValue = [exceptionEvent startDate]; - offset = [timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; + dateValue = [timeZone computedDateForDate: [exceptionEvent startDate]]; exceptionInfo->StartDateTime = [dateValue asMinutesSince1601]; extendedException->ChangeHighlight.Value = BIT_CH_START; extendedException->StartDateTime = exceptionInfo->StartDateTime; - dateValue = [exceptionEvent endDate]; - offset = [timeZone secondsFromGMTForDate: dateValue]; - dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; + dateValue = [timeZone computedDateForDate: [exceptionEvent endDate]]; exceptionInfo->EndDateTime = [dateValue asMinutesSince1601]; extendedException->ChangeHighlight.Value |= BIT_CH_END; extendedException->EndDateTime = exceptionInfo->EndDateTime; - dateValue = [[exceptionEvent recurrenceId] - dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: offset]; + dateValue = [timeZone computedDateForDate: [exceptionEvent recurrenceId]]; exceptionInfo->OriginalStartDate = [dateValue asMinutesSince1601]; extendedException->OriginalStartDate = exceptionInfo->OriginalStartDate; @@ -1464,7 +1424,6 @@ static NSCharacterSet *hexCharacterSet = nil; arp = talloc_zero (NULL, struct AppointmentRecurrencePattern); [rule fillRecurrencePattern: &arp->RecurrencePattern withEvent: event - inTimeZone: timeZone inMemCtx: arp]; arp->ReaderVersion2 = 0x00003006; arp->WriterVersion2 = 0x00003008; /* 0x3008 for compatibility with @@ -1475,7 +1434,7 @@ static NSCharacterSet *hexCharacterSet = nil; fields are relative to midnight of those days ([MS-OXOCAL] 2.2.1.44.5), so no time zone adjustment is needed */ if (![event isAllDay]) - [firstStartDate setTimeZone: timeZone]; + firstStartDate = [timeZone computedDateForDate: firstStartDate]; startMinutes = ([firstStartDate hourOfDay] * 60 + [firstStartDate minuteOfHour]); arp->StartTimeOffset = startMinutes; @@ -1701,15 +1660,16 @@ ReservedBlockEE2Size: 00 00 00 00 fromDate: (NSCalendarDate *) instanceDate; { uint16_t year; + NSCalendarDate *dateValue; if (instanceDate) { - [instanceDate setTimeZone: timeZone]; - year = [instanceDate yearOfCommonEra]; + dateValue = [timeZone computedDateForDate: instanceDate]; + year = [dateValue yearOfCommonEra]; newGlobalId->YH = year >> 8; newGlobalId->YL = year & 0xff; - newGlobalId->Month = [instanceDate monthOfYear]; - newGlobalId->D = [instanceDate dayOfMonth]; + newGlobalId->Month = [dateValue monthOfYear]; + newGlobalId->D = [dateValue dayOfMonth]; } } @@ -1974,7 +1934,6 @@ ReservedBlockEE2Size: 00 00 00 00 if (alarm) { alarmDate = [alarm nextAlarmDate]; - [alarmDate setTimeZone: utcTZ]; *data = [alarmDate asFileTimeInMemCtx: memCtx]; } else @@ -2036,8 +1995,7 @@ ReservedBlockEE2Size: 00 00 00 00 enum mapistore_error rc; NSString *tzid; - tzid = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] - value: 0 ofAttribute: @"tzid"]; + tzid = [timeZone tzId]; if ([tzid length] > 0) { *data = [tzid asUnicodeInMemCtx: memCtx]; @@ -2053,16 +2011,9 @@ ReservedBlockEE2Size: 00 00 00 00 inMemCtx: (TALLOC_CTX *) memCtx { enum mapistore_error rc; - iCalTimeZone *icalTZ; - icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone]; - if (icalTZ) - { - *data = [icalTZ asTimeZoneStructInMemCtx: memCtx]; - rc = MAPISTORE_SUCCESS; - } - else - rc = MAPISTORE_ERR_NOT_FOUND; + *data = [timeZone asTimeZoneStructInMemCtx: memCtx]; + rc = MAPISTORE_SUCCESS; return rc; } @@ -2071,24 +2022,16 @@ ReservedBlockEE2Size: 00 00 00 00 inMemCtx: (TALLOC_CTX *) memCtx { enum mapistore_error rc; - iCalTimeZone *icalTZ; /* [MS-OXOCAL] 3.1.5.5.1: This property is used in floating (all-day) events, specified in floating time, to convert the start date from UTC to the user's time zone */ - if ([event isAllDay]) - icalTZ = [iCalTimeZone timeZoneForName: [timeZone timeZoneName]]; - else if ([event isRecurrent]) - icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone]; - else - icalTZ = nil; - - if (icalTZ) + if ([event isAllDay] | [event isRecurrent]) { /* [MS-OXOCAL] 2.2.1.42: This property can only have the E flag set in the TimeZoneDefinition struct */ - *data = [icalTZ asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG - inMemCtx: memCtx]; + *data = [timeZone asZoneTimeDefinitionWithFlags: TZRULE_FLAG_EFFECTIVE_TZREG + inMemCtx: memCtx]; rc = MAPISTORE_SUCCESS; } else diff --git a/OpenChange/MAPIStoreCalendarEmbeddedMessage.m b/OpenChange/MAPIStoreCalendarEmbeddedMessage.m index ca3ba12d6..986b106d3 100644 --- a/OpenChange/MAPIStoreCalendarEmbeddedMessage.m +++ b/OpenChange/MAPIStoreCalendarEmbeddedMessage.m @@ -58,7 +58,6 @@ wrapperWithICalEvent: [newContainer event] andUser: [userContext sogoUser] andSenderEmail: nil - inTimeZone: [userContext timeZone] withConnectionInfo: [context connectionInfo]]; [self addProxy: appointmentWrapper]; } diff --git a/OpenChange/MAPIStoreCalendarMessage.m b/OpenChange/MAPIStoreCalendarMessage.m index 7f025e400..108471eae 100644 --- a/OpenChange/MAPIStoreCalendarMessage.m +++ b/OpenChange/MAPIStoreCalendarMessage.m @@ -197,7 +197,6 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK; = [MAPIStoreAppointmentWrapper wrapperWithICalEvent: masterEvent andUser: [userContext sogoUser] andSenderEmail: nil - inTimeZone: [userContext timeZone] withConnectionInfo: [context connectionInfo]]; [self addProxy: appointmentWrapper]; } diff --git a/OpenChange/MAPIStoreMailMessage.m b/OpenChange/MAPIStoreMailMessage.m index 235ca5698..f79511eb6 100644 --- a/OpenChange/MAPIStoreMailMessage.m +++ b/OpenChange/MAPIStoreMailMessage.m @@ -340,7 +340,6 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) wrapperWithICalEvent: event andUser: [context activeUser] andSenderEmail: senderEmail - inTimeZone: [[self userContext] timeZone] withConnectionInfo: [context connectionInfo]]; [appointmentWrapper retain]; } diff --git a/OpenChange/MAPIStoreRecurrenceUtils.h b/OpenChange/MAPIStoreRecurrenceUtils.h index 6912cb294..dbb2f0c19 100644 --- a/OpenChange/MAPIStoreRecurrenceUtils.h +++ b/OpenChange/MAPIStoreRecurrenceUtils.h @@ -25,14 +25,10 @@ #include -#import - #import #import #import -@class NSTimeZone; - @class iCalEvent; @class iCalRepeatableEntityObject; @class iCalRecurrenceRule; @@ -55,7 +51,6 @@ - (void) fillRecurrencePattern: (struct RecurrencePattern *) rp withEvent: (iCalEvent *) event - inTimeZone: (NSTimeZone *) timeZone inMemCtx: (TALLOC_CTX *) memCtx; @end diff --git a/OpenChange/MAPIStoreRecurrenceUtils.m b/OpenChange/MAPIStoreRecurrenceUtils.m index e88fb5e4a..90052474a 100644 --- a/OpenChange/MAPIStoreRecurrenceUtils.m +++ b/OpenChange/MAPIStoreRecurrenceUtils.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import @@ -265,7 +264,6 @@ - (void) fillRecurrencePattern: (struct RecurrencePattern *) rp withEvent: (iCalEvent *) event - inTimeZone: (NSTimeZone *) timeZone inMemCtx: (TALLOC_CTX *) memCtx { iCalRecurrenceFrequency freq; @@ -281,10 +279,8 @@ NSMutableArray *deletedDates, *modifiedDates; startDate = [event firstRecurrenceStartDate]; - [startDate setTimeZone: timeZone]; endDate = [event lastPossibleRecurrenceStartDate]; - [endDate setTimeZone: timeZone]; - + rp->ReaderVersion = 0x3004; rp->WriterVersion = 0x3004; diff --git a/OpenChange/iCalTimeZone+MAPIStore.h b/OpenChange/iCalTimeZone+MAPIStore.h index 01bc51b82..25817392a 100644 --- a/OpenChange/iCalTimeZone+MAPIStore.h +++ b/OpenChange/iCalTimeZone+MAPIStore.h @@ -33,6 +33,8 @@ - (iCalTimeZone *) iCalTimeZoneFromDefinition: (NSData *) value withDescription: (NSString *) description inMemCtx: (TALLOC_CTX *) memCtx; +- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date; + @end diff --git a/OpenChange/iCalTimeZone+MAPIStore.m b/OpenChange/iCalTimeZone+MAPIStore.m index bfdf64ed4..7cf380fdf 100644 --- a/OpenChange/iCalTimeZone+MAPIStore.m +++ b/OpenChange/iCalTimeZone+MAPIStore.m @@ -40,6 +40,7 @@ #include #import "iCalTimeZone+MAPIStore.h" +#import "MAPIStoreTypes.h" @interface iCalTimeZonePeriod (MAPIStorePropertiesPrivate) @@ -352,4 +353,25 @@ end: return tz; } +/** + * Adjust a date in this vTimeZone to its representation in UTC + * Example: Timezone is +0001, the date is 2015-12-15 00:00:00 +0000 + * it returns 2015-12-14 23:00:00 +0000 + * @param date the date to adjust to the timezone. + * @return a new GMT date adjusted with the offset of the timezone. + */ +- (NSCalendarDate *) shiftedCalendarDateForDate: (NSCalendarDate *) date +{ + NSCalendarDate *tmpDate; + + tmpDate = [date copy]; + [tmpDate autorelease]; + + [tmpDate setTimeZone: utcTZ]; + + return [tmpDate addYear: 0 month: 0 day: 0 + hour: 0 minute: 0 + second: -[[self periodForDate: tmpDate] secondsOffsetFromGMT]]; +} + @end