From 3f5e37c50db29d03961f6c75bdc2494f17cfe9d3 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Fri, 15 Apr 2011 21:10:56 +0000 Subject: [PATCH 1/8] Monotone-Parent: 79d4612ae4a95206d934814a5aef8dd0eb18b3a5 Monotone-Revision: ed8a21d5648d8bc72dc33ad272987d8963be1285 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-15T21:10:56 Monotone-Branch: ca.inverse.sogo --- SOPE/NGCards/iCalEvent.h | 1 + 1 file changed, 1 insertion(+) diff --git a/SOPE/NGCards/iCalEvent.h b/SOPE/NGCards/iCalEvent.h index 4383a8d9f..05fe05c5b 100644 --- a/SOPE/NGCards/iCalEvent.h +++ b/SOPE/NGCards/iCalEvent.h @@ -51,6 +51,7 @@ - (BOOL) hasEndDate; - (NSString *) duration; +- (void) setDuration: (NSString *) _value; - (BOOL) hasDuration; - (NSTimeInterval) durationAsTimeInterval; From 037e2e6c1f096ea0f57f9ccfa7a182f2f522cb93 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Sat, 16 Apr 2011 01:35:06 +0000 Subject: [PATCH 2/8] See ChangeLog. Monotone-Parent: ed8a21d5648d8bc72dc33ad272987d8963be1285 Monotone-Revision: 12a15fd8afcf3963e3ec84c6a630972534773465 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-16T01:35:06 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 14 ++ .../Appointments/SOGoAppointmentFolder.m | 121 +++++++++++------- .../Appointments/SOGoAppointmentObject.m | 40 ++++++ SoObjects/Appointments/iCalEvent+SOGo.h | 1 + SoObjects/Appointments/iCalEvent+SOGo.m | 18 ++- 5 files changed, 140 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b7a88454..1a5490181 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2011-04-15 Francis Lachapelle + * SoObjects/Appointments/iCalEvent+SOGo.m (-firstOccurenceRange): + we now compute the end date by looking at the occurrence + interval. This way, we support events with an end date or a duration. + + * SoObjects/Appointments/SOGoAppointmentFolder.m + (-_flattenCycleRecord:forRange:intoArray:): also compute the end + date by looking at the occurrence interval. + (-importCalendar:): added a duration to events with no end date nor duration. + + * SoObjects/Appointments/SOGoAppointmentObject.m + (-_adjustEventsInRequest:): new method to verify the vCalendar for + any inconsistency or missing attributes. Currently, it only adds a + duration if no end date nor duration is found. + * UI/WebServerResources/ckeditor/config.js: Changed the default enter mode to use BR instead of P. This matches the behavior of Thunderbird. diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 0498d1bcf..2419a203b 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -73,6 +73,7 @@ #import #import "iCalRepeatableEntityObject+SOGo.h" +#import "iCalEvent+SOGo.h" #import "iCalPerson+SOGo.h" #import "SOGoAppointmentObject.h" #import "SOGoAppointmentFolders.h" @@ -849,9 +850,9 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir NSArray *rules, *exRules, *exDates, *ranges; NSArray *elements, *components; NSString *content; - iCalRepeatableEntityObject *component; id firstStartDate, firstEndDate; NSCalendarDate *checkStartDate, *checkEndDate; + iCalEvent *component; iCalTimeZone *eventTimeZone; unsigned count, max, offset; @@ -890,52 +891,54 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir // Retrieve the range of the first/master event component = [components objectAtIndex: 0]; firstStartDate = [component uniqueChildWithTag: @"dtstart"]; - firstEndDate = [component uniqueChildWithTag: @"dtend"]; - eventTimeZone = [(iCalDateTime*)firstStartDate timeZone]; - firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: [[[firstStartDate values] lastObject] asCalendarDate] - endDate: [[[firstEndDate values] lastObject] asCalendarDate]]; - - if (eventTimeZone) - { - // Adjust the range to check with respect to the event timezone (extracted from the start date) - checkStartDate = [eventTimeZone computedDateForDate: [theRange startDate]]; - checkEndDate = [eventTimeZone computedDateForDate: [theRange endDate]]; - recurrenceRange = [NGCalendarDateRange calendarDateRangeWithStartDate: checkStartDate - endDate: checkEndDate]; - - // Adjust the exception dates - exDates = [eventTimeZone computedDatesForStrings: exDates]; - - // Adjust the recurrence rules "until" dates - rules = [component recurrenceRulesWithTimeZone: eventTimeZone]; - exRules = [component exceptionRulesWithTimeZone: eventTimeZone]; - } - else - { - recurrenceRange = theRange; - if ([[theRecord objectForKey: @"c_isallday"] boolValue]) - { - // The event lasts all-day and has no timezone (floating); we convert the range of the first event - // to the user's timezone - offset = [timeZone secondsFromGMTForDate: [firstRange startDate]]; - firstStartDate = (NSCalendarDate*)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; - firstEndDate = (NSCalendarDate*)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; - [firstStartDate setTimeZone: timeZone]; - [firstEndDate setTimeZone: timeZone]; - firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate - endDate: firstEndDate]; - } - } - - // Calculate the occurrences for the given range + firstStartDate = [[[firstStartDate values] lastObject] asCalendarDate]; + firstEndDate = [firstStartDate addTimeInterval: [component occurenceInterval]]; + + firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate + endDate: firstEndDate]; + + eventTimeZone = [(iCalDateTime*)firstStartDate timeZone]; + if (eventTimeZone) + { + // Adjust the range to check with respect to the event timezone (extracted from the start date) + checkStartDate = [eventTimeZone computedDateForDate: [theRange startDate]]; + checkEndDate = [eventTimeZone computedDateForDate: [theRange endDate]]; + recurrenceRange = [NGCalendarDateRange calendarDateRangeWithStartDate: checkStartDate + endDate: checkEndDate]; + + // Adjust the exception dates + exDates = [eventTimeZone computedDatesForStrings: exDates]; + + // Adjust the recurrence rules "until" dates + rules = [component recurrenceRulesWithTimeZone: eventTimeZone]; + exRules = [component exceptionRulesWithTimeZone: eventTimeZone]; + } + else + { + recurrenceRange = theRange; + if ([[theRecord objectForKey: @"c_isallday"] boolValue]) + { + // The event lasts all-day and has no timezone (floating); we convert the range of the first event + // to the user's timezone + offset = [timeZone secondsFromGMTForDate: [firstRange startDate]]; + firstStartDate = (NSCalendarDate*)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + seconds:-offset]; + firstEndDate = (NSCalendarDate*)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + seconds:-offset]; + [firstStartDate setTimeZone: timeZone]; + [firstEndDate setTimeZone: timeZone]; + firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate + endDate: firstEndDate]; + } + } + + // Calculate the occurrences for the given range records = [NSMutableArray array]; - ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: recurrenceRange - firstInstanceCalendarDateRange: firstRange + ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: recurrenceRange + firstInstanceCalendarDateRange: firstRange recurrenceRules: rules - exceptionRules: exRules - exceptionDates: exDates]; + exceptionRules: exRules + exceptionDates: exDates]; max = [ranges count]; for (count = 0; count < max; count++) { @@ -947,15 +950,15 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir if (fixedRow) [records addObject: fixedRow]; } - + [self _appendCycleExceptionsFromRow: row firstInstanceCalendarDateRange: firstRange forRange: theRange toArray: records]; - + [theRecords addObjectsFromArray: records]; - } - } + } + } } else [self errorWithFormat:@"cyclic record doesn't have content -> %@", theRecord]; @@ -2607,6 +2610,11 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir return ([object saveContentString: content] == nil); } +/** + * Import all components of a vCalendar. + * @param calendar the calendar to import + * @return the number of components imported + */ - (int) importCalendar: (iCalCalendar *) calendar { NSArray *vtimezones; @@ -2616,6 +2624,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir iCalEntityObject *element; iCalDateTime *startDate; iCalTimeZone *timezone; + iCalEvent *event; int imported, count, i; @@ -2651,6 +2660,20 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir { timezone = [startDate timeZone]; tz = [timezones valueForKey: [timezone tzId]]; + if ([element isKindOfClass: [iCalEvent class]]) + { + event = (iCalEvent *)element; + if (![event hasEndDate] && ![event hasDuration]) + { + // No end date, no duration + if ([event isAllDay]) + [event setDuration: @"P1D"]; + else + [event setDuration: @"PT1H"]; + + [self errorWithFormat: @"Importing event with no end date; setting duration to %@", [event duration]]; + } + } } if ([self importComponent: element timezone: (tz == nil? @"" : tz)]) diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index bec825629..29a308411 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -1336,6 +1336,44 @@ [rq setContent: [[calendar versitString] dataUsingEncoding: [rq contentEncoding]]]; } +/** + * Verify vCalendar for any inconsistency or missing attributes. + * Currently only check if the events have an end date or a duration. + * @param rq the HTTP PUT request + */ +- (void) _adjustEventsInRequest: (WORequest *) rq +{ + iCalCalendar *calendar; + NSArray *allEvents; + iCalEvent *event; + NSUInteger i; + BOOL modified; + + calendar = [iCalCalendar parseSingleFromSource: [rq contentAsString]]; + allEvents = [calendar events]; + modified = NO; + + for (i = 0; i < [allEvents count]; i++) + { + event = [allEvents objectAtIndex: i]; + + if (![event hasEndDate] && ![event hasDuration]) + { + // No end date, no duration + if ([event isAllDay]) + [event setDuration: @"P1D"]; + else + [event setDuration: @"PT1H"]; + + modified = YES; + [self errorWithFormat: @"Invalid event: no end date; setting duration to %@", [event duration]]; + } + } + + if (modified) + [rq setContent: [[calendar versitString] dataUsingEncoding: [rq contentEncoding]]]; +} + - (void) _decomposeGroupsInRequest: (WORequest *) rq { iCalCalendar *calendar; @@ -1471,6 +1509,8 @@ { [self _adjustTransparencyInRequest: rq]; } + + [self _adjustEventsInRequest: rq]; } // diff --git a/SoObjects/Appointments/iCalEvent+SOGo.h b/SoObjects/Appointments/iCalEvent+SOGo.h index d7e970b5d..9d2ee9dd4 100644 --- a/SoObjects/Appointments/iCalEvent+SOGo.h +++ b/SoObjects/Appointments/iCalEvent+SOGo.h @@ -31,6 +31,7 @@ @interface iCalEvent (SOGoExtensions) - (BOOL) isStillRelevant; +- (unsigned int) occurenceInterval; - (NSMutableDictionary *) quickRecord; - (void) updateRecurrenceRulesUntilDate: (NSCalendarDate *) previousEndDate; diff --git a/SoObjects/Appointments/iCalEvent+SOGo.m b/SoObjects/Appointments/iCalEvent+SOGo.m index a645afc6a..089592dba 100644 --- a/SoObjects/Appointments/iCalEvent+SOGo.m +++ b/SoObjects/Appointments/iCalEvent+SOGo.m @@ -272,14 +272,22 @@ */ - (NGCalendarDateRange *) firstOccurenceRange { - iCalDateTime *firstStartDate, *firstEndDate; + iCalDateTime *firstStartDate; + NSCalendarDate *start, *end; NGCalendarDateRange *firstRange; - firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"]; - firstEndDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtend"]; - firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: [[[firstStartDate values] lastObject] asCalendarDate] - endDate: [[[firstEndDate values] lastObject] asCalendarDate]]; + firstRange = nil; + firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"]; + if ([[firstStartDate values] count] > 0) + { + start = [[[firstStartDate values] lastObject] asCalendarDate]; + end = [start addTimeInterval: [self occurenceInterval]]; + + firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: start + endDate: end]; + } + return firstRange; } From 628af06e473c1a458de998fd8119ea84d20b6d68 Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Tue, 19 Apr 2011 13:12:04 +0000 Subject: [PATCH 3/8] Removed useless log call Monotone-Parent: 40362052f51195c01351fb098d0a2d6936db5292 Monotone-Revision: c1c73961c8d9bbf5383d28788200bf3cbbac4e55 Monotone-Author: ludovic@Sophos.ca Monotone-Date: 2011-04-19T13:12:04 Monotone-Branch: ca.inverse.sogo --- SoObjects/SOGo/LDAPSource.m | 1 - 1 file changed, 1 deletion(-) diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index 9bb2d4dcb..b1c13c4dd 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -178,7 +178,6 @@ static NSArray *commonSearchFields; - (void) dealloc { - NSLog(@"LDAPSource: -dealloc"); [bindDN release]; [hostname release]; [encryption release]; From ad9d7bc04b6f1cad3164c4a58d48ad751b5c61ae Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 19 Apr 2011 13:37:09 +0000 Subject: [PATCH 4/8] Improved RPM spec file. Monotone-Parent: 12a15fd8afcf3963e3ec84c6a630972534773465 Monotone-Revision: 3a01f867447b17374f553706956b1711bb6d715e Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-19T13:37:09 Monotone-Branch: ca.inverse.sogo --- sogo.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sogo.spec b/sogo.spec index d05fe9dcd..9b11bab51 100644 --- a/sogo.spec +++ b/sogo.spec @@ -195,8 +195,8 @@ rm -fr ${RPM_BUILD_ROOT} %{prefix}/Library/OCSTypeModels/contact-oracle.ocs %{prefix}/Library/WOxElemBuilders-%{sope_version}/SOGoElements.wox -%config %{_sysconfdir}/httpd/conf.d/SOGo.conf -%config %{_sysconfdir}/sysconfig/sogo +%config(noreplace) %{_sysconfdir}/httpd/conf.d/SOGo.conf +%config(noreplace) %{_sysconfdir}/sysconfig/sogo %doc ChangeLog NEWS Scripts/sql-update-20070724.sh Scripts/sql-update-20070822.sh Scripts/sql-update-20080303.sh Scripts/sql-update-101_to_102.sh Scripts/sql-update-1.2.2_to_1.3.0.sh Scripts/sql-update-1.2.2_to_1.3.0-mysql.sh Scripts/sql-update-1.3.3_to_1.3.4.sh Scripts/sql-update-1.3.3_to_1.3.4-mysql.sh %files -n sogo-tool From c259f618e26b2f5e2d74393a9f78594f82282217 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 19 Apr 2011 14:23:52 +0000 Subject: [PATCH 5/8] Fix for bug #1250 Monotone-Parent: 3a01f867447b17374f553706956b1711bb6d715e Monotone-Revision: 9649af47ac1814f0a873960b05bd95c5d93ec65f Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-19T14:23:52 Monotone-Branch: ca.inverse.sogo --- UI/WebServerResources/SOGoTabsController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UI/WebServerResources/SOGoTabsController.js b/UI/WebServerResources/SOGoTabsController.js index 033af9f70..e32d85cff 100644 --- a/UI/WebServerResources/SOGoTabsController.js +++ b/UI/WebServerResources/SOGoTabsController.js @@ -141,7 +141,7 @@ SOGoTabsController.prototype = { this.activeTab = $(clickedTab); this.activeTab.addClassName("active"); // current LI content.addClassName("active"); - event.stop(); + // Prototype alternative //oldContent.removeClassName("active"); From 67472f93a1a6e79d0609e37247ff2826c9ac0bdf Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 19 Apr 2011 14:25:53 +0000 Subject: [PATCH 6/8] JavaScript fix for IE Monotone-Parent: 9649af47ac1814f0a873960b05bd95c5d93ec65f Monotone-Revision: 40362052f51195c01351fb098d0a2d6936db5292 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-19T14:25:53 Monotone-Branch: ca.inverse.sogo --- UI/WebServerResources/ContactsUI.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UI/WebServerResources/ContactsUI.js b/UI/WebServerResources/ContactsUI.js index 8f600b8ec..c95b6b38d 100644 --- a/UI/WebServerResources/ContactsUI.js +++ b/UI/WebServerResources/ContactsUI.js @@ -1295,7 +1295,7 @@ function initContacts(event) { if (table) { // Initialize event delegation on contacts table table.multiselect = true; - var tbody = table.tBodies[0]; + var tbody = $(table.tBodies[0]); tbody.on("mousedown", onContactSelectionChange); tbody.on("dblclick", onContactRowDblClick); tbody.on("selectstart", listRowMouseDownHandler); From d3a9c2af9bc737c9d625b206058b3aa7af5812fd Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 19 Apr 2011 19:06:35 +0000 Subject: [PATCH 7/8] Monotone-Parent: 40362052f51195c01351fb098d0a2d6936db5292 Monotone-Revision: 2c09693bb8c946283a7305ff62458c9930fc8a9c Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-19T19:06:35 Monotone-Branch: ca.inverse.sogo --- .../Appointments/iCalRepeatableEntityObject+SOGo.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m index 577cc8354..00276a1d6 100644 --- a/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalRepeatableEntityObject+SOGo.m @@ -131,8 +131,8 @@ firstRange = [self firstOccurenceRange]; // Set the range to check with respect to the event timezone (extracted from the start date) - firstStartDate = (iCalDateTime*) [self uniqueChildWithTag: @"dtstart"]; - eventTimeZone = [(iCalDateTime*) firstStartDate timeZone]; + firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"]; + eventTimeZone = [(iCalDateTime *)firstStartDate timeZone]; if (eventTimeZone) startDate = [eventTimeZone computedDateForDate: theOccurenceDate]; else @@ -144,12 +144,12 @@ // to the occurence's timezone. timeZone = [theOccurenceDate timeZone]; offset = [timeZone secondsFromGMTForDate: [firstRange startDate]]; - firstStartDate = (NSCalendarDate*) [[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + firstStartDate = (NSCalendarDate *)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-offset]; - firstEndDate = (NSCalendarDate*) [[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + firstEndDate = (NSCalendarDate *)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-offset]; - [(NSCalendarDate*) firstStartDate setTimeZone: timeZone]; - [(NSCalendarDate*) firstEndDate setTimeZone: timeZone]; + [(NSCalendarDate *)firstStartDate setTimeZone: timeZone]; + [(NSCalendarDate *)firstEndDate setTimeZone: timeZone]; firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate endDate: firstEndDate]; } From 5e466cf968666cfd4d1d83386ec29c031412da37 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 19 Apr 2011 20:39:12 +0000 Subject: [PATCH 8/8] See ChangeLog. Monotone-Parent: 6f81ff5c61f2abaad8d6b69b657abb61e52df9b9 Monotone-Revision: c4b00c603f23bbc97a3d07724c6b2a4e9361c098 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-04-19T20:39:12 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 6 ++++++ .../Appointments/SOGoAppointmentFolder.m | 20 +++++++++---------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a5490181..df803a8e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-04-19 Francis Lachapelle + + * SoObjects/Appointments/SOGoAppointmentFolder.m + (-_flattenCycleRecord:forRange:intoArray:): fixed the + verification of the event's timezone. + 2011-04-15 Francis Lachapelle * SoObjects/Appointments/iCalEvent+SOGo.m (-firstOccurenceRange): diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 2419a203b..78117c7ac 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -850,8 +850,8 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir NSArray *rules, *exRules, *exDates, *ranges; NSArray *elements, *components; NSString *content; - id firstStartDate, firstEndDate; - NSCalendarDate *checkStartDate, *checkEndDate; + iCalDateTime *dtstart; + NSCalendarDate *checkStartDate, *checkEndDate, *firstStartDate, *firstEndDate; iCalEvent *component; iCalTimeZone *eventTimeZone; unsigned count, max, offset; @@ -890,14 +890,14 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir { // Retrieve the range of the first/master event component = [components objectAtIndex: 0]; - firstStartDate = [component uniqueChildWithTag: @"dtstart"]; - firstStartDate = [[[firstStartDate values] lastObject] asCalendarDate]; + dtstart = (iCalDateTime *)[component uniqueChildWithTag: @"dtstart"]; + firstStartDate = [[[dtstart values] lastObject] asCalendarDate]; firstEndDate = [firstStartDate addTimeInterval: [component occurenceInterval]]; firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate endDate: firstEndDate]; - - eventTimeZone = [(iCalDateTime*)firstStartDate timeZone]; + + eventTimeZone = [dtstart timeZone]; if (eventTimeZone) { // Adjust the range to check with respect to the event timezone (extracted from the start date) @@ -921,10 +921,10 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir // The event lasts all-day and has no timezone (floating); we convert the range of the first event // to the user's timezone offset = [timeZone secondsFromGMTForDate: [firstRange startDate]]; - firstStartDate = (NSCalendarDate*)[[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; - firstEndDate = (NSCalendarDate*)[[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; + firstStartDate = [[firstRange startDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + seconds:-offset]; + firstEndDate = [[firstRange endDate] dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + seconds:-offset]; [firstStartDate setTimeZone: timeZone]; [firstEndDate setTimeZone: timeZone]; firstRange = [NGCalendarDateRange calendarDateRangeWithStartDate: firstStartDate