From 03a125ea1f1a0736aecac27198621e1c3e131a8f Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Tue, 10 Jul 2012 00:29:13 +0000 Subject: [PATCH] See ChangeLog Monotone-Parent: 801c13ca7d8e3a2f3e502ee658399b458681bcab Monotone-Revision: cf43f2030dbd1c4f0747be7cbd5dc3239cd6bd15 Monotone-Author: ludovic@Sophos.ca Monotone-Date: 2012-07-10T00:29:13 --- ChangeLog | 19 +++ .../Appointments/SOGoAppointmentFolder.h | 15 +- .../Appointments/SOGoAppointmentFolder.m | 78 +++++++++++ .../Appointments/SOGoAppointmentObject.m | 102 +++++++++----- SoObjects/Appointments/SOGoAptMailReceipt.h | 29 ++-- SoObjects/Appointments/SOGoAptMailReceipt.m | 75 +++++++--- .../Appointments/SOGoCalendarComponent.h | 7 +- .../Appointments/SOGoCalendarComponent.m | 128 +++++++++++------- SoObjects/SOGo/SOGoConstants.h | 7 + SoObjects/SOGo/SOGoDomainDefaults.h | 2 + SoObjects/SOGo/SOGoDomainDefaults.m | 10 ++ SoObjects/SOGo/SOGoUserDefaults.h | 5 +- SoObjects/SOGo/SOGoUserDefaults.m | 12 +- UI/Scheduler/UIxCalendarProperties.h | 13 +- UI/Scheduler/UIxCalendarProperties.m | 43 +++++- .../SOGoAptMailDeletionReceipt.wox | 30 ---- .../SOGoAptMailInvitationReceipt.wox | 31 ----- .../Appointments/SOGoAptMailReceipt.wox | 54 ++++++++ .../Appointments/SOGoAptMailUpdateReceipt.wox | 27 ---- .../SchedulerUI/UIxCalendarProperties.wox | 23 ++++ UI/WebServerResources/SchedulerUI.js | 4 +- 21 files changed, 480 insertions(+), 234 deletions(-) delete mode 100644 UI/Templates/Appointments/SOGoAptMailDeletionReceipt.wox delete mode 100644 UI/Templates/Appointments/SOGoAptMailInvitationReceipt.wox create mode 100644 UI/Templates/Appointments/SOGoAptMailReceipt.wox delete mode 100644 UI/Templates/Appointments/SOGoAptMailUpdateReceipt.wox diff --git a/ChangeLog b/ChangeLog index 534c8483a..dc5736909 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2012-07-09 Ludovic Marcotte + + * Dropped old templates (SOGoAptMailDeletionReceipt.wox + SOGoAptMailInvitationReceipt.wox and SOGoAptMailUpdateReceipt.wox) + which are in fact replaced by SOGoAptMailReceipt.wox. File added + to the repository. + + * Dropped SOGoAppointmentSendEMailReceipts + + * Added two new domain defaults: SOGoNotifyOnPersonalModifications + and SOGoNotifyOnExternalModifications. They allow users to be notified + when modifying their own calendars or when someone else to it. These + defaults are over-writable by users from their calendar properties window. + + * Implemented the code related to the two new defaults together with a + third option - which is to notify a specific person when one modifies + his/her calendar. This commit is partial as more testing is required + and some code changes to trigger the right notifications. + 2012-07-09 Jean Raby * Tools/SOGoToolUserPreferences.m: diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.h b/SoObjects/Appointments/SOGoAppointmentFolder.h index 3e058fc0f..ee703b1d5 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.h +++ b/SoObjects/Appointments/SOGoAppointmentFolder.h @@ -2,14 +2,14 @@ Copyright (C) 2004-2005 SKYRIX Software AG Copyright (C) 2007-2012 Inverse inc. - This file is part of OpenGroupware.org. + This file is part of SOGo. - OGo is free software; you can redistribute it and/or modify it under + SOGo 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 + SOGo 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. @@ -163,6 +163,15 @@ typedef enum { - (BOOL) includeInFreeBusy; - (void) setIncludeInFreeBusy: (BOOL) newInclude; +- (BOOL) notifyOnPersonalModifications; +- (void) setNotifyOnPersonalModifications: (BOOL) b; +- (BOOL) notifyOnExternalModifications; +- (void) setNotifyOnExternalModifications: (BOOL) b; +- (BOOL) notifyUserOnPersonalModifications; +- (void) setNotifyUserOnPersonalModifications: (BOOL) b; +- (NSString *) notifiedUserOnPersonalModifications; +- (void) setNotifiedUserOnPersonalModifications: (NSString *) theUser; + - (NSString *) importComponent: (iCalEntityObject *) event timezone: (iCalTimeZone *) timezone; diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 0a2dd4b18..864d0ec26 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -434,6 +434,84 @@ static NSNumber *sharedYes = nil; inCategory: @"FreeBusyExclusions"]; } +- (BOOL) _notificationValueForKey: (NSString *) theKey + defaultDomainKey: (NSString *) theDomainKey +{ + SOGoUser *ownerUser; + NSNumber *notify; + + ownerUser = [SOGoUser userWithLogin: self->owner]; + notify = [self folderPropertyValueInCategory: theKey + forUser: ownerUser]; + + if (!notify && theDomainKey) + notify = [NSNumber numberWithBool: [[[context activeUser] domainDefaults] + boolForKey: theDomainKey]]; + + return [notify boolValue]; +} + +// +// We MUST keep the 'NO' value here, because we will always +// fallback to the domain defaults otherwise. +// +- (BOOL) _setNotificationValue: (BOOL) b + forKey: (NSString *) theKey +{ + [self setFolderPropertyValue: [NSNumber numberWithBool: b] + inCategory: theKey]; +} + +- (BOOL) notifyOnPersonalModifications +{ + return [self _notificationValueForKey: @"NotifyOnPersonalModifications" + defaultDomainKey: @"SOGoNotifyOnPersonalModifications"]; +} + +- (void) setNotifyOnPersonalModifications: (BOOL) b +{ + [self _setNotificationValue: b forKey: @"NotifyOnPersonalModifications"]; +} + +- (BOOL) notifyOnExternalModifications +{ + return [self _notificationValueForKey: @"NotifyOnExternalModifications" + defaultDomainKey: @"SOGoNotifyOnExternalModifications"]; +} + +- (void) setNotifyOnExternalModifications: (BOOL) b +{ + [self _setNotificationValue: b forKey: @"NotifyOnExternalModifications"]; +} + +- (BOOL) notifyUserOnPersonalModifications +{ + return [self _notificationValueForKey: @"NotifyUserOnPersonalModifications" + defaultDomainKey: nil]; +} + +- (void) setNotifyUserOnPersonalModifications: (BOOL) b +{ + [self _setNotificationValue: b forKey: @"NotifyUserOnPersonalModifications"]; + +} + +- (NSString *) notifiedUserOnPersonalModifications +{ + SOGoUser *ownerUser; + + ownerUser = [SOGoUser userWithLogin: self->owner]; + + return [self folderPropertyValueInCategory: @"NotifiedUserOnPersonalModifications" + forUser: ownerUser]; +} + +- (void) setNotifiedUserOnPersonalModifications: (NSString *) theUser +{ + [self setFolderPropertyValue: theUser + inCategory: @"NotifiedUserOnPersonalModifications"]; +} + /* selection */ - (NSArray *) calendarUIDs diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index ad50e0ddf..2822535ab 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -40,6 +40,7 @@ #import +#import #import #import #import @@ -415,8 +416,13 @@ previousObject: oldEvent toAttendees: updateAttendees withType: @"calendar:invitation-update"]; - [self sendReceiptEmailUsingTemplateNamed: @"Update" - forObject: newEvent to: updateAttendees]; + +#if 0 + [self sendReceiptEmailForObject: newEvent + addedAttendees: nil + deletedAttendees: nil + updatedAttendees: updateAttendees]; +#endif } // @@ -647,10 +653,14 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent - (NSException *) _handleUpdatedEvent: (iCalEvent *) newEvent fromOldEvent: (iCalEvent *) oldEvent { + NSArray *addedAttendees, *deletedAttendees, *updatedAttendees; iCalEventChanges *changes; - NSArray *attendees; NSException *ex; + addedAttendees = nil; + deletedAttendees = nil; + updatedAttendees = nil; + changes = [newEvent getChangesRelativeToEvent: oldEvent]; if ([changes sequenceShouldBeIncreased]) { @@ -662,36 +672,34 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent changes = [newEvent getChangesRelativeToEvent: oldEvent]; } - attendees = [changes deletedAttendees]; + deletedAttendees = [changes deletedAttendees]; // We delete the attendees in all exception occurences, if // the attendees were removed from the master event. - [self _addOrDeleteAttendees: attendees + [self _addOrDeleteAttendees: deletedAttendees inRecurrenceExceptionsForEvent: newEvent add: NO]; - if ([attendees count]) + if ([deletedAttendees count]) { - [self _handleRemovedUsers: attendees + [self _handleRemovedUsers: deletedAttendees withRecurrenceId: [newEvent recurrenceId]]; [self sendEMailUsingTemplateNamed: @"Deletion" forObject: [newEvent itipEntryWithMethod: @"cancel"] previousObject: oldEvent - toAttendees: attendees + toAttendees: deletedAttendees withType: @"calendar:cancellation"]; - [self sendReceiptEmailUsingTemplateNamed: @"Deletion" - forObject: newEvent to: attendees]; } if ((ex = [self _handleResourcesConflicts: [newEvent attendees] forEvent: newEvent])) return ex; - attendees = [changes insertedAttendees]; + addedAttendees = [changes insertedAttendees]; // We insert the attendees in all exception occurences, if // the attendees were added to the master event. - [self _addOrDeleteAttendees: attendees + [self _addOrDeleteAttendees: addedAttendees inRecurrenceExceptionsForEvent: newEvent add: YES]; @@ -701,7 +709,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent // Update attendees calendars and send them an update // notification by email [self _handleSequenceUpdateInEvent: newEvent - ignoringAttendees: attendees + ignoringAttendees: addedAttendees fromOldEvent: oldEvent]; } else @@ -713,7 +721,6 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent NSEnumerator *enumerator; iCalPerson *currentAttendee; NSString *currentUID; - NSArray *updatedAttendees; updatedAttendees = [newEvent attendees]; enumerator = [updatedAttendees objectEnumerator]; @@ -725,28 +732,28 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent forUID: currentUID owner: owner]; } - - [self sendReceiptEmailUsingTemplateNamed: @"Update" - forObject: newEvent - to: updatedAttendees]; } } - if ([attendees count]) + if ([addedAttendees count]) { // Send an invitation to new attendees - if ((ex = [self _handleAddedUsers: attendees fromEvent: newEvent])) + if ((ex = [self _handleAddedUsers: addedAttendees fromEvent: newEvent])) return ex; [self sendEMailUsingTemplateNamed: @"Invitation" forObject: [newEvent itipEntryWithMethod: @"request"] previousObject: oldEvent - toAttendees: attendees + toAttendees: addedAttendees withType: @"calendar:invitation"]; - [self sendReceiptEmailUsingTemplateNamed: @"Invitation" - forObject: newEvent to: attendees]; } + [self sendReceiptEmailForObject: newEvent + addedAttendees: addedAttendees + deletedAttendees: deletedAttendees + updatedAttendees: updatedAttendees + operation: EventUpdated]; + return nil; } @@ -809,9 +816,13 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent previousObject: nil toAttendees: attendees withType: @"calendar:invitation"]; - [self sendReceiptEmailUsingTemplateNamed: @"Invitation" - forObject: newEvent to: attendees]; } + + [self sendReceiptEmailForObject: newEvent + addedAttendees: attendees + deletedAttendees: nil + updatedAttendees: nil + operation: EventCreated]; } else { @@ -1117,9 +1128,11 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent previousObject: nil toAttendees: delegates withType: @"calendar:cancellation"]; +#if 0 [self sendReceiptEmailUsingTemplateNamed: @"Deletion" forObject: event to: delegates]; +#endif } if (addDelegate) @@ -1139,8 +1152,10 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent previousObject: nil toAttendees: delegates withType: @"calendar:invitation"]; +#if 0 [self sendReceiptEmailUsingTemplateNamed: @"Invitation" forObject: event to: delegates]; +#endif } // We generate the updated iCalendar file and we save it in the database. @@ -1455,10 +1470,20 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent previousObject: nil toAttendees: attendees withType: @"calendar:cancellation"]; - [self sendReceiptEmailUsingTemplateNamed: @"Deletion" - forObject: occurence - to: attendees]; } + + iCalPerson *foo = [[iCalPerson alloc] init]; + + [foo setCn: @"Ludovic Marcotte"]; + [foo setEmail: @"lmarcotte@inverse.ca"]; + + NSArray *zot = [NSArray arrayWithObject: foo]; + +#if 0 + [self sendReceiptEmailUsingTemplateNamed: @"Deletion" + forObject: occurence + to: foo]; +#endif } else if ([occurence userIsAttendee: ownerUser]) // The current user deletes the occurence; let the organizer know that @@ -1757,11 +1782,13 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent iCalCalendar *calendar; SOGoUser *ownerUser; iCalEvent *event, *conflictingEvent; - + NSArray *attendees; + NSString *eventUID; BOOL scheduling; calendar = [iCalCalendar parseSingleFromSource: [rq contentAsString]]; + attendees = nil; event = [[calendar events] objectAtIndex: 0]; eventUID = [event uid]; @@ -1772,8 +1799,8 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent // TODO: send out a no-uid-conflict (DAV:href) xml element (rfc4791 section 5.3.2.1) if (conflictingEvent = [container resourceNameForEventUID: eventUID]) { - NSString *reason = [NSString stringWithFormat: @"Event UID already in use. (%s)", eventUID]; - return [NSException exceptionWithHTTPStatus:403 reason: reason]; + return [NSException exceptionWithHTTPStatus: 403 + reason: [NSString stringWithFormat: @"Event UID already in use. (%s)", eventUID]]; } // @@ -1781,8 +1808,6 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent // if (scheduling && [event userIsOrganizer: ownerUser]) { - NSArray *attendees; - attendees = [event attendeesWithoutUser: ownerUser]; if ([attendees count]) { @@ -1801,8 +1826,6 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent previousObject: nil toAttendees: attendees withType: @"calendar:invitation"]; - [self sendReceiptEmailUsingTemplateNamed: @"Invitation" - forObject: event to: attendees]; } } // @@ -1816,6 +1839,13 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent from: ownerUser to: [event organizer]]; } + + + [self sendReceiptEmailForObject: event + addedAttendees: attendees + deletedAttendees: nil + updatedAttendees: nil + operation: EventCreated]; } else { @@ -2015,7 +2045,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent } } } - } + } // else of if (isNew) ... // We must NOT invoke [super PUTAction:] here as it'll resave // the content string and we could have etag mismatches. diff --git a/SoObjects/Appointments/SOGoAptMailReceipt.h b/SoObjects/Appointments/SOGoAptMailReceipt.h index 58dbae3b9..dcc6fea6e 100644 --- a/SoObjects/Appointments/SOGoAptMailReceipt.h +++ b/SoObjects/Appointments/SOGoAptMailReceipt.h @@ -1,8 +1,9 @@ /* SOGoAptMailReceipt.h - this file is part of SOGo * - * Copyright (C) 2009 Inverse inc. + * Copyright (C) 2009-2012 Inverse inc. * * Author: Wolfgang Sourdeau + * Ludovic Marcotte * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,31 +28,27 @@ @class NSArray; @class NSString; - @class iCalPerson; +#import + @interface SOGoAptMailReceipt : SOGoAptMailNotification { NSString *originator; - NSArray *recipients; + NSArray *addedAttendees; + NSArray *deletedAttendees; + NSArray *updatedAttendees; iCalPerson *currentRecipient; + SOGoEventOperation operation; BOOL isSubject; } - (void) setOriginator: (NSString *) newOriginator; -- (void) setRecipients: (NSArray *) newRecipients; - -@end - -@interface SOGoAptMailInvitationReceipt : SOGoAptMailReceipt - -@end - -@interface SOGoAptMailUpdateReceipt : SOGoAptMailReceipt - -@end - -@interface SOGoAptMailDeletionReceipt : SOGoAptMailReceipt +- (void) setAddedAttendees: (NSArray *) theAttendees; +- (void) setDeletedAttendees: (NSArray *) theAttendees; +- (void) setUpdatedAttendees: (NSArray *) theAttendees; +- (void) setOperation: (SOGoEventOperation) theOperation; +- (NSString *) subject; @end diff --git a/SoObjects/Appointments/SOGoAptMailReceipt.m b/SoObjects/Appointments/SOGoAptMailReceipt.m index 6a6c70bfb..0cd5bf379 100644 --- a/SoObjects/Appointments/SOGoAptMailReceipt.m +++ b/SoObjects/Appointments/SOGoAptMailReceipt.m @@ -3,6 +3,7 @@ * Copyright (C) 2009-2012 Inverse inc. * * Author: Wolfgang Sourdeau + * Ludovic Marcotte * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,7 +58,9 @@ static NSCharacterSet *wsSet = nil; if ((self = [super init])) { originator = nil; - recipients = nil; + addedAttendees = nil; + deletedAttendees = nil; + updatedAttendees = nil; isSubject = NO; } @@ -67,7 +70,9 @@ static NSCharacterSet *wsSet = nil; - (void) dealloc { [originator release]; - [recipients release]; + [addedAttendees release]; + [deletedAttendees release]; + [updatedAttendees release]; [super dealloc]; } @@ -112,14 +117,34 @@ static NSCharacterSet *wsSet = nil; ASSIGN (originator, newOriginator); } -- (void) setRecipients: (NSArray *) newRecipients +- (void) setAddedAttendees: (NSArray *) theAttendees; { - ASSIGN (recipients, newRecipients); + ASSIGN (addedAttendees, theAttendees); } -- (NSArray *) recipients +- (NSArray *) addedAttendees; { - return recipients; + return addedAttendees; +} + +- (void) setDeletedAttendees: (NSArray *) theAttendees; +{ + ASSIGN (deletedAttendees, theAttendees); +} + +- (NSArray *) deletedAttendees; +{ + return deletedAttendees; +} + +- (NSArray *) updatedAttendes +{ + return updatedAttendees; +} + +- (void) setUpdatedAttendees: (NSArray *) theAttendees +{ + ASSIGN (updatedAttendees, theAttendees); } - (void) setCurrentRecipient: (iCalPerson *) newCurrentRecipient @@ -132,6 +157,32 @@ static NSCharacterSet *wsSet = nil; return currentRecipient; } +- (void) setOperation: (SOGoEventOperation) theOperation +{ + operation = theOperation; +} + +- (NSString *) subject +{ + NSString *s; + switch (operation) + { + case EventCreated: + s = @"Receipt: event was created"; + break; + + case EventDeleted: + s = @"Receipt: event was deleted"; + break; + + case EventUpdated: + default: + s = @"Receipt: event was updated"; + } + + return s; +} + - (NSString *) _formattedUserDate: (NSCalendarDate *) date { SOGoDateFormatter *formatter; @@ -165,15 +216,3 @@ static NSCharacterSet *wsSet = nil; } @end - -@implementation SOGoAptMailInvitationReceipt : SOGoAptMailReceipt - -@end - -@implementation SOGoAptMailUpdateReceipt : SOGoAptMailReceipt - -@end - -@implementation SOGoAptMailDeletionReceipt : SOGoAptMailReceipt - -@end diff --git a/SoObjects/Appointments/SOGoCalendarComponent.h b/SoObjects/Appointments/SOGoCalendarComponent.h index f3c341763..d334e7c57 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.h +++ b/SoObjects/Appointments/SOGoCalendarComponent.h @@ -75,9 +75,10 @@ - (void) sendResponseToOrganizer: (iCalRepeatableEntityObject *) newComponent from: (SOGoUser *) owner; -- (void) sendReceiptEmailUsingTemplateNamed: (NSString *) template - forObject: (iCalRepeatableEntityObject *) object - to: (NSArray *) recipients; +- (void) sendReceiptEmailForObject: (iCalRepeatableEntityObject *) object + addedAttendees: (NSArray *) theAddedAttendees + deletedAttendees: (NSArray *) theDeletedAttendees + updatedAttendees: (NSArray *) theUpdatedAttendees; - (iCalPerson *) findParticipantWithUID: (NSString *) uid; diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index 9719dcab2..811dbf734 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -760,6 +760,9 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, return bodyPart; } +// +// +// - (void) sendEMailUsingTemplateNamed: (NSString *) newPageName forObject: (iCalRepeatableEntityObject *) object previousObject: (iCalRepeatableEntityObject *) previousObject @@ -994,76 +997,99 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, } } -- (void) sendReceiptEmailUsingTemplateNamed: (NSString *) template - forObject: (iCalRepeatableEntityObject *) object - to: (NSArray *) attendees +- (void) sendReceiptEmailForObject: (iCalRepeatableEntityObject *) object + addedAttendees: (NSArray *) theAddedAttendees + deletedAttendees: (NSArray *) theDeletedAttendees + updatedAttendees: (NSArray *) theUpdatedAttendees + operation: (SOGoEventOperation) theOperation { - NSString *pageName, *mailDate, *mailText, *fullSenderEmail, *senderEmail; + NSString *mailDate, *mailText, *fullSenderEmail, *senderEmail, *fullRecipientEmail, *recipientEmail; + NSDictionary *senderIdentity, *recipientIdentity; SOGoAptMailReceipt *page; NGMutableHashMap *headerMap; NGMimeMessage *msg; SOGoUser *currentUser; SOGoDomainDefaults *dd; - NSDictionary *identity; + // We must handle three cases here: + // - Receive a mail when I modify my calendar + // - Receive a mail when someone else modifies my calendar + // - When I modify my calendar, send a mail to: + + // We first built the template that we'll slightly adjust for our three use-cases + page = [[WOApplication application] pageWithName: @"SOGoAptMailReceipt" + inContext: context]; + [page setApt: (iCalEvent *) object]; + [page setAddedAttendees: theAddedAttendees]; + [page setDeletedAttendees: theDeletedAttendees]; + [page setUpdatedAttendees: theUpdatedAttendees]; + [page setOperation: theOperation]; + currentUser = [context activeUser]; - if ([[currentUser userDefaults] appointmentSendEMailReceipts] - && [attendees count]) - { - pageName = [NSString stringWithFormat: @"SOGoAptMail%@Receipt", - template]; - page = [[WOApplication application] pageWithName: pageName - inContext: context]; - [page setApt: (iCalEvent *) object]; - [page setRecipients: attendees]; + senderIdentity = [currentUser primaryIdentity]; - identity = [currentUser primaryIdentity]; + dd = [currentUser domainDefaults]; - /* construct message */ #warning SOPE is just plain stupid here - if you change the case of keys, it will break the encoding of fields - headerMap = [NGMutableHashMap hashMapWithCapacity: 5]; - fullSenderEmail = [identity keysWithFormat: @"%{fullName} <%{email}>"]; - [headerMap setObject: fullSenderEmail forKey: @"from"]; - [headerMap setObject: fullSenderEmail forKey: @"to"]; - mailDate = [[NSCalendarDate date] rfc822DateString]; - [headerMap setObject: mailDate forKey: @"date"]; - [headerMap setObject: [page getSubject] forKey: @"subject"]; - [headerMap setObject: @"1.0" forKey: @"MIME-Version"]; - [headerMap setObject: @"text/plain; charset=utf-8" - forKey: @"content-type"]; - msg = [NGMimeMessage messageWithHeader: headerMap]; + headerMap = [NGMutableHashMap hashMapWithCapacity: 5]; + + // Sender can vary, base on whom modifies the actual event (owner vs. someone else) + senderEmail = [senderIdentity objectForKey: @"email"]; + fullSenderEmail = [senderIdentity keysWithFormat: @"%{fullName} <%{email}>"]; + [headerMap setObject: fullSenderEmail forKey: @"from"]; - /* text part */ - mailText = [page getBody]; - [msg setBody: [mailText dataUsingEncoding: NSUTF8StringEncoding]]; + // Recipient is fixed, which is the calendar owner + currentUser = [SOGoUser userWithLogin: self->owner]; + recipientIdentity = [currentUser primaryIdentity]; + recipientEmail = [recipientIdentity objectForKey: @"email"]; + fullRecipientEmail = [recipientIdentity keysWithFormat: @"%{fullName} <%{email}>"]; + + [headerMap setObject: fullRecipientEmail forKey: @"to"]; - /* send the damn thing */ - senderEmail = [identity objectForKey: @"email"]; - dd = [currentUser domainDefaults]; + mailDate = [[NSCalendarDate date] rfc822DateString]; + [headerMap setObject: mailDate forKey: @"date"]; + [headerMap setObject: [page getSubject] forKey: @"subject"]; + [headerMap setObject: @"1.0" forKey: @"MIME-Version"]; + [headerMap setObject: @"text/plain; charset=utf-8" + forKey: @"content-type"]; + msg = [NGMimeMessage messageWithHeader: headerMap]; + + /* text part */ + mailText = [page getBody]; + [msg setBody: [mailText dataUsingEncoding: NSUTF8StringEncoding]]; + + if ([self->owner isEqualToString: [currentUser login]]) + { + if ([[self container] notifyOnPersonalModifications]) + { + [[SOGoMailer mailerWithDomainDefaults: dd] + sendMimePart: msg + toRecipients: [NSArray arrayWithObject: recipientEmail] + sender: senderEmail]; + } + + if ([[self container] notifyUserOnPersonalModifications]) + { + recipientEmail = [[self container] notifiedUserOnPersonalModifications]; + [[SOGoMailer mailerWithDomainDefaults: dd] + sendMimePart: msg + toRecipients: [NSArray arrayWithObject: recipientEmail] + sender: senderEmail]; + } + } + + + if ([[self container] notifyOnExternalModifications] && + ![self->owner isEqualToString: [currentUser login]]) + { [[SOGoMailer mailerWithDomainDefaults: dd] sendMimePart: msg - toRecipients: [NSArray arrayWithObject: senderEmail] + toRecipients: [NSArray arrayWithObject: recipientEmail] sender: senderEmail]; } + } -// - (BOOL) isOrganizerOrOwner: (SOGoUser *) user -// { -// BOOL isOrganizerOrOwner; -// iCalRepeatableEntityObject *component; -// NSString *organizerEmail; - -// component = [self component: NO]; -// organizerEmail = [[component organizer] rfc822Email]; -// if (component && [organizerEmail length] > 0) -// isOrganizerOrOwner = [user hasEmail: organizerEmail]; -// else -// isOrganizerOrOwner -// = [[container ownerInContext: context] isEqualToString: [user login]]; - -// return isOrganizerOrOwner; -// } - - (iCalPerson *) findParticipantWithUID: (NSString *) uid { iCalEntityObject *component; diff --git a/SoObjects/SOGo/SOGoConstants.h b/SoObjects/SOGo/SOGoConstants.h index 08d16101c..433760346 100644 --- a/SoObjects/SOGo/SOGoConstants.h +++ b/SoObjects/SOGo/SOGoConstants.h @@ -44,4 +44,11 @@ typedef enum // Domain defaults extern NSString *SOGoPasswordChangeEnabled; +typedef enum +{ + EventCreated = 0, + EventDeleted = 1, + EventUpdated = 2, +} SOGoEventOperation; + #endif /* _SOGOCONSTANTS_H_ */ diff --git a/SoObjects/SOGo/SOGoDomainDefaults.h b/SoObjects/SOGo/SOGoDomainDefaults.h index fbed067ee..2e44b32a0 100644 --- a/SoObjects/SOGo/SOGoDomainDefaults.h +++ b/SoObjects/SOGo/SOGoDomainDefaults.h @@ -78,6 +78,8 @@ - (BOOL) hideSystemEMail; - (int) searchMinimumWordLength; +- (BOOL) notifyOnPersonalModifications; +- (BOOL) notifyOnExternalModifications; @end diff --git a/SoObjects/SOGo/SOGoDomainDefaults.m b/SoObjects/SOGo/SOGoDomainDefaults.m index 6fe2abb7a..4b1db7b0f 100644 --- a/SoObjects/SOGo/SOGoDomainDefaults.m +++ b/SoObjects/SOGo/SOGoDomainDefaults.m @@ -324,4 +324,14 @@ return [self integerForKey: @"SOGoSearchMinimumWordLength"]; } +- (BOOL) notifyOnPersonalModifications +{ + return [self boolForKey: @"SOGoNotifyOnPersonalModifications"]; +} + +- (BOOL) notifyOnExternalModifications +{ + return [self boolForKey: @"SOGoNotifyOnExternalModifications"]; +} + @end diff --git a/SoObjects/SOGo/SOGoUserDefaults.h b/SoObjects/SOGo/SOGoUserDefaults.h index 0c82a6c75..287d0a0ca 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.h +++ b/SoObjects/SOGo/SOGoUserDefaults.h @@ -1,6 +1,6 @@ /* SOGoUserDefaults.h - this file is part of SOGo * - * Copyright (C) 2011 Inverse inc. + * Copyright (C) 2011-2012 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -49,9 +49,6 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (void) setDefaultCalendar: (NSString *) newDefaultCalendar; - (NSString *) defaultCalendar; -- (void) setAppointmentSendEMailReceipts: (BOOL) newPoil; -- (BOOL) appointmentSendEMailReceipts; - - (void) setLongDateFormat: (NSString *) newFormat; - (void) unsetLongDateFormat; - (NSString *) longDateFormat; diff --git a/SoObjects/SOGo/SOGoUserDefaults.m b/SoObjects/SOGo/SOGoUserDefaults.m index 74ddb6e69..3d728d398 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.m +++ b/SoObjects/SOGo/SOGoUserDefaults.m @@ -1,6 +1,6 @@ /* SOGoUserDefaults.m - this file is part of SOGo * - * Copyright (C) 2009-2010 Inverse inc. + * Copyright (C) 2009-2012 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -243,16 +243,6 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; return [self stringForKey: @"SOGoDefaultCalendar"]; } -- (void) setAppointmentSendEMailReceipts: (BOOL) newValue -{ - [self setBool: newValue forKey: @"SOGoAppointmentSendEMailReceipts"]; -} - -- (BOOL) appointmentSendEMailReceipts -{ - return [self boolForKey: @"SOGoAppointmentSendEMailReceipts"]; -} - - (void) setDayStartTime: (NSString *) newValue { [self setObject: newValue forKey: @"SOGoDayStartTime"]; diff --git a/UI/Scheduler/UIxCalendarProperties.h b/UI/Scheduler/UIxCalendarProperties.h index ebe5a974f..157653dc2 100644 --- a/UI/Scheduler/UIxCalendarProperties.h +++ b/UI/Scheduler/UIxCalendarProperties.h @@ -1,8 +1,9 @@ /* UIxCalendarProperties.m - this file is part of SOGo * - * Copyright (C) 2008 Inverse inc. + * Copyright (C) 2008-2012 Inverse inc. * * Author: Wolfgang Sourdeau + * Ludovic Marcotte * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,4 +52,14 @@ - (NSString *) calendarSyncTag; - (void) setCalendarSyncTag: (NSString *) newTag; +/* notifications */ +- (BOOL) notifyOnPersonalModifications; +- (void) setNotifyOnPersonalModifications: (BOOL) b; +- (BOOL) notifyOnExternalModifications; +- (void) setNotifyOnExternalModifications: (BOOL) b; +- (BOOL) notifyUserOnPersonalModifications; +- (void) setNotifyUserOnPersonalModifications: (BOOL) b; +- (NSString *) notifiedUserOnPersonalModifications; +- (void) setNotifiedUserOnPersonalModifications: (NSString *) theUser; + @end diff --git a/UI/Scheduler/UIxCalendarProperties.m b/UI/Scheduler/UIxCalendarProperties.m index 3e6784d25..3817ad48d 100644 --- a/UI/Scheduler/UIxCalendarProperties.m +++ b/UI/Scheduler/UIxCalendarProperties.m @@ -1,8 +1,9 @@ /* UIxCalendarProperties.m - this file is part of SOGo * - * Copyright (C) 2008-2010 Inverse inc. + * Copyright (C) 2008-2012 Inverse inc. * * Author: Wolfgang Sourdeau + * Ludovic Marcotte * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -310,4 +311,44 @@ return [NSString stringWithFormat: @"%@.xml", [self _basePublicCalDAVURL]]; } +- (BOOL) notifyOnPersonalModifications +{ + return [calendar notifyOnPersonalModifications]; +} + +- (void) setNotifyOnPersonalModifications: (BOOL) b +{ + [calendar setNotifyOnPersonalModifications: b]; +} + +- (BOOL) notifyOnExternalModifications +{ + return [calendar notifyOnExternalModifications]; +} + +- (void) setNotifyOnExternalModifications: (BOOL) b +{ + [calendar setNotifyOnExternalModifications: b]; +} + +- (BOOL) notifyUserOnPersonalModifications +{ + return [calendar notifyUserOnPersonalModifications]; +} + +- (void) setNotifyUserOnPersonalModifications: (BOOL) b +{ + [calendar setNotifyUserOnPersonalModifications: b]; +} + +- (NSString *) notifiedUserOnPersonalModifications +{ + return [calendar notifiedUserOnPersonalModifications]; +} + +- (void) setNotifiedUserOnPersonalModifications: (NSString *) theUser +{ + [calendar setNotifiedUserOnPersonalModifications: theUser]; +} + @end diff --git a/UI/Templates/Appointments/SOGoAptMailDeletionReceipt.wox b/UI/Templates/Appointments/SOGoAptMailDeletionReceipt.wox deleted file mode 100644 index 6fbe93537..000000000 --- a/UI/Templates/Appointments/SOGoAptMailDeletionReceipt.wox +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/UI/Templates/Appointments/SOGoAptMailInvitationReceipt.wox b/UI/Templates/Appointments/SOGoAptMailInvitationReceipt.wox deleted file mode 100644 index 7e1f508d2..000000000 --- a/UI/Templates/Appointments/SOGoAptMailInvitationReceipt.wox +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/UI/Templates/Appointments/SOGoAptMailReceipt.wox b/UI/Templates/Appointments/SOGoAptMailReceipt.wox new file mode 100644 index 000000000..49e7490ed --- /dev/null +++ b/UI/Templates/Appointments/SOGoAptMailReceipt.wox @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UI/Templates/Appointments/SOGoAptMailUpdateReceipt.wox b/UI/Templates/Appointments/SOGoAptMailUpdateReceipt.wox deleted file mode 100644 index d92f4f268..000000000 --- a/UI/Templates/Appointments/SOGoAptMailUpdateReceipt.wox +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/UI/Templates/SchedulerUI/UIxCalendarProperties.wox b/UI/Templates/SchedulerUI/UIxCalendarProperties.wox index 2e4646fb8..c62854e2f 100644 --- a/UI/Templates/SchedulerUI/UIxCalendarProperties.wox +++ b/UI/Templates/SchedulerUI/UIxCalendarProperties.wox @@ -102,6 +102,29 @@ /> + +
+ +
+
+
+
+