Merge pull request #101 from Zentyal/ejhernandez/recurrence-exceptions-fixes
Two fixes on recurring events
This commit is contained in:
commit
b0ba6f4a22
2
NEWS
2
NEWS
|
@ -5,6 +5,8 @@ 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
|
||||||
|
- Weekly recurring events created in SOGo web interface are now shown in Outlook
|
||||||
|
- 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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -312,15 +325,25 @@
|
||||||
rp->RecurFrequency = RecurFrequency_Weekly;
|
rp->RecurFrequency = RecurFrequency_Weekly;
|
||||||
rp->PatternType = PatternType_Week;
|
rp->PatternType = PatternType_Week;
|
||||||
rp->Period = repeatInterval;
|
rp->Period = repeatInterval;
|
||||||
|
|
||||||
|
dayOfWeek = [startDate dayOfWeek];
|
||||||
|
|
||||||
mask = 0;
|
mask = 0;
|
||||||
byDayMask = [self byDayMask];
|
byDayMask = [self byDayMask];
|
||||||
for (count = 0; count < 7; count++)
|
if (byDayMask)
|
||||||
if ([byDayMask occursOnDay: count])
|
{
|
||||||
mask |= 1 << count;
|
for (count = 0; count < 7; count++)
|
||||||
|
if ([byDayMask occursOnDay: count])
|
||||||
|
mask |= 1 << count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the recurrence pattern using start date */
|
||||||
|
mask |= 1 << dayOfWeek;
|
||||||
|
}
|
||||||
rp->PatternTypeSpecific.WeekRecurrencePattern = mask;
|
rp->PatternTypeSpecific.WeekRecurrencePattern = mask;
|
||||||
|
|
||||||
/* FirstDateTime */
|
/* FirstDateTime */
|
||||||
dayOfWeek = [startDate dayOfWeek];
|
|
||||||
if (dayOfWeek)
|
if (dayOfWeek)
|
||||||
beginOfWeek = [startDate dateByAddingYears: 0 months: 0
|
beginOfWeek = [startDate dateByAddingYears: 0 months: 0
|
||||||
days: -dayOfWeek
|
days: -dayOfWeek
|
||||||
|
|
|
@ -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];
|
||||||
|
|
Loading…
Reference in a new issue