2014-01-10 20:12:53 +01:00
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (c) 2014, Inverse inc.
|
|
|
|
All rights reserved.
|
|
|
|
|
2014-01-13 17:46:32 +01:00
|
|
|
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 <COPYRIGHT HOLDER> 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.
|
2014-01-10 20:12:53 +01:00
|
|
|
|
|
|
|
*/
|
2014-01-13 17:46:32 +01:00
|
|
|
|
2014-01-10 20:12:53 +01:00
|
|
|
#import "iCalEvent+ActiveSync.h"
|
|
|
|
|
2014-01-13 22:25:14 +01:00
|
|
|
#import <Foundation/NSArray.h>
|
2014-01-10 22:48:39 +01:00
|
|
|
#import <Foundation/NSCalendarDate.h>
|
|
|
|
#import <Foundation/NSDate.h>
|
2014-01-10 20:12:53 +01:00
|
|
|
#import <Foundation/NSDictionary.h>
|
|
|
|
#import <Foundation/NSString.h>
|
2014-01-10 22:48:39 +01:00
|
|
|
#import <Foundation/NSTimeZone.h>
|
2014-01-10 20:12:53 +01:00
|
|
|
|
2014-01-10 22:48:39 +01:00
|
|
|
#import <NGCards/iCalCalendar.h>
|
2014-01-10 20:12:53 +01:00
|
|
|
#import <NGCards/iCalDateTime.h>
|
2014-01-13 22:25:14 +01:00
|
|
|
#import <NGCards/iCalPerson.h>
|
2014-01-10 20:12:53 +01:00
|
|
|
|
|
|
|
#include "iCalTimeZone+ActiveSync.h"
|
|
|
|
#include "NSDate+ActiveSync.h"
|
|
|
|
#include "NSString+ActiveSync.h"
|
|
|
|
|
|
|
|
@implementation iCalEvent (ActiveSync)
|
|
|
|
|
|
|
|
- (NSString *) activeSyncRepresentation
|
|
|
|
{
|
|
|
|
NSMutableString *s;
|
2014-01-13 22:25:14 +01:00
|
|
|
NSArray *attendees;
|
|
|
|
|
|
|
|
iCalPerson *organizer, *attendee;
|
2014-01-10 20:12:53 +01:00
|
|
|
iCalTimeZone *tz;
|
|
|
|
|
|
|
|
s = [NSMutableString string];
|
|
|
|
|
|
|
|
// DTStamp -- http://msdn.microsoft.com/en-us/library/ee219470(v=exchg.80).aspx
|
|
|
|
if ([self timeStampAsDate])
|
|
|
|
[s appendFormat: @"<DTStamp xmlns=\"Calendar:\">%@</DTStamp>", [[self timeStampAsDate] activeSyncRepresentation]];
|
|
|
|
else if ([self created])
|
|
|
|
[s appendFormat: @"<DTStamp xmlns=\"Calendar:\">%@</DTStamp>", [[self created] activeSyncRepresentation]];
|
|
|
|
|
|
|
|
// StartTime -- http://msdn.microsoft.com/en-us/library/ee157132(v=exchg.80).aspx
|
|
|
|
if ([self startDate])
|
|
|
|
[s appendFormat: @"<StartTime xmlns=\"Calendar:\">%@</StartTime>", [[self startDate] activeSyncRepresentation]];
|
|
|
|
|
|
|
|
// EndTime -- http://msdn.microsoft.com/en-us/library/ee157945(v=exchg.80).aspx
|
|
|
|
if ([self endDate])
|
|
|
|
[s appendFormat: @"<EndTime xmlns=\"Calendar:\">%@</EndTime>", [[self endDate] activeSyncRepresentation]];
|
|
|
|
|
|
|
|
// Timezone
|
|
|
|
tz = [(iCalDateTime *)[self firstChildWithTag: @"dtstart"] timeZone];
|
|
|
|
|
|
|
|
if (!tz)
|
|
|
|
tz = [iCalTimeZone timeZoneForName: @"Europe/London"];
|
|
|
|
|
|
|
|
[s appendFormat: @"<TimeZone xmlns=\"Calendar:\">%@</TimeZone>", [[tz activeSyncRepresentation] stringByReplacingString: @"\n" withString: @""]];;
|
|
|
|
|
2014-01-13 22:25:14 +01:00
|
|
|
// Organizer and attendees
|
|
|
|
if ((organizer = [self organizer]))
|
|
|
|
{
|
|
|
|
[s appendFormat: @"<Organizer_Email xmlns=\"Calendar:\">%@</Organizer_Email>", [organizer rfc822Email]];
|
|
|
|
[s appendFormat: @"<Organizer_Name xmlns=\"Calendar:\">%@</Organizer_Name>", [organizer cn]];
|
|
|
|
}
|
|
|
|
|
|
|
|
attendees = [self attendees];
|
2014-01-10 20:12:53 +01:00
|
|
|
|
2014-01-13 22:25:14 +01:00
|
|
|
if ([attendees count])
|
|
|
|
{
|
|
|
|
int i, attendee_type, attendee_status;
|
|
|
|
|
|
|
|
[s appendString: @"<Attendees xmlns=\"Calendar:\">"];
|
|
|
|
|
|
|
|
for (i = 0; i < [attendees count]; i++)
|
|
|
|
{
|
|
|
|
[s appendString: @"<Attendee xmlns=\"Calendar:\">"];
|
|
|
|
|
|
|
|
attendee = [attendees objectAtIndex: i];
|
|
|
|
[s appendFormat: @"<Attendee_Email xmlns=\"Calendar:\">%@</Attendee_Email>", [attendee rfc822Email]];
|
|
|
|
[s appendFormat: @"<Attendee_Name xmlns=\"Calendar:\">%@</Attendee_Name>", [attendee cn]];
|
|
|
|
|
|
|
|
|
|
|
|
attendee_status = 5;
|
|
|
|
if ([[attendee partStat] caseInsensitiveCompare: @"ACCEPTED"] == NSOrderedSame)
|
|
|
|
attendee_status = 3;
|
|
|
|
else if ([[attendee partStat] caseInsensitiveCompare: @"DECLINED"] == NSOrderedSame)
|
|
|
|
attendee_status = 4;
|
|
|
|
else if ([[attendee partStat] caseInsensitiveCompare: @"TENTATIVE"] == NSOrderedSame)
|
|
|
|
attendee_status = 2;
|
|
|
|
|
|
|
|
[s appendFormat: @"<Attendee_Status xmlns=\"Calendar:\">%d</Attendee_Status>", attendee_status];
|
|
|
|
|
|
|
|
// FIXME: handle resource
|
|
|
|
if ([[attendee role] caseInsensitiveCompare: @"REQ-PARTICIPANT"] == NSOrderedSame)
|
|
|
|
attendee_type = 1;
|
|
|
|
else
|
|
|
|
attendee_type = 2;
|
|
|
|
|
|
|
|
|
|
|
|
[s appendFormat: @"<Attendee_Type xmlns=\"Calendar:\">%d</Attendee_Type>", attendee_type];
|
|
|
|
|
|
|
|
[s appendString: @"</Attendee>"];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
[s appendString: @"</Attendees>"];
|
|
|
|
}
|
|
|
|
|
2014-01-10 20:12:53 +01:00
|
|
|
// Subject -- http://msdn.microsoft.com/en-us/library/ee157192(v=exchg.80).aspx
|
|
|
|
if ([[self summary] length])
|
|
|
|
[s appendFormat: @"<Subject xmlns=\"Calendar:\">%@</Subject>", [self summary]];
|
|
|
|
|
|
|
|
// UID -- http://msdn.microsoft.com/en-us/library/ee159919(v=exchg.80).aspx
|
|
|
|
if ([[self uid] length])
|
|
|
|
[s appendFormat: @"<UID xmlns=\"Calendar:\">%@</UID>", [self uid]];
|
|
|
|
|
|
|
|
// Sensitivity - FIXME
|
|
|
|
[s appendFormat: @"<Sensitivity xmlns=\"Calendar:\">%d</Sensitivity>", 0];
|
|
|
|
|
|
|
|
// BusyStatus -- http://msdn.microsoft.com/en-us/library/ee202290(v=exchg.80).aspx
|
|
|
|
[s appendFormat: @"<BusyStatus xmlns=\"Calendar:\">%d</BusyStatus>", 0];
|
|
|
|
|
|
|
|
// Reminder -- http://msdn.microsoft.com/en-us/library/ee219691(v=exchg.80).aspx
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2014-01-13 22:25:14 +01:00
|
|
|
// To understand meeting requests/responses, see:
|
2014-01-10 20:12:53 +01:00
|
|
|
//
|
2014-01-13 22:25:14 +01:00
|
|
|
// http://blogs.msdn.com/b/exchangedev/archive/2011/07/22/working-with-meeting-requests-in-exchange-activesync.aspx
|
|
|
|
// http://blogs.msdn.com/b/exchangedev/archive/2011/07/29/working-with-meeting-responses-in-exchange-activesync.aspx
|
2014-01-10 20:12:53 +01:00
|
|
|
//
|
|
|
|
- (void) takeActiveSyncValues: (NSDictionary *) theValues
|
|
|
|
{
|
2014-01-10 22:48:39 +01:00
|
|
|
iCalDateTime *start, *end;
|
|
|
|
NSTimeZone *userTimeZone;
|
|
|
|
iCalTimeZone *tz;
|
2014-01-10 20:12:53 +01:00
|
|
|
id o;
|
2014-01-10 22:48:39 +01:00
|
|
|
|
|
|
|
NSInteger tzOffset;
|
|
|
|
BOOL isAllDay;
|
2014-01-10 20:12:53 +01:00
|
|
|
|
|
|
|
if ((o = [theValues objectForKey: @"UID"]))
|
|
|
|
[self setUid: o];
|
|
|
|
|
2014-01-12 01:31:39 +01:00
|
|
|
// FIXME: merge with iCalToDo
|
2014-01-10 20:12:53 +01:00
|
|
|
if ((o = [theValues objectForKey: @"Subject"]))
|
|
|
|
[self setSummary: o];
|
|
|
|
|
2014-01-10 22:48:39 +01:00
|
|
|
isAllDay = NO;
|
2014-01-10 20:12:53 +01:00
|
|
|
if ([[theValues objectForKey: @"AllDayEvent"] intValue])
|
|
|
|
{
|
2014-01-10 22:48:39 +01:00
|
|
|
isAllDay = YES;
|
|
|
|
}
|
2014-01-10 20:12:53 +01:00
|
|
|
|
2014-01-10 22:48:39 +01:00
|
|
|
//
|
|
|
|
// 0- free, 1- tentative, 2- busy and 3- out of office
|
|
|
|
//
|
|
|
|
if ((o = [theValues objectForKey: @"BusyStatus"]))
|
|
|
|
{
|
|
|
|
[o intValue];
|
2014-01-10 20:12:53 +01:00
|
|
|
}
|
|
|
|
|
2014-01-10 22:48:39 +01:00
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
if ((o = [theValues objectForKey: @"MeetingStatus"]))
|
|
|
|
{
|
|
|
|
[o intValue];
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// 0- normal, 1- personal, 2- private and 3-confidential
|
|
|
|
//
|
|
|
|
if ((o = [theValues objectForKey: @"Sensitivy"]))
|
|
|
|
{
|
|
|
|
switch ([o intValue])
|
|
|
|
{
|
|
|
|
case 2:
|
|
|
|
[self setAccessClass: @"PRIVATE"];
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
[self setAccessClass: @"CONFIDENTIAL"];
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
default:
|
|
|
|
[self setAccessClass: @"PUBLIC"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((o = [theValues objectForKey: @"TimeZone"]))
|
|
|
|
{
|
|
|
|
// Ugh, we ignore it for now.
|
|
|
|
userTimeZone = [theValues objectForKey: @"SOGoUserTimeZone"];
|
|
|
|
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
|
|
|
[(iCalCalendar *) parent addTimeZone: tz];
|
|
|
|
}
|
|
|
|
|
2014-01-12 01:31:39 +01:00
|
|
|
// FIXME: merge with iCalToDo
|
2014-01-10 20:12:53 +01:00
|
|
|
if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"]))
|
|
|
|
[self setComment: o];
|
|
|
|
|
|
|
|
if ((o = [theValues objectForKey: @"Location"]))
|
|
|
|
[self setLocation: o];
|
|
|
|
|
|
|
|
if ((o = [theValues objectForKey: @"StartTime"]))
|
2014-01-10 22:48:39 +01:00
|
|
|
{
|
|
|
|
o = [o calendarDate];
|
|
|
|
start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
|
|
|
|
[start setTimeZone: tz];
|
|
|
|
|
|
|
|
if (isAllDay)
|
|
|
|
{
|
|
|
|
[start setDate: o];
|
|
|
|
[start setTimeZone: nil];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tzOffset = [userTimeZone secondsFromGMTForDate: o];
|
|
|
|
o = [o dateByAddingYears: 0 months: 0 days: 0
|
|
|
|
hours: 0 minutes: 0
|
|
|
|
seconds: tzOffset];
|
|
|
|
[start setDateTime: o];
|
|
|
|
}
|
|
|
|
}
|
2014-01-10 20:12:53 +01:00
|
|
|
|
|
|
|
if ((o = [theValues objectForKey: @"EndTime"]))
|
2014-01-10 22:48:39 +01:00
|
|
|
{
|
|
|
|
o = [o calendarDate];
|
|
|
|
end = (iCalDateTime *) [self uniqueChildWithTag: @"dtend"];
|
|
|
|
[end setTimeZone: tz];
|
|
|
|
|
|
|
|
if (isAllDay)
|
|
|
|
{
|
|
|
|
[end setDate: o];
|
|
|
|
[end setTimeZone: nil];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tzOffset = [userTimeZone secondsFromGMTForDate: o];
|
|
|
|
o = [o dateByAddingYears: 0 months: 0 days: 0
|
|
|
|
hours: 0 minutes: 0
|
|
|
|
seconds: tzOffset];
|
|
|
|
[end setDateTime: o];
|
|
|
|
}
|
|
|
|
}
|
2014-01-10 20:12:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|