From 0ce1d4ed630007adad9af972f10782c2a58f4e4c Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Tue, 9 Dec 2008 15:29:39 +0000 Subject: [PATCH] Monotone-Parent: 0cec38c2db19c72bdff0ec74c3b4141bdc6cfeb4 Monotone-Revision: 383366b73218cb743a0be1ecef654d1c6aabd0a5 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2008-12-09T15:29:39 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 26 ++- SOPE/NGCards/iCalRepeatableEntityObject.m | 10 +- .../Appointments/SOGoAppointmentObject.h | 4 +- .../Appointments/SOGoAppointmentObject.m | 218 +++++++++++------- 4 files changed, 164 insertions(+), 94 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3bab83ebc..9e9f2a87a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2008-12-09 Francis Lachapelle + + * SoObjects/Appointments/SOGoAppointmentObject.m + ([SOGoAppointmentObject -_handleUpdatedEvent:fromOldEvent:]): if + the sequence doesn't change, attendees will no longer receive a + notification by email. + ([SOGoAppointmentObject + -_updateAttendee:ownerUser:forEventUID:withRecurrenceId:withSequence:forUID:shouldAddSentBy:]): + if an attendee accepts all events, on the master event of a + repeating event will be updated; occurrences will no longer be affected. + ([SOGoAppointmentObject -postCalDAVEventRequestTo:from:]): when + dealing with an occurrence of a repeating event, the function now + proprly update each attendee's calendar. + ([SOGoAppointmentObject + -takeAttendeeStatus:from:withRecurrenceId:]): fixed handling of an + occurrence of a repeating event. + ([SOGoAppointmentObject -postCalDAVEventReplyTo:from:]): idem. + 2008-12-08 Ludovic Marcotte * SoObjects/Appointments/SOGoAppointmentFolder.m @@ -14,17 +32,17 @@ * SoObjects/Appointments/SOGoAppointmentObject.m ([SOGoAppointmentObject - _removeEventFromUID:owner:withRecurrenceId:]): for a repeating + -_removeEventFromUID:owner:withRecurrenceId:]): for a repeating event, the occurrence was not properly removed. * SoObjects/Appointments/SOGoComponentOccurence.m - ([SOGoComponentOccurence prepareDelete]): for a repeating event, + ([SOGoComponentOccurence -prepareDelete]): for a repeating event, the exception date was not added and the occurence was not properly deleted. * UI/MailPartViewers/UIxMailPartICalViewer.m - ([UIxMailPartICalViewer isEventStoredInCalendar]): when dealing - with an occurence of a repeating event, the function now properly + ([UIxMailPartICalViewer -isEventStoredInCalendar]): when dealing + with an occurrence of a repeating event, the function now properly verify the presence of the occurence and not only the event. 2008-12-05 Ludovic Marcotte diff --git a/SOPE/NGCards/iCalRepeatableEntityObject.m b/SOPE/NGCards/iCalRepeatableEntityObject.m index 26214f5a6..4e68ed50b 100644 --- a/SOPE/NGCards/iCalRepeatableEntityObject.m +++ b/SOPE/NGCards/iCalRepeatableEntityObject.m @@ -118,11 +118,11 @@ [dateTime release]; } -- (void) setExceptionDates: (NSArray *) _rdates -{ - [children removeObjectsInArray: [self childrenWithTag: @"exdate"]]; - [self addChildren: _rdates]; -} +//- (void) setExceptionDates: (NSArray *) _rdates +//{ +// [children removeObjectsInArray: [self childrenWithTag: @"exdate"]]; +// [self addChildren: _rdates]; +//} - (BOOL) hasExceptionDates { diff --git a/SoObjects/Appointments/SOGoAppointmentObject.h b/SoObjects/Appointments/SOGoAppointmentObject.h index c15621498..e0d526922 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.h +++ b/SoObjects/Appointments/SOGoAppointmentObject.h @@ -50,7 +50,9 @@ - (NSException *) changeParticipationStatus: (NSString *) _status forRecurrenceId: (NSCalendarDate *) _recurrenceId; -- (void) takeAttendeeStatus: (iCalPerson *) attendee from: (NSString *) originator; +- (void) takeAttendeeStatus: (iCalPerson *) attendee + from: (NSString *) originator + withRecurrenceId: (NSCalendarDate*) recurrenceId; - (NSArray *) postCalDAVEventRequestTo: (NSArray *) recipients from: (NSString *) originator; - (NSArray *) postCalDAVEventReplyTo: (NSArray *) recipients from: (NSString *) originator; diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index d1fa4a833..c3f490986 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -162,8 +162,8 @@ SOGoAppointmentObject *object; NSString *possibleName; - folder = [container lookupCalendarFolderForUID: uid]; #warning Should call lookupCalendarFoldersForUIDs to search among all folders + folder = [container lookupCalendarFolderForUID: uid]; object = [folder lookupName: nameInContainer inContext: context acquire: NO]; if ([object isKindOfClass: [NSException class]]) @@ -221,6 +221,7 @@ NSString *calendarContent; int max, count; +#warning Should call lookupCalendarFoldersForUIDs to search among all folders folder = [container lookupCalendarFolderForUID: theUID]; object = [folder lookupName: nameInContainer inContext: context acquire: NO]; @@ -364,16 +365,16 @@ if ([changes sequenceShouldBeIncreased]) { [newEvent increaseSequence]; + // Set new attendees status to "needs action" [self _requireResponseFromAttendees: [newEvent attendees]]; + // Update attendees calendars and send them an update + // notification by email [self _handleSequenceUpdateInEvent: newEvent ignoringAttendees: attendees fromOldEvent: oldEvent]; } else { - // Set new attendees status to "needs action" - [self _requireResponseFromAttendees: attendees]; - // If other attributes have changed, update the event // in each attendee's calendar if ([[changes updatedProperties] count]) @@ -487,7 +488,6 @@ iCalCalendar *calendar; iCalEntityObject *event; iCalPerson *otherAttendee; - NSArray *events; NSString *iCalString, *recurrenceTime; NSException *error; @@ -501,7 +501,7 @@ // We must update main event and all its occurences (if any). calendar = [eventObject calendar: NO secure: NO]; event = (iCalEntityObject*)[calendar firstChildWithTag: [self componentTag]]; - events = [calendar allObjects]; + //events = [calendar allObjects]; } else { @@ -513,48 +513,41 @@ if (event == nil) // If no occurence found, create one event = [eventObject newOccurenceWithID: recurrenceTime]; - - events = [NSArray arrayWithObject: event]; } if ([[event sequence] compare: sequence] == NSOrderedSame) { SOGoUser *currentUser; - int i; currentUser = [context activeUser]; + otherAttendee = [event findParticipant: theOwnerUser]; + [otherAttendee setPartStat: [attendee partStat]]; - for (i = 0; i < [events count]; i++) + // If one has accepted / declined an invitation on behalf of + // the attendee, we add the user to the SENT-BY attribute. + if (b && ![[currentUser login] isEqualToString: [theOwnerUser login]]) { - event = [events objectAtIndex: i]; - - 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. - if (b && ![[currentUser login] isEqualToString: [theOwnerUser login]]) - { - NSString *currentEmail; - currentEmail = [[currentUser allEmails] objectAtIndex: 0]; - [otherAttendee addAttribute: @"SENT-BY" - value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]]; - } - else - { - // We must REMOVE any SENT-BY here. This is important since if A accepted - // the event for B and then, B changes by himself his participation status, - // we don't want to keep the previous SENT-BY attribute there. - [(NSMutableDictionary *)[otherAttendee attributes] removeObjectForKey: @"SENT-BY"]; - } + NSString *currentEmail; + currentEmail = [[currentUser allEmails] objectAtIndex: 0]; + [otherAttendee addAttribute: @"SENT-BY" + value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]]; + } + else + { + // We must REMOVE any SENT-BY here. This is important since if A accepted + // the event for B and then, B changes by himself his participation status, + // we don't want to keep the previous SENT-BY attribute there. + [(NSMutableDictionary *)[otherAttendee attributes] removeObjectForKey: @"SENT-BY"]; } - - iCalString = [[event parent] versitString]; - error = [eventObject saveContentString: iCalString]; } + + // We generate the updated iCalendar file and we save it + // in the database. + iCalString = [[event parent] versitString]; + error = [eventObject saveContentString: iCalString]; } - + return error; } @@ -623,6 +616,7 @@ organizerUID = [[(iCalEntityObject*)[[event parent] firstChildWithTag: [self componentTag]] organizer] uid]; if (organizerUID) + // Update the attendee in organizer's calendar. ex = [self _updateAttendee: attendee ownerUser: theOwnerUser forEventUID: [event uid] @@ -699,13 +693,15 @@ { NSMutableArray *elements; NSEnumerator *recipientsEnum; - NSString *recipient, *uid; + NSString *recipient, *uid, *ownerUID; iCalEvent *event, *oldEvent; iCalPerson *person; BOOL isUpdate, hasChanged; elements = [NSMutableArray array]; - + + ownerUID = [[LDAPUserManager sharedUserManager] + getUIDForEmail: originator]; event = [self component: NO secure: NO]; recipientsEnum = [recipients objectEnumerator]; while ((recipient = [recipientsEnum nextObject])) @@ -722,24 +718,65 @@ { // We check if we must send an invitation update // rather than just a normal invitation + NSString *iCalString; SOGoAppointmentObject *oldEventObject; - iCalEventChanges *changes; oldEventObject = [self _lookupEvent: [event uid] forUID: uid]; - oldEvent = [oldEventObject component: NO secure: NO]; - changes = [event getChangesRelativeToEvent: oldEvent]; - if ([[oldEvent sequence] compare: [event sequence]] != NSOrderedSame) + if (![oldEventObject isNew]) { - if ([changes sequenceShouldBeIncreased]) - isUpdate = YES; + // We are updating an existing event. + // If the event containts a recurrence-id, replace the proper + // occurrence of the recurrent event. + iCalCalendar *calendar; + iCalEvent *currentOccurence; + iCalEventChanges *changes; + NSArray *occurences; + NSCalendarDate *recurrenceId, *currentId; + NSString *recurrenceTime; + unsigned int i; + + calendar = [oldEventObject calendar: NO secure: NO]; + recurrenceId = [event recurrenceId]; + if (recurrenceId == nil) + oldEvent = [oldEventObject component: NO secure: NO]; else - hasChanged = NO; + { + // If recurrenceId is defined, find the specified occurence + // within the repeating vEvent and replace it. + occurences = [calendar events]; + for (i = 1; i< [occurences count]; i++) + { + currentOccurence = [occurences objectAtIndex: i]; + currentId = [currentOccurence recurrenceId]; + if ([currentId compare: recurrenceId] == NSOrderedSame) + { + [[calendar children] removeObject: currentOccurence]; + oldEvent = currentOccurence; + break; + } + } + // Add the event as a new occurrence, without the organizer. + [event setOrganizer: nil]; + [calendar addChild: event]; + } + + // Identify changes in order to send a notification to the attendee + // if necessary and with the proper template. + changes = [event getChangesRelativeToEvent: oldEvent]; + if ([[oldEvent sequence] compare: [event sequence]] != NSOrderedSame) + { + if ([changes sequenceShouldBeIncreased]) + isUpdate = YES; + else + hasChanged = NO; + } } - [self _addOrUpdateEvent: event - forUID: uid - owner: [[LDAPUserManager sharedUserManager] - getUIDForEmail: originator]]; + + // We generate the updated iCalendar file and we save it + // in the database. + iCalString = [[event parent] versitString]; + [oldEventObject saveContentString: iCalString]; } #warning fix this when sendEmailUsing blabla has been cleaned up if (hasChanged) @@ -764,12 +801,14 @@ { NSMutableArray *elements; NSEnumerator *recipientsEnum; - NSString *recipient, *uid; + NSString *recipient, *ownerUID, *uid; iCalEvent *event; iCalPerson *person; elements = [NSMutableArray array]; + ownerUID = [[LDAPUserManager sharedUserManager] + getUIDForEmail: originator]; event = [self component: NO secure: NO]; recipientsEnum = [recipients objectEnumerator]; while ((recipient = [recipientsEnum nextObject])) @@ -780,8 +819,7 @@ uid = [person uid]; if (uid) [self _removeEventFromUID: uid - owner: [[LDAPUserManager sharedUserManager] - getUIDForEmail: originator] + owner: ownerUID withRecurrenceId: [event recurrenceId]]; #warning fix this when sendEmailUsing blabla has been cleaned up [self sendEMailUsingTemplateNamed: @"Deletion" @@ -808,42 +846,54 @@ // be propagated to the organizer and the other attendees. // - (void) takeAttendeeStatus: (iCalPerson *) attendee - from: (NSString *) originator + from: (NSString *) ownerUser + withRecurrenceId: (NSCalendarDate*) recurrenceId { iCalPerson *localAttendee; iCalEvent *event; - SOGoUser *ownerUser; + NSString *recurrenceTime; - event = [self component: NO secure: NO]; + if (recurrenceId == nil) + // We must update the master event only. + event = [self component: NO secure: NO]; + else + { + // If recurrenceId is defined, find the specified occurence + // within the repeating vEvent. + recurrenceTime = [NSString stringWithFormat: @"%f", [recurrenceId timeIntervalSince1970]]; + event = [self lookupOccurence: recurrenceTime]; + + if (event == nil) + // If no occurence found, create one + event = [self newOccurenceWithID: recurrenceTime]; + } + + // Find attendee within event localAttendee = [event findParticipantWithEmail: [attendee rfc822Email]]; if (localAttendee) { + // Update the attendee's status [localAttendee setPartStat: [attendee partStat]]; [self saveComponent: event]; - - /// TEST /// - NSArray *attendees; - iCalPerson *att; - NSString *uid; - int i; - - ownerUser = [SOGoUser userWithLogin:[[LDAPUserManager sharedUserManager] - getUIDForEmail: originator] - roles: nil]; - - // We update the copy of the organizer, only - // if it's a local user. + + NSArray *attendees; + iCalPerson *att; + NSString *uid; + int i; + + // 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] - withRecurrenceId: [event recurrenceId] - withSequence: [event sequence] - forUID: uid - shouldAddSentBy: NO]; - + uid = [[event organizer] uid]; + if (uid) + [self _updateAttendee: attendee + ownerUser: ownerUser + forEventUID: [event uid] + withRecurrenceId: [event recurrenceId] + withSequence: [event sequence] + forUID: uid + shouldAddSentBy: NO]; + attendees = [event attendees]; for (i = 0; i < [attendees count]; i++) @@ -854,15 +904,15 @@ uid = [[LDAPUserManager sharedUserManager] getUIDForEmail: [att rfc822Email]]; - + if (uid) { - // We skip the update that correspond to the originator + // We skip the update that correspond to the owner // 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] @@ -872,8 +922,6 @@ shouldAddSentBy: NO]; } } - - /// TEST /// } else [self errorWithFormat: @"attendee not found: '%@'", attendee]; @@ -892,7 +940,6 @@ elements = [NSMutableArray array]; event = [self component: NO secure: NO]; - //ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: [[LDAPUserManager sharedUserManager] getUIDForEmail: originator] @@ -914,8 +961,11 @@ [recipientEvent saveComponent: event]; else [recipientEvent takeAttendeeStatus: attendee - from: originator]; + from: ownerUser + withRecurrenceId: [event recurrenceId]]; } + + // Send reply to recipient/organizer [self sendIMIPReplyForEvent: event from: ownerUser to: person];