Improved handling of notifications and participation change updates. Added comments to the code.

Monotone-Parent: 17e3e8707a2ae061fd0c4184a32cd23a97af96ba
Monotone-Revision: 6fac49c5eccc3f49ff214ee3fa7e0df6f166f18d

Monotone-Author: ludovic@Sophos.ca
Monotone-Date: 2008-11-10T15:38:05
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Ludovic Marcotte 2008-11-10 15:38:05 +00:00
parent 1b5c0ef81c
commit 312656117f
6 changed files with 167 additions and 39 deletions

View File

@ -1882,18 +1882,18 @@ static Class sogoAppointmentFolderKlass = Nil;
NSArray *elements;
NSString *method, *filename;
SOGoAppointmentObject *apt;
filename = [NSString stringWithFormat: @"%@.ics", [event uid]];
apt = [SOGoAppointmentObject objectWithName: filename
andContent: iCalString
inContainer: self];
method = [[event parent] method];
if ([method isEqualToString: @"REQUEST"])
elements = [apt postCalDAVEventRequestTo: recipients];
elements = [apt postCalDAVEventRequestTo: recipients from: originator];
else if ([method isEqualToString: @"REPLY"])
elements = [apt postCalDAVEventReplyTo: recipients];
elements = [apt postCalDAVEventReplyTo: recipients from: originator];
else if ([method isEqualToString: @"CANCEL"])
elements = [apt postCalDAVEventCancelTo: recipients];
elements = [apt postCalDAVEventCancelTo: recipients from: originator];
else
elements = nil;
@ -1964,6 +1964,10 @@ static Class sogoAppointmentFolderKlass = Nil;
if ([cType hasPrefix: @"text/calendar"])
{
originator = [request headerForKey: @"originator"];
if ([[originator lowercaseString] hasPrefix: @"mailto:"])
originator = [originator substringFromIndex: 7];
recipients = [[request headerForKey: @"recipient"]
componentsSeparatedByString: @", "];
obj = [self caldavScheduleRequest: [request contentAsString]

View File

@ -48,11 +48,11 @@
- (NSException *) changeParticipationStatus: (NSString *) _status;
- (void) takeAttendeeStatus: (iCalPerson *) attendee;
- (void) takeAttendeeStatus: (iCalPerson *) attendee from: (NSString *) originator;
- (NSArray *) postCalDAVEventRequestTo: (NSArray *) recipients;
- (NSArray *) postCalDAVEventReplyTo: (NSArray *) recipients;
- (NSArray *) postCalDAVEventCancelTo: (NSArray *) recipients;
- (NSArray *) postCalDAVEventRequestTo: (NSArray *) recipients from: (NSString *) originator;
- (NSArray *) postCalDAVEventReplyTo: (NSArray *) recipients from: (NSString *) originator;
- (NSArray *) postCalDAVEventCancelTo: (NSArray *) recipients from: (NSString *) originator;
/* "iCal multifolder saves" */

View File

@ -362,6 +362,17 @@
[super saveComponent: newEvent];
}
//
// This method is used to update the status of an attendee.
//
// - theOwnerUser is owner of the calendar where the attendee
// participation state has changed.
// - uid is the actual UID of the user for whom we must
// update the calendar event (with the participation change)
//
// This method is called multiple times, in order to update the
// status of the attendee in calendars for the particular event UID.
//
- (NSException *) _updateAttendee: (iCalPerson *) attendee
ownerUser: (SOGoUser *) theOwnerUser
forEventUID: (NSString *) eventUID
@ -409,14 +420,21 @@
return error;
}
//
// This method is invoked only from the SOGo Web interface.
//
// - theOwnerUser is owner of the calendar where the attendee
// participation state has changed.
//
- (NSException *) _handleAttendee: (iCalPerson *) attendee
ownerUser: (SOGoUser *) theOwnerUser
statusChange: (NSString *) newStatus
inEvent: (iCalEvent *) event
{
NSString *newContent, *currentStatus, *currentUser, *organizerUID;
NSException *ex;
SOGoUser *ownerUser;
NSException *ex;
ex = nil;
@ -442,14 +460,17 @@
newContent = [[event parent] versitString];
ex = [self saveContentString: newContent];
// If the current user isn't the organizer of the event
// that has just been updated, we update the event and
// send a notification
ownerUser = [SOGoUser userWithLogin: owner roles: nil];
if (!(ex || [event userIsOrganizer: ownerUser]))
{
if ([[attendee rsvp] isEqualToString: @"true"]
&& [event isStillRelevant])
[self sendResponseToOrganizer: event];
[self sendResponseToOrganizer: event
from: ownerUser];
organizerUID = [[event organizer] uid];
if (organizerUID)
ex = [self _updateAttendee: attendee
@ -514,6 +535,7 @@
}
- (NSArray *) postCalDAVEventRequestTo: (NSArray *) recipients
from: (NSString *) originator
{
NSMutableArray *elements;
NSEnumerator *recipientsEnum;
@ -546,6 +568,7 @@
}
- (NSArray *) postCalDAVEventCancelTo: (NSArray *) recipients
from: (NSString *) originator
{
NSMutableArray *elements;
NSEnumerator *recipientsEnum;
@ -577,7 +600,19 @@
return elements;
}
//
// This method is invoked by CalDAV clients such as
// Mozilla Lightning. We assume the SENT-BY has
// already been added, if required.
//
// It is used to updated the status of an attendee.
// The originator is the actualy owner of the calendar
// where the update took place. The status must then
// be propagated to the organizer and the other attendees.
//
- (void) takeAttendeeStatus: (iCalPerson *) attendee
from: (NSString *) originator
{
iCalPerson *localAttendee;
iCalEvent *event;
@ -595,17 +630,23 @@
iCalPerson *att;
NSString *uid;
int i;
ownerUser = [SOGoUser userWithLogin:[[LDAPUserManager sharedUserManager]
getUIDForEmail: originator]
roles: nil];
// We update for the organizer
ownerUser = [context activeUser];
[self _updateAttendee: attendee
ownerUser: ownerUser
forEventUID: [event uid]
withSequence: [event sequence]
forUID: [[SOGoUser userWithLogin: owner roles: nil] login]
shouldAddSentBy: NO];
// We update the copy of the organizer, only
// if it's a local user.
#warning add a check for only local users
uid = [[event organizer] uid];
if (uid)
[self _updateAttendee: attendee
ownerUser: ownerUser
forEventUID: [event uid]
withSequence: [event sequence]
forUID: uid
shouldAddSentBy: NO];
attendees = [event attendees];
for (i = 0; i < [attendees count]; i++)
@ -619,6 +660,12 @@
if (uid)
{
// We skip the update that correspond to the originator
// since the CalDAV client will already have updated
// the actual event.
if ([ownerUser hasEmail: [att rfc822Email]])
continue;
[self _updateAttendee: attendee
ownerUser: ownerUser
forEventUID: [event uid]
@ -635,6 +682,7 @@
}
- (NSArray *) postCalDAVEventReplyTo: (NSArray *) recipients
from: (NSString *) originator
{
NSMutableArray *elements;
NSEnumerator *recipientsEnum;
@ -643,10 +691,15 @@
iCalPerson *attendee, *person;
SOGoAppointmentObject *recipientEvent;
SOGoUser *ownerUser;
NSString *email;
elements = [NSMutableArray array];
event = [self component: NO secure: NO];
ownerUser = [SOGoUser userWithLogin: owner roles: nil];
//ownerUser = [SOGoUser userWithLogin: owner roles: nil];
ownerUser = [SOGoUser userWithLogin: [[LDAPUserManager sharedUserManager]
getUIDForEmail: originator]
roles: nil];
attendee = [event findParticipant: ownerUser];
eventUID = [event uid];
@ -663,9 +716,12 @@
if ([recipientEvent isNew])
[recipientEvent saveComponent: event];
else
[recipientEvent takeAttendeeStatus: attendee];
[recipientEvent takeAttendeeStatus: attendee
from: originator];
}
[self sendIMIPReplyForEvent: event to: person];
[self sendIMIPReplyForEvent: event
from: ownerUser
to: person];
[person release];
[elements
addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
@ -674,6 +730,9 @@
return elements;
}
//
// This method is invoked only from the SOGo Web interface.
//
- (NSException *) changeParticipationStatus: (NSString *) _status
{
iCalEvent *event;
@ -686,7 +745,13 @@
event = [self component: NO secure: NO];
if (event)
{
// owerUser will actually be the owner of the calendar
// where the participation change on the event has
// actually occured. The particpation change will of
// course be on the attendee that is the owner of the
// calendar where the participation change has occured.
ownerUser = [SOGoUser userWithLogin: owner roles: nil];
attendee = [event findParticipant: ownerUser];
if (attendee)
ex = [self _handleAttendee: attendee

View File

@ -63,8 +63,10 @@
forObject: (iCalRepeatableEntityObject *) object
toAttendees: (NSArray *) attendees;
- (void) sendIMIPReplyForEvent: (iCalRepeatableEntityObject *) event
from: (SOGoUser *) from
to: (iCalPerson *) recipient;
- (void) sendResponseToOrganizer: (iCalRepeatableEntityObject *) newComponent;
- (void) sendResponseToOrganizer: (iCalRepeatableEntityObject *) newComponent
from: (SOGoUser *) owner;
// - (BOOL) isOrganizerOrOwner: (SOGoUser *) user;

View File

@ -583,6 +583,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
#warning fix this when sendEmailUsing blabla has been cleaned up
- (void) sendIMIPReplyForEvent: (iCalRepeatableEntityObject *) event
from: (SOGoUser *) from
to: (iCalPerson *) recipient
{
NSString *pageName, *language, *mailDate, *email;
@ -602,7 +603,8 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
/* get WOApplication instance */
app = [WOApplication application];
ownerUser = [SOGoUser userWithLogin: owner roles: nil];
//ownerUser = [SOGoUser userWithLogin: owner roles: nil];
ownerUser = from;
language = [ownerUser language];
/* create page name */
pageName
@ -672,6 +674,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
}
- (void) sendResponseToOrganizer: (iCalRepeatableEntityObject *) newComponent
from: (SOGoUser *) from
{
iCalPerson *organizer, *attendee;
iCalEvent *event;
@ -684,7 +687,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
organizer = [event organizer];
attendee = [event findParticipant: ownerUser];
[event setAttendees: [NSArray arrayWithObject: attendee]];
[self sendIMIPReplyForEvent: event to: organizer];
[self sendIMIPReplyForEvent: event from: from to: organizer];
}
}

View File

@ -1,6 +1,6 @@
/* UIxMailPartICalActions.m - this file is part of SOGo
*
* Copyright (C) 2007 Inverse inc.
* Copyright (C) 2007-2008 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -36,6 +36,7 @@
#import <NGImap4/NGImap4EnvelopeAddress.h>
#import <SoObjects/Appointments/iCalEvent+SOGo.h>
#import <SoObjects/Appointments/iCalPerson+SOGo.h>
#import <SoObjects/Appointments/SOGoAppointmentObject.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
@ -168,16 +169,18 @@
#warning this is code copied from SOGoAppointmentObject...
- (void) _updateAttendee: (iCalPerson *) attendee
withSequence: (NSNumber *) sequence
andCalUID: (NSString *) calUID
forUID: (NSString *) uid
ownerUser: (SOGoUser *) theOwnerUser
forEventUID: (NSString *) eventUID
withSequence: (NSNumber *) sequence
forUID: (NSString *) uid
shouldAddSentBy: (BOOL) b
{
SOGoAppointmentObject *eventObject;
iCalEvent *event;
iCalPerson *otherAttendee;
NSString *iCalString;
eventObject = [self _eventObjectWithUID: calUID
eventObject = [self _eventObjectWithUID: eventUID
forUser: [SOGoUser userWithLogin: uid roles: nil]];
if (![eventObject isNew])
{
@ -185,9 +188,22 @@
if ([[event sequence] compare: sequence]
== NSOrderedSame)
{
otherAttendee
= [event findParticipantWithEmail: [attendee rfc822Email]];
SOGoUser *currentUser;
otherAttendee = [event findParticipant: theOwnerUser];
[otherAttendee setPartStat: [attendee partStat]];
// If one has accepted / declined an invitation on behalf of
// the attendee, we add the user to the SENT-BY attribute.
currentUser = [context activeUser];
if (b && ![[currentUser login] isEqualToString: [theOwnerUser login]])
{
NSString *currentEmail;
currentEmail = [[currentUser allEmails] objectAtIndex: 0];
[otherAttendee addAttribute: @"SENT-BY"
value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]];
}
iCalString = [[event parent] versitString];
[eventObject saveContentString: iCalString];
}
@ -219,12 +235,50 @@
else
rsvp = nil;
[eventObject saveContentString: [calendar versitString]];
if ([rsvp isEqualToString: @"true"])
[eventObject sendResponseToOrganizer: chosenEvent];
if ([rsvp isEqualToString: @"true"] &&
[chosenEvent isStillRelevant])
[eventObject sendResponseToOrganizer: chosenEvent
from: [context activeUser]];
organizerUID = [[chosenEvent organizer] uid];
if (organizerUID)
[self _updateAttendee: user withSequence: [chosenEvent sequence]
andCalUID: [chosenEvent uid] forUID: organizerUID];
[self _updateAttendee: user
ownerUser: [context activeUser]
forEventUID: [chosenEvent uid]
withSequence: [chosenEvent sequence]
forUID: organizerUID
shouldAddSentBy: YES];
// We update the calendar of all participants that are
// local to the system. This is useful in case user A accepts
// invitation from organizer B and users C, D, E who are also
// attendees need to verify if A has accepted.
NSArray *attendees;
iCalPerson *att;
NSString *uid;
int i;
attendees = [chosenEvent attendees];
for (i = 0; i < [attendees count]; i++)
{
att = [attendees objectAtIndex: i];
if (att == user) continue;
uid = [[LDAPUserManager sharedUserManager]
getUIDForEmail: [att rfc822Email]];
if (uid)
{
[self _updateAttendee: user
ownerUser: [context activeUser]
forEventUID: [chosenEvent uid]
withSequence: [chosenEvent sequence]
forUID: uid
shouldAddSentBy: YES];
}
}
response = [self responseWith204];
}
else