oc-calendar: Fix import in SOGo exceptions from recurring series

According to [MS-OXICAL] Section 2.1.3.1.1.20.13, the EXDATE property
must be written only if there are ocurrences from the series that have
been deleted and before this commit ModifiedInstanceDates were also
included.

We check against every ExceptionInfo from exception ocurrences of the series
to know if the ocurrence was deleted or only modified.
pull/65/head
Enrique J. Hernández Blasco 2015-03-06 13:23:17 +01:00 committed by Julio García
parent 3b0b43f28f
commit 6f44ec42c1
4 changed files with 53 additions and 30 deletions

1
NEWS
View File

@ -5,6 +5,7 @@ Enhancements
- Improve sync speed from Outlook by non-reprocessing already downloaded unread mails - Improve sync speed from Outlook by non-reprocessing already downloaded unread mails
Bug fixes Bug fixes
- Fix exception modifications import in recurrence series
- Sent mails are not longer in Drafts folder using Outlook - Sent mails are not longer in Drafts folder using Outlook
- Fix server side crash parsing rtf emails with images (with word97 format) - Fix server side crash parsing rtf emails with images (with word97 format)

View File

@ -25,6 +25,8 @@
#include <talloc.h> #include <talloc.h>
#import <Foundation/NSTimeZone.h>
#import <NGCards/iCalCalendar.h> #import <NGCards/iCalCalendar.h>
#import <NGCards/iCalRecurrenceRule.h> #import <NGCards/iCalRecurrenceRule.h>
@ -41,7 +43,10 @@
@interface iCalCalendar (MAPIStoreRecurrence) @interface iCalCalendar (MAPIStoreRecurrence)
- (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity - (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity
fromRecurrencePattern: (struct RecurrencePattern *) rp; fromRecurrencePattern: (struct RecurrencePattern *) rp
withExceptions: (struct ExceptionInfo *) exInfos
andExceptionCount: (uint16_t) exInfoCount
inTimeZone: (NSTimeZone *) tz;
@end @end

View File

@ -24,6 +24,7 @@
#import <Foundation/NSCalendarDate.h> #import <Foundation/NSCalendarDate.h>
#import <Foundation/NSSet.h> #import <Foundation/NSSet.h>
#import <Foundation/NSString.h> #import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSCalendarDate+misc.h> #import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
@ -48,6 +49,10 @@
- (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity - (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity
fromRecurrencePattern: (struct RecurrencePattern *) rp fromRecurrencePattern: (struct RecurrencePattern *) rp
withExceptions: (struct ExceptionInfo *) exInfos
andExceptionCount: (uint16_t) exInfoCount
inTimeZone: (NSTimeZone *) tz
{ {
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate; NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
NSString *monthDay, *month; NSString *monthDay, *month;
@ -214,34 +219,42 @@
/* exception dates: /* exception dates:
- take all deleted instances - take all deleted instances
- remove all modified instances from the above set - remove all modified instances available in ExceptionInfo from the above set
- add remaining instances, in chronological order - add remaining instances, in chronological order
*/ */
exceptionDates = [NSMutableSet set];
for (count = 0; count < rp->DeletedInstanceCount; count++)
{
exDate
= [NSDate dateFromMinutesSince1601: rp->DeletedInstanceDates[count]];
exDate = [exDate hour: [startDate hourOfDay]
minute: [startDate minuteOfHour]
second: [startDate secondOfMinute]];
[exceptionDates addObject: exDate];
}
for (count = 0; count < rp->ModifiedInstanceCount; count++)
{
exDate
= [NSDate dateFromMinutesSince1601: rp->ModifiedInstanceDates[count]];
exDate = [exDate hour: [startDate hourOfDay]
minute: [startDate minuteOfHour]
second: [startDate secondOfMinute]];
[exceptionDates removeObject: exDate];
}
realExDates = [[exceptionDates allObjects] /* Heuristic to avoid these loops */
sortedArrayUsingSelector: @selector (compare:)]; if (rp->DeletedInstanceCount != rp->ModifiedInstanceCount) {
max = [realExDates count]; exceptionDates = [NSMutableSet set];
for (count = 0; count < max; count++) for (count = 0; count < rp->DeletedInstanceCount; count++)
[entity addToExceptionDates: [realExDates objectAtIndex: count]]; {
exDate
= [NSDate dateFromMinutesSince1601: rp->DeletedInstanceDates[count]];
exDate = [exDate hour: [startDate hourOfDay]
minute: [startDate minuteOfHour]
second: [startDate secondOfMinute]];
[exceptionDates addObject: exDate];
}
/* Read the exceptions to remove the instances that are modified and not deleted */
if (exInfos && exInfoCount > 0)
{
for (count = 0; count < exInfoCount; count++)
{
/* The OriginalStartDate is in local time */
exDate = [NSDate dateFromMinutesSince1601: exInfos[count].OriginalStartDate];
exDate = [exDate dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: - [tz secondsFromGMT]];
[exceptionDates removeObject: exDate];
}
}
realExDates = [[exceptionDates allObjects]
sortedArrayUsingSelector: @selector (compare:)];
max = [realExDates count];
for (count = 0; count < max; count++)
[entity addToExceptionDates: [realExDates objectAtIndex: count]];
}
} }
@end @end

View File

@ -74,6 +74,7 @@
@implementation iCalEvent (MAPIStoreProperties) @implementation iCalEvent (MAPIStoreProperties)
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData - (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
inTimeZone: (NSTimeZone *) tz
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
struct Binary_r *blob; struct Binary_r *blob;
@ -87,9 +88,12 @@
return; return;
} }
[(iCalCalendar *) parent [(iCalCalendar *) parent setupRecurrenceWithMasterEntity: self
setupRecurrenceWithMasterEntity: self fromRecurrencePattern: &pattern->RecurrencePattern
fromRecurrencePattern: &pattern->RecurrencePattern]; withExceptions: pattern->ExceptionInfo
andExceptionCount: pattern->ExceptionCount
inTimeZone: tz
];
//talloc_free (blob); //talloc_free (blob);
} }
@ -362,7 +366,7 @@
value = [properties value = [properties
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)]; objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
if (value) if (value)
[self _setupEventRecurrence: value inMemCtx: memCtx]; [self _setupEventRecurrence: value inTimeZone: userTimeZone inMemCtx: memCtx];
/* alarm */ /* alarm */
[self _setupEventAlarmFromProperties: properties]; [self _setupEventAlarmFromProperties: properties];