mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-06-24 19:34:17 +00:00
Monotone-Parent: 463195ab0268a4a769eab22f23b6aecf0c87ad79
Monotone-Revision: 9abbb51cbabcad645190865841814453369fa85f Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-11-18T10:16:25 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
|
||||
#import <NGObjWeb/NSException+HTTP.h>
|
||||
#import <NGObjWeb/WOContext.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
@@ -30,14 +30,19 @@
|
||||
#import <NGCards/iCalEventChanges.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
|
||||
#import <SoObjects/SOGo/iCalEntityObject+Utilities.h>
|
||||
#import <SoObjects/SOGo/LDAPUserManager.h>
|
||||
#import <SoObjects/SOGo/NSArray+Utilities.h>
|
||||
#import <SoObjects/SOGo/SOGoObject.h>
|
||||
#import <SoObjects/SOGo/SOGoPermissions.h>
|
||||
#import <SoObjects/SOGo/SOGoUser.h>
|
||||
#import <SoObjects/SOGo/WORequest+SOGo.h>
|
||||
|
||||
#import "NSArray+Appointments.h"
|
||||
#import "SOGoAppointmentFolder.h"
|
||||
#import "iCalEventChanges+SOGo.h"
|
||||
#import "iCalEntityObject+SOGo.h"
|
||||
#import "iCalPerson+SOGo.h"
|
||||
|
||||
#import "SOGoAppointmentObject.h"
|
||||
|
||||
@@ -48,387 +53,325 @@
|
||||
return @"vevent";
|
||||
}
|
||||
|
||||
/* iCal handling */
|
||||
- (NSArray *) attendeeUIDsFromAppointment: (iCalEvent *) _apt
|
||||
- (SOGoAppointmentObject *) _lookupEvent: (NSString *) eventUID
|
||||
forUID: (NSString *) uid
|
||||
{
|
||||
SOGoAppointmentFolder *folder;
|
||||
SOGoAppointmentObject *object;
|
||||
NSString *possibleName;
|
||||
|
||||
folder = [container lookupCalendarFolderForUID: uid];
|
||||
object = [folder lookupName: nameInContainer
|
||||
inContext: context acquire: NO];
|
||||
if ([object isKindOfClass: [NSException class]])
|
||||
{
|
||||
possibleName = [folder resourceNameForEventUID: eventUID];
|
||||
if (possibleName)
|
||||
{
|
||||
object = [folder lookupName: nameInContainer
|
||||
inContext: context acquire: NO];
|
||||
if ([object isKindOfClass: [NSException class]])
|
||||
object = nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (!object)
|
||||
object = [SOGoAppointmentObject objectWithName: nameInContainer
|
||||
inContainer: folder];
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
- (void) _addOrUpdateEvent: (iCalEvent *) event
|
||||
forUID: (NSString *) uid
|
||||
{
|
||||
SOGoAppointmentObject *object;
|
||||
NSString *iCalString, *userLogin;
|
||||
|
||||
userLogin = [[context activeUser] login];
|
||||
if (![uid isEqualToString: userLogin])
|
||||
{
|
||||
object = [self _lookupEvent: [event uid] forUID: uid];
|
||||
iCalString = [[event parent] versitString];
|
||||
[object saveContentString: iCalString];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _removeEventFromUID: (NSString *) uid
|
||||
{
|
||||
SOGoAppointmentFolder *folder;
|
||||
SOGoAppointmentObject *object;
|
||||
NSString *userLogin;
|
||||
|
||||
userLogin = [[context activeUser] login];
|
||||
if (![uid isEqualToString: userLogin])
|
||||
{
|
||||
folder = [container lookupCalendarFolderForUID: uid];
|
||||
object = [folder lookupName: nameInContainer
|
||||
inContext: context acquire: NO];
|
||||
if (![object isKindOfClass: [NSException class]])
|
||||
[object delete];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _handleRemovedUsers: (NSArray *) attendees
|
||||
{
|
||||
NSEnumerator *enumerator;
|
||||
iCalPerson *currentAttendee;
|
||||
NSString *currentUID;
|
||||
|
||||
enumerator = [attendees objectEnumerator];
|
||||
while ((currentAttendee = [enumerator nextObject]))
|
||||
{
|
||||
currentUID = [currentAttendee uid];
|
||||
if (currentUID)
|
||||
[self _removeEventFromUID: currentUID];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _requireResponseFromAttendees: (NSArray *) attendees
|
||||
{
|
||||
NSEnumerator *enumerator;
|
||||
iCalPerson *currentAttendee;
|
||||
|
||||
enumerator = [attendees objectEnumerator];
|
||||
while ((currentAttendee = [enumerator nextObject]))
|
||||
{
|
||||
[currentAttendee setRsvp: @"TRUE"];
|
||||
[currentAttendee setParticipationStatus: iCalPersonPartStatNeedsAction];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _handleSequenceUpdateInEvent: (iCalEvent *) newEvent
|
||||
ignoringAttendees: (NSArray *) attendees
|
||||
fromOldEvent: (iCalEvent *) oldEvent
|
||||
{
|
||||
NSMutableArray *updateAttendees, *updateUIDs;
|
||||
NSEnumerator *enumerator;
|
||||
iCalPerson *currentAttendee;
|
||||
NSString *currentUID;
|
||||
|
||||
updateAttendees = [NSMutableArray arrayWithArray: [newEvent attendees]];
|
||||
[updateAttendees removeObjectsInArray: attendees];
|
||||
|
||||
updateUIDs = [NSMutableArray arrayWithCapacity: [updateAttendees count]];
|
||||
enumerator = [updateAttendees objectEnumerator];
|
||||
while ((currentAttendee = [enumerator nextObject]))
|
||||
{
|
||||
currentUID = [currentAttendee uid];
|
||||
if (currentUID)
|
||||
[self _addOrUpdateEvent: newEvent
|
||||
forUID: currentUID];
|
||||
}
|
||||
|
||||
[self sendEMailUsingTemplateNamed: @"Update"
|
||||
forOldObject: oldEvent
|
||||
andNewObject: [newEvent itipEntryWithMethod: @"request"]
|
||||
toAttendees: updateAttendees];
|
||||
}
|
||||
|
||||
- (void) _handleAddedUsers: (NSArray *) attendees
|
||||
fromEvent: (iCalEvent *) newEvent
|
||||
{
|
||||
NSEnumerator *enumerator;
|
||||
iCalPerson *currentAttendee;
|
||||
NSString *currentUID;
|
||||
|
||||
enumerator = [attendees objectEnumerator];
|
||||
while ((currentAttendee = [enumerator nextObject]))
|
||||
{
|
||||
currentUID = [currentAttendee uid];
|
||||
if (currentUID)
|
||||
[self _addOrUpdateEvent: newEvent
|
||||
forUID: currentUID];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _handleUpdatedEvent: (iCalEvent *) newEvent
|
||||
fromOldEvent: (iCalEvent *) oldEvent
|
||||
{
|
||||
LDAPUserManager *um;
|
||||
NSMutableArray *uids;
|
||||
NSArray *attendees;
|
||||
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];
|
||||
|
||||
um = [LDAPUserManager sharedUserManager];
|
||||
|
||||
/* add organizer */
|
||||
|
||||
email = [[_apt organizer] rfc822Email];
|
||||
if ([email isNotNull]) {
|
||||
uid = [um getUIDForEmail: email];
|
||||
if ([uid isNotNull]) {
|
||||
[uids addObject:uid];
|
||||
}
|
||||
else
|
||||
[self logWithFormat:@"Note: got no uid for organizer: '%@'", email];
|
||||
}
|
||||
|
||||
/* add attendees */
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
iCalPerson *person;
|
||||
|
||||
person = [attendees objectAtIndex:i];
|
||||
email = [person rfc822Email];
|
||||
if (![email isNotNull]) continue;
|
||||
|
||||
uid = [um getUIDForEmail:email];
|
||||
if (![uid isNotNull]) {
|
||||
[self logWithFormat:@"Note: got no uid for email: '%@'", email];
|
||||
continue;
|
||||
}
|
||||
if (![uids containsObject:uid])
|
||||
[uids addObject:uid];
|
||||
}
|
||||
|
||||
return uids;
|
||||
}
|
||||
|
||||
/* store in all the other folders */
|
||||
|
||||
- (NSException *) saveContentString: (NSString *) _iCal
|
||||
inUIDs: (NSArray *) _uids
|
||||
{
|
||||
NSEnumerator *e;
|
||||
id folder;
|
||||
NSException *allErrors = nil;
|
||||
NSException *error;
|
||||
SOGoAppointmentObject *apt;
|
||||
|
||||
e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
|
||||
objectEnumerator];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return allErrors;
|
||||
}
|
||||
|
||||
- (NSException *) deleteInUIDs: (NSArray *) _uids
|
||||
{
|
||||
NSEnumerator *e;
|
||||
id folder;
|
||||
NSException *allErrors = nil;
|
||||
NSException *error;
|
||||
SOGoAppointmentObject *apt;
|
||||
|
||||
e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
|
||||
objectEnumerator];
|
||||
while ((folder = [e nextObject]))
|
||||
{
|
||||
apt = [folder lookupName: [self nameInContainer]
|
||||
inContext: context
|
||||
acquire:NO];
|
||||
if ([apt isKindOfClass: [NSException class]]) {
|
||||
[self logWithFormat: @"%@", [(NSException *) apt reason]];
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((error = [apt primaryDelete]) != nil) {
|
||||
[self logWithFormat:@"Note: failed to delete in folder: %@", folder];
|
||||
// TODO: make compound
|
||||
allErrors = error;
|
||||
}
|
||||
}
|
||||
|
||||
return allErrors;
|
||||
}
|
||||
|
||||
/* "iCal multifolder saves" */
|
||||
- (BOOL) _aptIsStillRelevant: (iCalEvent *) appointment
|
||||
{
|
||||
NSCalendarDate *now;
|
||||
|
||||
now = [NSCalendarDate calendarDate];
|
||||
|
||||
return ([[appointment endDate] earlierDate: now] == now);
|
||||
}
|
||||
|
||||
- (NSException *) saveContentString: (NSString *) _iCal
|
||||
baseSequence: (int) _v
|
||||
{
|
||||
/*
|
||||
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
|
||||
*/
|
||||
LDAPUserManager *um;
|
||||
iCalEvent *oldApt, *newApt;
|
||||
iCalEventChanges *changes;
|
||||
iCalPerson *organizer;
|
||||
NSString *oldContent, *uid;
|
||||
NSArray *uids, *props;
|
||||
NSMutableArray *attendees, *storeUIDs, *removedUIDs;
|
||||
NSException *storeError, *delError;
|
||||
BOOL updateForcesReconsider;
|
||||
|
||||
if ([[context request] handledByDefaultHandler])
|
||||
|
||||
changes = [newEvent getChangesRelativeToEvent: oldEvent];
|
||||
attendees = [changes deletedAttendees];
|
||||
if ([attendees count])
|
||||
{
|
||||
updateForcesReconsider = NO;
|
||||
[self _handleRemovedUsers: attendees];
|
||||
[self sendEMailUsingTemplateNamed: @"Deletion"
|
||||
forOldObject: oldEvent
|
||||
andNewObject: [newEvent itipEntryWithMethod: @"cancel"]
|
||||
toAttendees: attendees];
|
||||
}
|
||||
|
||||
if ([_iCal length] == 0)
|
||||
return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
|
||||
reason: @"got no iCalendar content to store!"];
|
||||
attendees = [changes insertedAttendees];
|
||||
if ([changes sequenceShouldBeIncreased])
|
||||
{
|
||||
[newEvent increaseSequence];
|
||||
[self _requireResponseFromAttendees: [newEvent attendees]];
|
||||
[self _handleSequenceUpdateInEvent: newEvent
|
||||
ignoringAttendees: attendees
|
||||
fromOldEvent: oldEvent];
|
||||
}
|
||||
else
|
||||
[self _requireResponseFromAttendees: attendees];
|
||||
|
||||
um = [LDAPUserManager sharedUserManager];
|
||||
if ([attendees count])
|
||||
{
|
||||
[self _handleAddedUsers: attendees fromEvent: newEvent];
|
||||
[self sendEMailUsingTemplateNamed: @"Invitation"
|
||||
forOldObject: oldEvent
|
||||
andNewObject: [newEvent itipEntryWithMethod: @"request"]
|
||||
toAttendees: attendees];
|
||||
}
|
||||
}
|
||||
|
||||
/* handle old content */
|
||||
|
||||
oldContent = [self contentAsString]; /* if nil, this is a new appointment */
|
||||
if ([oldContent length] == 0)
|
||||
{
|
||||
/* new appointment */
|
||||
[self debugWithFormat:@"saving new appointment: %@", _iCal];
|
||||
oldApt = nil;
|
||||
}
|
||||
- (void) saveComponent: (iCalEvent *) newEvent
|
||||
{
|
||||
iCalEvent *oldEvent;
|
||||
NSArray *attendees;
|
||||
|
||||
[[newEvent parent] setMethod: @""];
|
||||
if ([newEvent userIsOrganizer: [context activeUser]])
|
||||
{
|
||||
oldEvent = [self component: NO secure: NO];
|
||||
if (oldEvent)
|
||||
[self _handleUpdatedEvent: newEvent fromOldEvent: oldEvent];
|
||||
else
|
||||
oldApt = (iCalEvent *) [self component: NO];
|
||||
|
||||
/* compare sequence if requested */
|
||||
if (_v != 0) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/* handle new content */
|
||||
|
||||
newApt = (iCalEvent *) [self component: NO];
|
||||
if (!newApt)
|
||||
return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
|
||||
reason: @"could not parse iCalendar content!"];
|
||||
|
||||
/* diff */
|
||||
|
||||
changes = [iCalEventChanges changesFromEvent: oldApt toEvent: newApt];
|
||||
uids = [self getUIDsForICalPersons: [changes deletedAttendees]];
|
||||
removedUIDs = [NSMutableArray arrayWithArray: uids];
|
||||
|
||||
uids = [self getUIDsForICalPersons: [newApt attendees]];
|
||||
storeUIDs = [NSMutableArray arrayWithArray: uids];
|
||||
props = [changes updatedProperties];
|
||||
|
||||
/* detect whether sequence has to be increased */
|
||||
if ([changes hasChanges])
|
||||
[newApt increaseSequence];
|
||||
|
||||
/* preserve organizer */
|
||||
|
||||
organizer = [newApt organizer];
|
||||
uid = [self getUIDForICalPerson: organizer];
|
||||
if (!uid)
|
||||
uid = [self ownerInContext: nil];
|
||||
if (uid)
|
||||
{
|
||||
[storeUIDs addObjectUniquely: uid];
|
||||
[removedUIDs removeObject: uid];
|
||||
}
|
||||
|
||||
/* organizer might have changed completely */
|
||||
|
||||
if (oldApt && ([props containsObject: @"organizer"]))
|
||||
{
|
||||
uid = [self getUIDForICalPerson: [oldApt organizer]];
|
||||
if (uid && ![storeUIDs containsObject: uid])
|
||||
[removedUIDs addObjectUniquely: 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
|
||||
*/
|
||||
|
||||
if (oldApt
|
||||
&& ([props containsObject: @"startDate"]
|
||||
|| [props containsObject: @"endDate"]
|
||||
|| [props containsObject: @"duration"]))
|
||||
{
|
||||
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];
|
||||
}
|
||||
_iCal = [[newApt parent] versitString];
|
||||
updateForcesReconsider = YES;
|
||||
}
|
||||
|
||||
/* perform storing */
|
||||
|
||||
storeError = [self saveContentString: _iCal inUIDs: storeUIDs];
|
||||
delError = [self deleteInUIDs: removedUIDs];
|
||||
|
||||
// TODO: make compound
|
||||
if (storeError != nil) return storeError;
|
||||
if (delError != nil) return delError;
|
||||
|
||||
/* email notifications */
|
||||
if ([self sendEMailNotifications]
|
||||
&& [self _aptIsStillRelevant: newApt])
|
||||
{
|
||||
iCalEvent *requestApt;
|
||||
|
||||
requestApt = [newApt copy];
|
||||
[(iCalCalendar *) [requestApt parent] setMethod: @"request"];
|
||||
attendees
|
||||
= [NSMutableArray arrayWithArray: [changes insertedAttendees]];
|
||||
[attendees removePerson: organizer];
|
||||
[self sendEMailUsingTemplateNamed: @"Invitation"
|
||||
forOldObject: nil
|
||||
andNewObject: requestApt
|
||||
toAttendees: attendees];
|
||||
[requestApt release];
|
||||
|
||||
if (updateForcesReconsider)
|
||||
{
|
||||
iCalEvent *updatedApt;
|
||||
|
||||
updatedApt = [newApt copy];
|
||||
[(iCalCalendar *) [updatedApt parent] setMethod: @"request"];
|
||||
attendees = [NSMutableArray arrayWithArray:[newApt attendees]];
|
||||
[attendees removeObjectsInArray:[changes insertedAttendees]];
|
||||
[attendees removePerson:organizer];
|
||||
[self sendEMailUsingTemplateNamed: @"Update"
|
||||
forOldObject: oldApt
|
||||
andNewObject: updatedApt
|
||||
toAttendees: attendees];
|
||||
[updatedApt release];
|
||||
}
|
||||
|
||||
attendees
|
||||
= [NSMutableArray arrayWithArray: [changes deletedAttendees]];
|
||||
[attendees removePerson: organizer];
|
||||
attendees = [newEvent attendeesWithoutUser: [context activeUser]];
|
||||
if ([attendees count])
|
||||
{
|
||||
iCalEvent *cancelledApt;
|
||||
|
||||
cancelledApt = [newApt copy];
|
||||
[(iCalCalendar *) [cancelledApt parent] setMethod: @"cancel"];
|
||||
[self sendEMailUsingTemplateNamed: @"Removal"
|
||||
[self _handleAddedUsers: attendees fromEvent: newEvent];
|
||||
[self sendEMailUsingTemplateNamed: @"Invitation"
|
||||
forOldObject: nil
|
||||
andNewObject: cancelledApt
|
||||
andNewObject: [newEvent itipEntryWithMethod: @"request"]
|
||||
toAttendees: attendees];
|
||||
[cancelledApt release];
|
||||
}
|
||||
|
||||
if (![[newEvent attendees] count])
|
||||
[[newEvent uniqueChildWithTag: @"organizer"] setValue: 0
|
||||
to: @""];
|
||||
}
|
||||
}
|
||||
else
|
||||
[self primarySaveContentString: _iCal];
|
||||
|
||||
return nil;
|
||||
[super saveComponent: newEvent];
|
||||
}
|
||||
|
||||
- (NSException *) deleteWithBaseSequence: (int)_v
|
||||
- (NSException *) _updateAttendee: (iCalPerson *) attendee
|
||||
forEventUID: (NSString *) eventUID
|
||||
withSequence: (NSNumber *) sequence
|
||||
forUID: (NSString *) uid
|
||||
{
|
||||
/*
|
||||
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
|
||||
*/
|
||||
iCalEvent *apt;
|
||||
NSMutableArray *attendees, *removedUIDs;
|
||||
SOGoAppointmentObject *eventObject;
|
||||
iCalEvent *event;
|
||||
iCalPerson *otherAttendee;
|
||||
NSString *iCalString;
|
||||
NSException *error;
|
||||
|
||||
if ([[context request] handledByDefaultHandler])
|
||||
error = nil;
|
||||
|
||||
eventObject = [self _lookupEvent: eventUID forUID: uid];
|
||||
if (![eventObject isNew])
|
||||
{
|
||||
/* load existing content */
|
||||
apt = (iCalEvent *) [self component: NO];
|
||||
|
||||
/* compare sequence if requested */
|
||||
|
||||
// if (_v != 0) {
|
||||
// // TODO
|
||||
// }
|
||||
|
||||
removedUIDs = [NSMutableArray arrayWithArray:
|
||||
[self attendeeUIDsFromAppointment: apt]];
|
||||
if (![removedUIDs containsObject: owner])
|
||||
[removedUIDs addObject: owner];
|
||||
|
||||
if ([self sendEMailNotifications]
|
||||
&& [self _aptIsStillRelevant: apt])
|
||||
event = [eventObject component: NO secure: NO];
|
||||
if ([[event sequence] compare: sequence]
|
||||
== NSOrderedSame)
|
||||
{
|
||||
/* send notification email to attendees excluding organizer */
|
||||
attendees = [NSMutableArray arrayWithArray: [apt attendees]];
|
||||
[attendees removePerson: [apt organizer]];
|
||||
|
||||
/* flag appointment as being cancelled */
|
||||
[(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];
|
||||
otherAttendee = [event findParticipant: [context activeUser]];
|
||||
[otherAttendee setPartStat: [attendee partStat]];
|
||||
iCalString = [[event parent] versitString];
|
||||
error = [eventObject saveContentString: iCalString];
|
||||
}
|
||||
|
||||
error = [self deleteInUIDs: removedUIDs];
|
||||
}
|
||||
else
|
||||
error = [self primaryDelete];
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
- (NSException *) saveContentString: (NSString *) _iCalString
|
||||
- (NSException *) _handleAttendee: (iCalPerson *) attendee
|
||||
statusChange: (NSString *) newStatus
|
||||
inEvent: (iCalEvent *) event
|
||||
{
|
||||
return [self saveContentString: _iCalString baseSequence: 0];
|
||||
NSString *newContent, *currentStatus, *organizerUID;
|
||||
NSException *ex;
|
||||
|
||||
ex = nil;
|
||||
|
||||
currentStatus = [attendee partStat];
|
||||
if ([currentStatus caseInsensitiveCompare: newStatus]
|
||||
!= NSOrderedSame)
|
||||
{
|
||||
[attendee setPartStat: newStatus];
|
||||
newContent = [[event parent] versitString];
|
||||
ex = [self saveContentString: newContent];
|
||||
if (!(ex || [event userIsOrganizer: [context activeUser]]))
|
||||
{
|
||||
if ([[attendee rsvp] isEqualToString: @"true"])
|
||||
[self sendResponseToOrganizer];
|
||||
organizerUID = [[event organizer] uid];
|
||||
if (organizerUID)
|
||||
ex = [self _updateAttendee: attendee
|
||||
forEventUID: [event uid]
|
||||
withSequence: [event sequence]
|
||||
forUID: organizerUID];
|
||||
}
|
||||
}
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
- (NSException *) changeParticipationStatus: (NSString *) _status
|
||||
{
|
||||
iCalEvent *event;
|
||||
iCalPerson *attendee;
|
||||
NSException *ex;
|
||||
|
||||
ex = nil;
|
||||
|
||||
event = [self component: NO secure: NO];
|
||||
if (event)
|
||||
{
|
||||
attendee = [event findParticipant: [context activeUser]];
|
||||
if (attendee)
|
||||
ex = [self _handleAttendee: attendee statusChange: _status
|
||||
inEvent: event];
|
||||
else
|
||||
ex = [NSException exceptionWithHTTPStatus: 404 /* Not Found */
|
||||
reason: @"user does not participate in this "
|
||||
@"calendar event"];
|
||||
}
|
||||
else
|
||||
ex = [NSException exceptionWithHTTPStatus: 500 /* Server Error */
|
||||
reason: @"unable to parse event record"];
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
- (void) prepareDelete
|
||||
{
|
||||
iCalEvent *event;
|
||||
SOGoUser *currentUser;
|
||||
NSArray *attendees;
|
||||
|
||||
if ([[context request] handledByDefaultHandler])
|
||||
{
|
||||
currentUser = [context activeUser];
|
||||
event = [self component: NO secure: NO];
|
||||
if ([event userIsOrganizer: currentUser])
|
||||
{
|
||||
attendees = [event attendeesWithoutUser: currentUser];
|
||||
if ([attendees count])
|
||||
{
|
||||
[self _handleRemovedUsers: attendees];
|
||||
[self sendEMailUsingTemplateNamed: @"Deletion"
|
||||
forOldObject: nil
|
||||
andNewObject: [event itipEntryWithMethod: @"cancel"]
|
||||
toAttendees: attendees];
|
||||
}
|
||||
}
|
||||
else if ([event userIsParticipant: currentUser])
|
||||
[self changeParticipationStatus: @"DECLINED"];
|
||||
}
|
||||
}
|
||||
|
||||
/* message type */
|
||||
|
||||
Reference in New Issue
Block a user