2006-06-15 21:34:10 +02:00
|
|
|
/*
|
|
|
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
|
|
|
|
|
|
|
This file is part of OpenGroupware.org.
|
|
|
|
|
|
|
|
OGo is free software; you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU Lesser General Public License as published by the
|
|
|
|
Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
later version.
|
|
|
|
|
|
|
|
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
|
|
License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with OGo; see the file COPYING. If not, write to the
|
|
|
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2007-09-06 22:51:59 +02:00
|
|
|
#import <Foundation/NSCalendarDate.h>
|
|
|
|
|
2007-08-07 20:37:31 +02:00
|
|
|
#import <NGObjWeb/NSException+HTTP.h>
|
|
|
|
#import <NGExtensions/NSNull+misc.h>
|
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
2006-10-11 20:58:16 +02:00
|
|
|
#import <NGCards/iCalCalendar.h>
|
|
|
|
#import <NGCards/iCalEvent.h>
|
2006-12-14 22:20:13 +01:00
|
|
|
#import <NGCards/iCalEventChanges.h>
|
|
|
|
#import <NGCards/iCalPerson.h>
|
2006-10-31 19:54:56 +01:00
|
|
|
|
2007-05-09 20:25:51 +02:00
|
|
|
#import <SoObjects/SOGo/LDAPUserManager.h>
|
|
|
|
#import <SoObjects/SOGo/SOGoObject.h>
|
|
|
|
#import <SoObjects/SOGo/SOGoPermissions.h>
|
2006-10-31 19:54:56 +01:00
|
|
|
|
2006-10-11 20:58:16 +02:00
|
|
|
#import "NSArray+Appointments.h"
|
2007-09-15 00:01:02 +02:00
|
|
|
#import "SOGoAppointmentFolder.h"
|
|
|
|
|
2007-08-07 20:37:31 +02:00
|
|
|
#import "SOGoAppointmentObject.h"
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
@implementation SOGoAppointmentObject
|
|
|
|
|
2007-02-15 21:59:02 +01:00
|
|
|
- (NSString *) componentTag
|
2006-11-07 19:15:42 +01:00
|
|
|
{
|
2007-02-15 21:59:02 +01:00
|
|
|
return @"vevent";
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* iCal handling */
|
2007-01-31 21:15:28 +01:00
|
|
|
- (NSArray *) attendeeUIDsFromAppointment: (iCalEvent *) _apt
|
|
|
|
{
|
2007-05-09 20:25:51 +02:00
|
|
|
LDAPUserManager *um;
|
2007-01-31 21:15:28 +01:00
|
|
|
NSMutableArray *uids;
|
|
|
|
NSArray *attendees;
|
2006-06-15 21:34:10 +02:00
|
|
|
unsigned i, count;
|
|
|
|
NSString *email, *uid;
|
|
|
|
|
|
|
|
if (![_apt isNotNull])
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
if ((attendees = [_apt attendees]) == nil)
|
|
|
|
return nil;
|
|
|
|
count = [attendees count];
|
|
|
|
uids = [NSMutableArray arrayWithCapacity:count + 1];
|
|
|
|
|
2007-05-09 20:25:51 +02:00
|
|
|
um = [LDAPUserManager sharedUserManager];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
/* add organizer */
|
|
|
|
|
|
|
|
email = [[_apt organizer] rfc822Email];
|
|
|
|
if ([email isNotNull]) {
|
2007-05-09 20:25:51 +02:00
|
|
|
uid = [um getUIDForEmail: email];
|
2006-06-15 21:34:10 +02:00
|
|
|
if ([uid isNotNull]) {
|
|
|
|
[uids addObject:uid];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
[self logWithFormat:@"Note: got no uid for organizer: '%@'", email];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add attendees */
|
|
|
|
|
2007-02-15 21:59:02 +01:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
iCalPerson *person;
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-02-15 21:59:02 +01:00
|
|
|
person = [attendees objectAtIndex:i];
|
|
|
|
email = [person rfc822Email];
|
|
|
|
if (![email isNotNull]) continue;
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-02-15 21:59:02 +01:00
|
|
|
uid = [um getUIDForEmail:email];
|
|
|
|
if (![uid isNotNull]) {
|
|
|
|
[self logWithFormat:@"Note: got no uid for email: '%@'", email];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (![uids containsObject:uid])
|
|
|
|
[uids addObject:uid];
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
2007-02-15 21:59:02 +01:00
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
return uids;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store in all the other folders */
|
|
|
|
|
2007-08-24 00:11:19 +02:00
|
|
|
- (NSException *) saveContentString: (NSString *) _iCal
|
|
|
|
inUIDs: (NSArray *) _uids
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
NSEnumerator *e;
|
2007-01-31 21:15:28 +01:00
|
|
|
id folder;
|
|
|
|
NSException *allErrors = nil;
|
2007-11-08 00:35:26 +01:00
|
|
|
NSException *error;
|
|
|
|
SOGoAppointmentObject *apt;
|
|
|
|
|
2007-09-15 00:01:02 +02:00
|
|
|
e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
|
|
|
|
objectEnumerator];
|
2007-11-08 00:35:26 +01:00
|
|
|
while ((folder = [e nextObject]))
|
|
|
|
{
|
|
|
|
apt = [SOGoAppointmentObject objectWithName: nameInContainer
|
|
|
|
inContainer: folder];
|
|
|
|
error = [apt primarySaveContentString:_iCal];
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
[self logWithFormat:@"Note: failed to save iCal in folder: %@", folder];
|
|
|
|
// TODO: make compound
|
|
|
|
allErrors = error;
|
|
|
|
}
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
2007-01-31 21:15:28 +01:00
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
return allErrors;
|
|
|
|
}
|
2007-01-31 21:15:28 +01:00
|
|
|
|
2007-11-07 16:58:43 +01:00
|
|
|
- (NSException *) deleteInUIDs: (NSArray *) _uids
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
NSEnumerator *e;
|
2007-01-31 21:15:28 +01:00
|
|
|
id folder;
|
|
|
|
NSException *allErrors = nil;
|
2007-11-07 16:58:43 +01:00
|
|
|
NSException *error;
|
|
|
|
SOGoAppointmentObject *apt;
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-09-15 00:01:02 +02:00
|
|
|
e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
|
|
|
|
objectEnumerator];
|
2007-11-07 16:58:43 +01:00
|
|
|
while ((folder = [e nextObject]))
|
|
|
|
{
|
|
|
|
apt = [folder lookupName: [self nameInContainer]
|
|
|
|
inContext: context
|
|
|
|
acquire:NO];
|
|
|
|
if ([apt isKindOfClass: [NSException class]]) {
|
|
|
|
[self logWithFormat: @"%@", [(NSException *) apt reason]];
|
|
|
|
continue;
|
|
|
|
}
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-11-07 16:58:43 +01:00
|
|
|
if ((error = [apt primaryDelete]) != nil) {
|
|
|
|
[self logWithFormat:@"Note: failed to delete in folder: %@", folder];
|
|
|
|
// TODO: make compound
|
|
|
|
allErrors = error;
|
|
|
|
}
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
2007-11-07 16:58:43 +01:00
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
return allErrors;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* "iCal multifolder saves" */
|
2007-09-06 22:51:59 +02:00
|
|
|
- (BOOL) _aptIsStillRelevant: (iCalEvent *) appointment
|
|
|
|
{
|
|
|
|
NSCalendarDate *now;
|
|
|
|
|
|
|
|
now = [NSCalendarDate calendarDate];
|
|
|
|
|
|
|
|
return ([[appointment endDate] earlierDate: now] == now);
|
|
|
|
}
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2006-09-28 19:23:39 +02:00
|
|
|
- (NSException *) saveContentString: (NSString *) _iCal
|
|
|
|
baseSequence: (int) _v
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
/*
|
|
|
|
Note: we need to delete in all participants folders and send iMIP messages
|
|
|
|
for all external accounts.
|
|
|
|
|
|
|
|
Steps:
|
|
|
|
- fetch stored content
|
|
|
|
- parse old content
|
|
|
|
- check if sequence matches (or if 0=ignore)
|
|
|
|
- extract old attendee list + organizer (make unique)
|
|
|
|
- parse new content (ensure that sequence is increased!)
|
|
|
|
- extract new attendee list + organizer (make unique)
|
|
|
|
- make a diff => new, same, removed
|
|
|
|
- write to new, same
|
|
|
|
- delete in removed folders
|
|
|
|
- send iMIP mail for all folders not found
|
|
|
|
*/
|
2007-05-09 20:25:51 +02:00
|
|
|
LDAPUserManager *um;
|
2006-09-28 19:23:39 +02:00
|
|
|
iCalEvent *oldApt, *newApt;
|
2007-01-31 21:15:28 +01:00
|
|
|
iCalEventChanges *changes;
|
|
|
|
iCalPerson *organizer;
|
|
|
|
NSString *oldContent, *uid;
|
|
|
|
NSArray *uids, *props;
|
|
|
|
NSMutableArray *attendees, *storeUIDs, *removedUIDs;
|
|
|
|
NSException *storeError, *delError;
|
|
|
|
BOOL updateForcesReconsider;
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
updateForcesReconsider = NO;
|
|
|
|
|
2007-03-18 16:10:03 +01:00
|
|
|
if ([_iCal length] == 0)
|
|
|
|
return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
|
|
|
|
reason: @"got no iCalendar content to store!"];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-05-09 20:25:51 +02:00
|
|
|
um = [LDAPUserManager sharedUserManager];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
/* handle old content */
|
|
|
|
|
2007-01-31 21:15:28 +01:00
|
|
|
oldContent = [self contentAsString]; /* if nil, this is a new appointment */
|
2006-09-28 19:23:39 +02:00
|
|
|
if ([oldContent length] == 0)
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
/* new appointment */
|
2006-09-28 19:23:39 +02:00
|
|
|
[self debugWithFormat:@"saving new appointment: %@", _iCal];
|
|
|
|
oldApt = nil;
|
|
|
|
}
|
|
|
|
else
|
2007-03-18 16:10:03 +01:00
|
|
|
oldApt = (iCalEvent *) [self component: NO];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
/* compare sequence if requested */
|
|
|
|
|
|
|
|
if (_v != 0) {
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
/* handle new content */
|
|
|
|
|
2007-03-18 16:10:03 +01:00
|
|
|
newApt = (iCalEvent *) [self component: NO];
|
|
|
|
if (!newApt)
|
|
|
|
return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
|
|
|
|
reason: @"could not parse iCalendar content!"];
|
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
/* diff */
|
|
|
|
|
2007-03-18 16:10:03 +01:00
|
|
|
changes = [iCalEventChanges changesFromEvent: oldApt toEvent: newApt];
|
2007-05-09 20:25:51 +02:00
|
|
|
uids = [self getUIDsForICalPersons: [changes deletedAttendees]];
|
2007-03-18 16:10:03 +01:00
|
|
|
removedUIDs = [NSMutableArray arrayWithArray: uids];
|
|
|
|
|
2007-05-09 20:25:51 +02:00
|
|
|
uids = [self getUIDsForICalPersons: [newApt attendees]];
|
2007-03-18 16:10:03 +01:00
|
|
|
storeUIDs = [NSMutableArray arrayWithArray: uids];
|
2007-01-31 21:15:28 +01:00
|
|
|
props = [changes updatedProperties];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
/* detect whether sequence has to be increased */
|
|
|
|
if ([changes hasChanges])
|
|
|
|
[newApt increaseSequence];
|
|
|
|
|
|
|
|
/* preserve organizer */
|
|
|
|
|
2006-09-28 19:23:39 +02:00
|
|
|
organizer = [newApt organizer];
|
2007-05-09 20:25:51 +02:00
|
|
|
uid = [self getUIDForICalPerson: organizer];
|
2007-03-18 16:10:03 +01:00
|
|
|
if (!uid)
|
|
|
|
uid = [self ownerInContext: nil];
|
2006-06-15 21:34:10 +02:00
|
|
|
if (uid) {
|
|
|
|
if (![storeUIDs containsObject:uid])
|
|
|
|
[storeUIDs addObject:uid];
|
|
|
|
[removedUIDs removeObject:uid];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* organizer might have changed completely */
|
|
|
|
|
2006-09-28 19:23:39 +02:00
|
|
|
if (oldApt && ([props containsObject: @"organizer"])) {
|
2007-05-09 20:25:51 +02:00
|
|
|
uid = [self getUIDForICalPerson:[oldApt organizer]];
|
2006-06-15 21:34:10 +02:00
|
|
|
if (uid) {
|
|
|
|
if (![storeUIDs containsObject:uid]) {
|
|
|
|
if (![removedUIDs containsObject:uid]) {
|
|
|
|
[removedUIDs addObject:uid];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[self debugWithFormat:@"UID ops:\n store: %@\n remove: %@",
|
|
|
|
storeUIDs, removedUIDs];
|
|
|
|
|
|
|
|
/* if time did change, all participants have to re-decide ...
|
|
|
|
* ... exception from that rule: the organizer
|
|
|
|
*/
|
|
|
|
|
2006-09-28 19:23:39 +02:00
|
|
|
if (oldApt != nil &&
|
2007-03-18 16:10:03 +01:00
|
|
|
([props containsObject: @"startDate"] ||
|
|
|
|
[props containsObject: @"endDate"] ||
|
|
|
|
[props containsObject: @"duration"]))
|
2006-06-15 21:34:10 +02:00
|
|
|
{
|
|
|
|
NSArray *ps;
|
|
|
|
unsigned i, count;
|
|
|
|
|
|
|
|
ps = [newApt attendees];
|
|
|
|
count = [ps count];
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
iCalPerson *p;
|
|
|
|
|
|
|
|
p = [ps objectAtIndex:i];
|
|
|
|
if (![p hasSameEmailAddress:organizer])
|
|
|
|
[p setParticipationStatus:iCalPersonPartStatNeedsAction];
|
|
|
|
}
|
2006-09-28 19:23:39 +02:00
|
|
|
_iCal = [[newApt parent] versitString];
|
2006-06-15 21:34:10 +02:00
|
|
|
updateForcesReconsider = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* perform storing */
|
|
|
|
|
2007-03-18 16:10:03 +01:00
|
|
|
storeError = [self saveContentString: _iCal inUIDs: storeUIDs];
|
|
|
|
delError = [self deleteInUIDs: removedUIDs];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
// TODO: make compound
|
|
|
|
if (storeError != nil) return storeError;
|
|
|
|
if (delError != nil) return delError;
|
|
|
|
|
|
|
|
/* email notifications */
|
2007-09-06 22:51:59 +02:00
|
|
|
if ([self sendEMailNotifications]
|
|
|
|
&& [self _aptIsStillRelevant: newApt])
|
2007-01-31 21:15:28 +01:00
|
|
|
{
|
2007-09-06 22:51:59 +02:00
|
|
|
attendees
|
|
|
|
= [NSMutableArray arrayWithArray: [changes insertedAttendees]];
|
2007-01-31 21:15:28 +01:00
|
|
|
[attendees removePerson: organizer];
|
|
|
|
[self sendEMailUsingTemplateNamed: @"Invitation"
|
|
|
|
forOldObject: nil
|
|
|
|
andNewObject: newApt
|
|
|
|
toAttendees: attendees];
|
|
|
|
|
|
|
|
if (updateForcesReconsider) {
|
|
|
|
attendees = [NSMutableArray arrayWithArray:[newApt attendees]];
|
|
|
|
[attendees removeObjectsInArray:[changes insertedAttendees]];
|
|
|
|
[attendees removePerson:organizer];
|
|
|
|
[self sendEMailUsingTemplateNamed: @"Update"
|
|
|
|
forOldObject: oldApt
|
|
|
|
andNewObject: newApt
|
|
|
|
toAttendees: attendees];
|
|
|
|
}
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-09-06 22:51:59 +02:00
|
|
|
attendees
|
|
|
|
= [NSMutableArray arrayWithArray: [changes deletedAttendees]];
|
2007-01-31 21:15:28 +01:00
|
|
|
[attendees removePerson: organizer];
|
|
|
|
if ([attendees count])
|
|
|
|
{
|
2007-09-06 23:10:51 +02:00
|
|
|
iCalEvent *cancelledApt;
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-09-06 23:10:51 +02:00
|
|
|
cancelledApt = [newApt copy];
|
|
|
|
[(iCalCalendar *) [cancelledApt parent] setMethod: @"cancel"];
|
2007-01-31 21:15:28 +01:00
|
|
|
[self sendEMailUsingTemplateNamed: @"Removal"
|
|
|
|
forOldObject: nil
|
2007-09-06 23:10:51 +02:00
|
|
|
andNewObject: cancelledApt
|
2007-01-31 21:15:28 +01:00
|
|
|
toAttendees: attendees];
|
2007-09-06 23:10:51 +02:00
|
|
|
[cancelledApt release];
|
2007-01-31 21:15:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSException *)deleteWithBaseSequence:(int)_v {
|
|
|
|
/*
|
|
|
|
Note: We need to delete in all participants folders and send iMIP messages
|
|
|
|
for all external accounts.
|
|
|
|
Delete is basically identical to save with all attendees and the
|
|
|
|
organizer being deleted.
|
|
|
|
|
|
|
|
Steps:
|
|
|
|
- fetch stored content
|
|
|
|
- parse old content
|
|
|
|
- check if sequence matches (or if 0=ignore)
|
|
|
|
- extract old attendee list + organizer (make unique)
|
|
|
|
- delete in removed folders
|
|
|
|
- send iMIP mail for all folders not found
|
|
|
|
*/
|
2006-09-28 19:23:39 +02:00
|
|
|
iCalEvent *apt;
|
2007-06-05 21:33:44 +02:00
|
|
|
NSMutableArray *attendees, *removedUIDs;
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
/* load existing content */
|
2006-12-14 22:20:13 +01:00
|
|
|
|
2007-03-18 16:10:03 +01:00
|
|
|
apt = (iCalEvent *) [self component: NO];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
/* compare sequence if requested */
|
|
|
|
|
2007-01-31 21:15:28 +01:00
|
|
|
// if (_v != 0) {
|
|
|
|
// // TODO
|
|
|
|
// }
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-06-05 21:33:44 +02:00
|
|
|
removedUIDs = [NSMutableArray arrayWithArray:
|
|
|
|
[self attendeeUIDsFromAppointment: apt]];
|
|
|
|
if (![removedUIDs containsObject: owner])
|
|
|
|
[removedUIDs addObject: owner];
|
2006-06-15 21:34:10 +02:00
|
|
|
|
2007-11-01 23:38:57 +01:00
|
|
|
if ([self sendEMailNotifications]
|
|
|
|
&& [self _aptIsStillRelevant: apt])
|
2007-01-31 21:15:28 +01:00
|
|
|
{
|
|
|
|
/* send notification email to attendees excluding organizer */
|
|
|
|
attendees = [NSMutableArray arrayWithArray:[apt attendees]];
|
|
|
|
[attendees removePerson:[apt organizer]];
|
|
|
|
|
2007-09-06 23:10:51 +02:00
|
|
|
/* flag appointment as being cancelled */
|
2007-01-31 21:15:28 +01:00
|
|
|
[(iCalCalendar *) [apt parent] setMethod: @"cancel"];
|
|
|
|
[apt increaseSequence];
|
|
|
|
|
|
|
|
/* remove all attendees to signal complete removal */
|
|
|
|
[apt removeAllAttendees];
|
|
|
|
|
|
|
|
/* send notification email */
|
|
|
|
[self sendEMailUsingTemplateNamed: @"Deletion"
|
|
|
|
forOldObject: nil
|
|
|
|
andNewObject: apt
|
|
|
|
toAttendees: attendees];
|
|
|
|
}
|
2006-06-15 21:34:10 +02:00
|
|
|
|
|
|
|
/* perform */
|
2007-01-31 21:15:28 +01:00
|
|
|
|
2007-06-01 06:08:19 +02:00
|
|
|
return [self deleteInUIDs: removedUIDs];
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
|
|
|
|
2007-01-31 21:15:28 +01:00
|
|
|
- (NSException *) saveContentString: (NSString *) _iCalString
|
|
|
|
{
|
|
|
|
return [self saveContentString: _iCalString baseSequence: 0];
|
2006-06-15 21:34:10 +02:00
|
|
|
}
|
2006-10-31 19:54:56 +01:00
|
|
|
|
2006-06-15 21:34:10 +02:00
|
|
|
/* message type */
|
|
|
|
|
2007-01-31 21:15:28 +01:00
|
|
|
- (NSString *) outlookMessageClass
|
|
|
|
{
|
2006-06-15 21:34:10 +02:00
|
|
|
return @"IPM.Appointment";
|
|
|
|
}
|
|
|
|
|
|
|
|
@end /* SOGoAppointmentObject */
|