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