mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-02-17 07:33:57 +00:00
fix(calendar): deleted occurence of repeated event could cause some troubles with other imrbicated occurences
The fix is within SOPE/NGCards/iCalRecurrenceCalculator.m:244, the others files are juste modified to make the code more readable
This commit is contained in:
@@ -159,28 +159,28 @@ static NGCardsSaxHandler *sax = nil;
|
||||
CardElement *newChild;
|
||||
|
||||
if (aChild)
|
||||
{
|
||||
childTag = [aChild tag];
|
||||
newChild = nil;
|
||||
mappedClass = [self classForTag: [childTag uppercaseString]];
|
||||
if (mappedClass)
|
||||
{
|
||||
if (![aChild isKindOfClass: mappedClass])
|
||||
{
|
||||
childTag = [aChild tag];
|
||||
newChild = nil;
|
||||
mappedClass = [self classForTag: [childTag uppercaseString]];
|
||||
if (mappedClass)
|
||||
{
|
||||
if (![aChild isKindOfClass: mappedClass])
|
||||
{
|
||||
//NSLog (@"warning: new child to entity '%@': '%@' converted to '%@'",
|
||||
// tag, childTag, NSStringFromClass(mappedClass));
|
||||
newChild = [aChild elementWithClass: mappedClass];
|
||||
}
|
||||
}
|
||||
}
|
||||
// else
|
||||
// NSLog (@"warning: no mapped class for tag '%@'",
|
||||
// childTag);
|
||||
|
||||
if (!newChild)
|
||||
newChild = aChild;
|
||||
[children addObject: newChild];
|
||||
[newChild setParent: self];
|
||||
}
|
||||
if (!newChild)
|
||||
newChild = aChild;
|
||||
[children addObject: newChild];
|
||||
[newChild setParent: self];
|
||||
}
|
||||
}
|
||||
|
||||
- (CardElement *) uniqueChildWithTag: (NSString *) aTag
|
||||
|
||||
@@ -235,19 +235,18 @@ static Class yearlyCalcClass = Nil;
|
||||
|
||||
dates = [[self _dates: exdates withinRange: limits startingWithDate: first] objectEnumerator];
|
||||
while ((currentDate = [dates nextObject]))
|
||||
{
|
||||
maxRanges = [ranges count];
|
||||
for (count = maxRanges; count > 0; count--)
|
||||
{
|
||||
currentRange = [ranges objectAtIndex: count - 1];
|
||||
compare = [[currentRange startDate] compare: currentDate];
|
||||
if ((compare == NSOrderedAscending || compare == NSOrderedSame) &&
|
||||
[[currentRange endDate] compare: currentDate] == NSOrderedDescending)
|
||||
{
|
||||
[ranges removeObjectAtIndex: count - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
maxRanges = [ranges count];
|
||||
for (count = maxRanges; count > 0; count--)
|
||||
{
|
||||
currentRange = [ranges objectAtIndex: count - 1];
|
||||
compare = [[currentRange startDate] compare: currentDate];
|
||||
if ( compare == NSOrderedSame)
|
||||
{
|
||||
[ranges removeObjectAtIndex: count - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSArray *)
|
||||
@@ -255,7 +254,7 @@ static Class yearlyCalcClass = Nil;
|
||||
firstInstanceCalendarDateRange: (NGCalendarDateRange *) _fir
|
||||
recurrenceRules: (NSArray *) _rRules
|
||||
exceptionRules: (NSArray *) _exRules
|
||||
recurrenceDates: (NSArray *) _rDates
|
||||
recurrenceDates: (NSArray *) _rDates
|
||||
exceptionDates: (NSArray *) _exDates
|
||||
{
|
||||
NSMutableArray *ranges;
|
||||
@@ -264,14 +263,10 @@ static Class yearlyCalcClass = Nil;
|
||||
|
||||
if ([_rRules count] > 0 || [_rDates count] > 0)
|
||||
{
|
||||
[self _fillRanges: ranges fromRules: _rRules
|
||||
withinRange: _r startingWithDate: _fir];
|
||||
[self _fillRanges: ranges fromDates: _rDates
|
||||
withinRange: _r startingWithDate: _fir];
|
||||
[self _removeExceptionsFromRanges: ranges withRules: _exRules
|
||||
withinRange: _r startingWithDate: _fir];
|
||||
[self _removeExceptionDatesFromRanges: ranges withDates: _exDates
|
||||
withinRange: _r startingWithDate: _fir];
|
||||
[self _fillRanges: ranges fromRules: _rRules withinRange: _r startingWithDate: _fir];
|
||||
[self _fillRanges: ranges fromDates: _rDates withinRange: _r startingWithDate: _fir];
|
||||
[self _removeExceptionsFromRanges: ranges withRules: _exRules withinRange: _r startingWithDate: _fir];
|
||||
[self _removeExceptionDatesFromRanges: ranges withDates: _exDates withinRange: _r startingWithDate: _fir];
|
||||
}
|
||||
|
||||
return ranges;
|
||||
|
||||
@@ -105,21 +105,21 @@
|
||||
interval = [[master endDate]
|
||||
timeIntervalSinceDate: firstDate];
|
||||
if ([newOccurence isAllDay])
|
||||
{
|
||||
nbrDays = ((float) abs (interval) / 86400);
|
||||
[newOccurence setAllDayWithStartDate: date
|
||||
{
|
||||
nbrDays = ((float) abs (interval) / 86400);
|
||||
[newOccurence setAllDayWithStartDate: date
|
||||
duration: nbrDays];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[newOccurence setStartDate: date];
|
||||
[newOccurence setEndDate: [date addYear: 0
|
||||
month: 0
|
||||
day: 0
|
||||
hour: 0
|
||||
minute: 0
|
||||
second: interval]];
|
||||
}
|
||||
{
|
||||
[newOccurence setStartDate: date];
|
||||
[newOccurence setEndDate: [date addYear: 0
|
||||
month: 0
|
||||
day: 0
|
||||
hour: 0
|
||||
minute: 0
|
||||
second: interval]];
|
||||
}
|
||||
|
||||
return newOccurence;
|
||||
}
|
||||
|
||||
@@ -391,28 +391,28 @@
|
||||
inContext: localContext
|
||||
acquire: acquire];
|
||||
if (!obj)
|
||||
{
|
||||
if ([lookupName isEqualToString: @"master"])
|
||||
obj = [self occurence: [self component: NO secure: NO]];
|
||||
else if ([lookupName hasPrefix: @"occurence"])
|
||||
{
|
||||
recID = [lookupName substringFromIndex: 9];
|
||||
occurence = [self lookupOccurrence: recID];
|
||||
if (occurence)
|
||||
isNewOccurence = NO;
|
||||
else
|
||||
{
|
||||
if ([lookupName isEqualToString: @"master"])
|
||||
obj = [self occurence: [self component: NO secure: NO]];
|
||||
else if ([lookupName hasPrefix: @"occurence"])
|
||||
{
|
||||
recID = [lookupName substringFromIndex: 9];
|
||||
occurence = [self lookupOccurrence: recID];
|
||||
if (occurence)
|
||||
isNewOccurence = NO;
|
||||
else
|
||||
{
|
||||
occurence = [self newOccurenceWithID: recID];
|
||||
isNewOccurence = YES;
|
||||
}
|
||||
if (occurence)
|
||||
if (occurence)
|
||||
{
|
||||
obj = [self occurence: occurence];
|
||||
if (isNewOccurence)
|
||||
[obj setIsNew: isNewOccurence];
|
||||
[obj setIsNew: isNewOccurence];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -470,36 +470,33 @@
|
||||
calendar = &fullCalendar;
|
||||
|
||||
if (!*calendar)
|
||||
{
|
||||
if (secure)
|
||||
iCalString = [self secureContentAsString];
|
||||
else
|
||||
iCalString = content;
|
||||
{
|
||||
if (secure)
|
||||
iCalString = [self secureContentAsString];
|
||||
else
|
||||
iCalString = content;
|
||||
|
||||
if ([iCalString length] > 0)
|
||||
{
|
||||
ASSIGN (*calendar, [iCalCalendar parseSingleFromSource: iCalString]);
|
||||
if (!secure)
|
||||
originalCalendar = [*calendar copy];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
ASSIGN (*calendar, [iCalCalendar groupWithTag: @"vcalendar"]);
|
||||
[*calendar setVersion: @"2.0"];
|
||||
prodID = [NSString stringWithFormat:
|
||||
@"-//Inverse inc./SOGo %@//EN",
|
||||
SOGoVersion];
|
||||
[*calendar setProdID: prodID];
|
||||
tag = [[self componentTag] uppercaseString];
|
||||
newComponent = [[*calendar classForTag: tag]
|
||||
groupWithTag: tag];
|
||||
[newComponent setUid: [self globallyUniqueObjectId]];
|
||||
[*calendar addChild: newComponent];
|
||||
}
|
||||
}
|
||||
if ([iCalString length] > 0)
|
||||
{
|
||||
ASSIGN (*calendar, [iCalCalendar parseSingleFromSource: iCalString]);
|
||||
if (!secure)
|
||||
originalCalendar = [*calendar copy];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
ASSIGN (*calendar, [iCalCalendar groupWithTag: @"vcalendar"]);
|
||||
[*calendar setVersion: @"2.0"];
|
||||
prodID = [NSString stringWithFormat:@"-//Inverse inc./SOGo %@//EN", SOGoVersion];
|
||||
[*calendar setProdID: prodID];
|
||||
tag = [[self componentTag] uppercaseString];
|
||||
newComponent = [[*calendar classForTag: tag] groupWithTag: tag];
|
||||
[newComponent setUid: [self globallyUniqueObjectId]];
|
||||
[*calendar addChild: newComponent];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
returnedCopy = [*calendar mutableCopy];
|
||||
[returnedCopy autorelease];
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
id occurrence;
|
||||
iCalRepeatableEntityObject *component;
|
||||
NSUInteger count, max, seconds, recSeconds;
|
||||
NSCalendarDate* recId;
|
||||
|
||||
occurrence = nil;
|
||||
|
||||
@@ -50,26 +51,27 @@
|
||||
component = [components objectAtIndex: 0];
|
||||
|
||||
if ([component isRecurrent] || [component recurrenceId])
|
||||
{
|
||||
// Skip the master event if required
|
||||
count = ([component recurrenceId] ? 0 : 1);
|
||||
while (!occurrence && count < max)
|
||||
{
|
||||
component = [components objectAtIndex: count];
|
||||
recSeconds = [[component recurrenceId] timeIntervalSince1970];
|
||||
if (recSeconds == seconds)
|
||||
occurrence = component;
|
||||
else
|
||||
count++;
|
||||
}
|
||||
}
|
||||
{
|
||||
// Skip the master event if required
|
||||
recId = [component recurrenceId];
|
||||
count = (recID ? 0 : 1);
|
||||
while (!occurrence && count < max)
|
||||
{
|
||||
component = [components objectAtIndex: count];
|
||||
recSeconds = [recId timeIntervalSince1970];
|
||||
if (recSeconds == seconds)
|
||||
occurrence = component;
|
||||
else
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The "master" event could be that occurrence. */
|
||||
recSeconds = [[component recurrenceId] timeIntervalSince1970];
|
||||
if (recSeconds == seconds)
|
||||
occurrence = component;
|
||||
}
|
||||
{
|
||||
/* The "master" event could be that occurrence. */
|
||||
recSeconds = [[component recurrenceId] timeIntervalSince1970];
|
||||
if (recSeconds == seconds)
|
||||
occurrence = component;
|
||||
}
|
||||
|
||||
return occurrence;
|
||||
}
|
||||
|
||||
@@ -408,24 +408,23 @@
|
||||
|
||||
doesOccur = [self isRecurrent];
|
||||
if (doesOccur)
|
||||
{
|
||||
// Retrieve the range of the first event
|
||||
firstRange = [self firstOccurenceRange]; // returns GMT dates
|
||||
{
|
||||
// Retrieve the range of the first event
|
||||
firstRange = [self firstOccurenceRange]; // returns GMT dates
|
||||
|
||||
// Set the range to check with respect to the event timezone (extracted from the start date)
|
||||
firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"];
|
||||
timeZone = [(iCalDateTime *)firstStartDate timeZone];
|
||||
if (timeZone)
|
||||
startDate = [(iCalTimeZone *)timeZone computedDateForDate: theOccurenceDate];
|
||||
else
|
||||
startDate = theOccurenceDate;
|
||||
endDate = [startDate addTimeInterval: [self occurenceInterval]];
|
||||
checkRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate
|
||||
// Set the range to check with respect to the event timezone (extracted from the start date)
|
||||
firstStartDate = (iCalDateTime *)[self uniqueChildWithTag: @"dtstart"];
|
||||
timeZone = [(iCalDateTime *)firstStartDate timeZone];
|
||||
if (timeZone)
|
||||
startDate = [(iCalTimeZone *)timeZone computedDateForDate: theOccurenceDate];
|
||||
else
|
||||
startDate = theOccurenceDate;
|
||||
endDate = [startDate addTimeInterval: [self occurenceInterval]];
|
||||
checkRange = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate
|
||||
endDate: endDate];
|
||||
|
||||
// Calculate the occurrences for the given date
|
||||
ranges =
|
||||
[NSMutableArray arrayWithArray:
|
||||
// Calculate the occurrences for the given date
|
||||
ranges = [NSMutableArray arrayWithArray:
|
||||
[iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: checkRange
|
||||
firstInstanceCalendarDateRange: firstRange
|
||||
recurrenceRules: [self recurrenceRulesWithTimeZone: timeZone]
|
||||
@@ -433,19 +432,18 @@
|
||||
recurrenceDates: [self recurrenceDatesWithTimeZone: timeZone]
|
||||
exceptionDates: [self exceptionDatesWithTimeZone: timeZone]]];
|
||||
|
||||
// Add the master occurrence when dealing with RDATES.
|
||||
// However, the master event must not be flagged with X-MOZ-FAKED-MASTER.
|
||||
if ([self hasRecurrenceDates] &&
|
||||
![[[self uniqueChildWithTag: @"x-moz-faked-master"]
|
||||
flattenedValuesForKey: @""] isEqualToString: @"1"] &&
|
||||
[checkRange doesIntersectWithDateRange: firstRange])
|
||||
{
|
||||
[ranges insertObject: firstRange atIndex: 0];
|
||||
}
|
||||
|
||||
doesOccur = [ranges dateRangeArrayContainsDate: startDate];
|
||||
// Add the master occurrence when dealing with RDATES.
|
||||
// However, the master event must not be flagged with X-MOZ-FAKED-MASTER.
|
||||
if ([self hasRecurrenceDates] &&
|
||||
![[[self uniqueChildWithTag: @"x-moz-faked-master"] flattenedValuesForKey: @""] isEqualToString: @"1"] &&
|
||||
[checkRange doesIntersectWithDateRange: firstRange])
|
||||
{
|
||||
[ranges insertObject: firstRange atIndex: 0];
|
||||
}
|
||||
|
||||
doesOccur = [ranges dateRangeArrayContainsDate: startDate];
|
||||
}
|
||||
|
||||
return doesOccur;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user