diff --git a/ActiveSync/GNUmakefile b/ActiveSync/GNUmakefile index 65d91f338..2ea1c36fe 100644 --- a/ActiveSync/GNUmakefile +++ b/ActiveSync/GNUmakefile @@ -10,6 +10,7 @@ ActiveSync_PRINCIPAL_CLASS = ActiveSyncProduct ActiveSync_OBJC_FILES = \ ActiveSyncProduct.m \ iCalEvent+ActiveSync.m \ + iCalRecurrenceRule+ActiveSync.m \ iCalTimeZone+ActiveSync.m \ iCalToDo+ActiveSync.m \ NSCalendarDate+ActiveSync.m \ diff --git a/ActiveSync/iCalEvent+ActiveSync.m b/ActiveSync/iCalEvent+ActiveSync.m index 251158c1c..66ec0b770 100644 --- a/ActiveSync/iCalEvent+ActiveSync.m +++ b/ActiveSync/iCalEvent+ActiveSync.m @@ -43,6 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import #import +#include "iCalRecurrenceRule+ActiveSync.h" #include "iCalTimeZone+ActiveSync.h" #include "NSDate+ActiveSync.h" #include "NSString+ActiveSync.h" @@ -173,6 +174,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Reminder -- http://msdn.microsoft.com/en-us/library/ee219691(v=exchg.80).aspx // TODO + // Recurrence rules + if ([self isRecurrent]) + { + [s appendString: [[[self recurrenceRules] lastObject] activeSyncRepresentation]]; + } + // Comment o = [self comment]; if ([o length]) @@ -312,6 +319,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [end setDateTime: o]; } } + + // Recurrence + if ((o = [theValues objectForKey: @"Recurrence"])) + { + iCalRecurrenceRule *rule; + + rule = [[iCalRecurrenceRule alloc] init]; + [self setRecurrenceRules: [NSArray arrayWithObject: rule]]; + RELEASE(rule); + + [rule takeActiveSyncValues: o]; + } } @end diff --git a/ActiveSync/iCalRecurrenceRule+ActiveSync.h b/ActiveSync/iCalRecurrenceRule+ActiveSync.h new file mode 100644 index 000000000..ab19964ac --- /dev/null +++ b/ActiveSync/iCalRecurrenceRule+ActiveSync.h @@ -0,0 +1,46 @@ +/* + +Copyright (c) 2014, Inverse inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Inverse inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __ICALRECURRENCERULEACTIVESYNC_H__ +#define __ICALRECURRENCERULEACTIVESYNC_H__ + +#import + +@class NSDictionary; +@class NSString; + +@interface iCalRecurrenceRule (ActiveSync) + +- (NSString *) activeSyncRepresentation; +- (void) takeActiveSyncValues: (NSDictionary *) theValues; + +@end + +#endif diff --git a/ActiveSync/iCalRecurrenceRule+ActiveSync.m b/ActiveSync/iCalRecurrenceRule+ActiveSync.m new file mode 100644 index 000000000..703f262b7 --- /dev/null +++ b/ActiveSync/iCalRecurrenceRule+ActiveSync.m @@ -0,0 +1,239 @@ +/* + +Copyright (c) 2014, Inverse inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Inverse inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#import "iCalRecurrenceRule+ActiveSync.h" + +#import +#import +#import + +#import + +#import "NSCalendarDate+ActiveSync.h" +#import "NSDate+ActiveSync.h" + +@implementation iCalRecurrenceRule (ActiveSync) + +- (NSString *) activeSyncRepresentation +{ + NSMutableString *s; + int type; + + s = [NSMutableString string]; + + [s appendString: @""]; + + // 0 -> daily, 1 -> weekly, 2 -> montly, 5 -> yearly + type = 0; + + if ([self frequency] == iCalRecurrenceFrequenceDaily) + { + type = 0; + + // 1 -> sunday, 2 -> monday, 4 -> tuesday, 8 -> wednesday, 16 -> thursday, 32 -> friday, 64 -> saturday, 127 -> last day of month (montly or yearl recurrences only) + if ([[self byDayMask] isWeekDays]) + { + [s appendFormat: @"%d", (2|4|8|16|32)]; + } + else + { + [s appendFormat: @"%d", [self repeatInterval]]; + } + } + else if ([self frequency] == iCalRecurrenceFrequenceWeekly) + { + iCalWeekOccurrence *occurrences; + int i, v; + + type = 1; + + occurrences = [[self byDayMask] weekDayOccurrences]; + v = 0; + + for (i = 0; i < 7; i++) + { + if (occurrences[i]) + v += (1 << i); + } + + [s appendFormat: @"%d", v]; + [s appendFormat: @"%d", [self repeatInterval]]; + } + else if ([self frequency] == iCalRecurrenceFrequenceMonthly) + { + if ([[self byDay] length]) + { + int firstOccurrence; + iCalByDayMask *dm; + + type = 3; // recurs monthly on the nth day + dm = [self byDayMask]; + firstOccurrence = [dayMask firstOccurrence]; + + // Handle the case for "Last day of the month" + if (firstOccurrence < 0) + firstOccurrence = 5; + + [s appendFormat: @"%d", (1 << [dm firstDay])]; + [s appendFormat: @"%d", firstOccurrence]; + } + else if ([[self byMonthDay] count]) + { + NSArray *days; + + type = 2; // recurs monthly + days = [self byMonthDay]; + if ([days count] > 0 && [[days objectAtIndex: 0] intValue] < 0) + { + // Last day of the month + iCalByDayMask *dm; + + dm = [self byDayMask]; + [s appendFormat: @"%d", (1 << [dm firstDay])]; + [s appendFormat: @"%d", 5]; + } + else + { + // Unsupported rule in ActiveSync/Outlook. Rule that says "Repeat on the 7th and 8th of each month". + // FIXME + } + } + } + else if ([self frequency] == iCalRecurrenceFrequenceYearly) + { + type = 6; // Yearly on the nth day + + if ([[self flattenedValuesForKey: @"bymonth"] length]) + { + if ([[self byDay] length]) + { + int firstOccurrence; + iCalByDayMask *dm; + + dm = [self byDayMask]; + firstOccurrence = [dm firstOccurrence]; + if (firstOccurrence < 0) + firstOccurrence = 5; + + [s appendFormat: @"%d", (1 << [dm firstDay])]; + [s appendFormat: @"%d", firstOccurrence]; + [s appendFormat: @"%@", + [self flattenedValuesForKey: @"bymonth"]]; + } + else + { + type = 5; // Yearly + + [s appendFormat: @"%@", + [self flattenedValuesForKey: @"bymonthday"]]; + + [s appendFormat: @"%@", + [self flattenedValuesForKey: @"bymonth"]]; + } + } + else + type = 5; + } + + [s appendFormat: @"%d", type]; + + // Occurrences / Until + //[s appendFormat: @"%d", 5]; + if ([self repeatCount]) + { + [s appendFormat: @"%@", + [self flattenedValuesForKey: @"count"]]; + } + else if ([self untilDate]) + { + NSCalendarDate *date; + + date = [self untilDate]; + //ud = [[context activeUser] userDefaults]; + //[date setTimeZone: [ud timeZone]]; + + [s appendFormat: @"%@", + [date activeSyncRepresentationWithoutSeparators]]; + } + + + [s appendString: @""]; + + return s; +} + +// +// +// +- (void) takeActiveSyncValues: (NSDictionary *) theValues +{ + id o; + + int recurrenceType; + + recurrenceType = [[theValues objectForKey: @"Recurrence_Type"] intValue]; + + [self setInterval: @"1"]; + + switch (recurrenceType) + { + // Daily + case 0: + [self setFrequency: iCalRecurrenceFrequenceDaily]; + if ((o = [theValues objectForKey: @"Recurrence_Interval"])) + { + [self setRepeatInterval: [o intValue]]; + } + break; + // Weekly + case 1: + break; + // Montly + case 2: + case 3: + break; + // Yearly + case 5: + case 6: + default: + break; + } + + if ((o = [theValues objectForKey: @"Recurrence_Occurrences"])) + { + [self setRepeatCount: [o intValue]]; + } + else if ((o = [theValues objectForKey: @"Recurrence_Until"])) + { + [self setUntilDate: [o calendarDate]]; + } +} + +@end