Monotone-Parent: 9a9029239df8b59ccf4609e50402e80e31085154

Monotone-Revision: f04c25f5f8bfb6f1876bab3f70b89ee5c99bcc01

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2009-08-25T21:28:24
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2009-08-25 21:28:24 +00:00
parent b7c9a59791
commit 1486216b0c
26 changed files with 431 additions and 50 deletions

View File

@ -1,3 +1,13 @@
2009-08-25 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoUser.m (+userWithLogin:): new constructor
designed to avoid the need to pass a nil role parameter.
* SoObjects/Appointments/SOGoCalendarComponent.m
(-sendReceiptEmailUsingTemplateNamed:forObject:to:) new method
that enables the sending of receipts to an event modifier in case
of an invitation, modification or deletion.
2009-08-25 Cyril Robert <crobert@inverse.ca> 2009-08-25 Cyril Robert <crobert@inverse.ca>
* SoObjects/Contacts/SOGoContactGCSList.m (copyToFolder): Implementation to * SoObjects/Contacts/SOGoContactGCSList.m (copyToFolder): Implementation to

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Evento Confidencial)";
vtodo_class0 = "(Tarefa Pública)"; vtodo_class0 = "(Tarefa Pública)";
vtodo_class1 = "(Tarefa Privada)"; vtodo_class1 = "(Tarefa Privada)";
vtodo_class2 = "(Tarefa Confidencial)"; vtodo_class2 = "(Tarefa Confidencial)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Skrytá událost)";
vtodo_class0 = "(Veřejný úkol)"; vtodo_class0 = "(Veřejný úkol)";
vtodo_class1 = "(Soukromý úkol)"; vtodo_class1 = "(Soukromý úkol)";
vtodo_class2 = "(Skrytý úkol)"; vtodo_class2 = "(Skrytý úkol)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Vertrouwelijke afspraak)";
vtodo_class0 = "(Publieke taak)"; vtodo_class0 = "(Publieke taak)";
vtodo_class1 = "(Privétaak)"; vtodo_class1 = "(Privétaak)";
vtodo_class2 = "(Vertrouwelijke taak)"; vtodo_class2 = "(Vertrouwelijke taak)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Confidential event)";
vtodo_class0 = "(Public task)"; vtodo_class0 = "(Public task)";
vtodo_class1 = "(Private task)"; vtodo_class1 = "(Private task)";
vtodo_class2 = "(Confidential task)"; vtodo_class2 = "(Confidential task)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Événement confidentiel)";
vtodo_class0 = "(Tâche publique)"; vtodo_class0 = "(Tâche publique)";
vtodo_class1 = "(Tâche privée)"; vtodo_class1 = "(Tâche privée)";
vtodo_class2 = "(Tâche confidentielle)"; vtodo_class2 = "(Tâche confidentielle)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Acc. de réception : vous avez ajouté des participants à une réunion";
"You have invited the following attendees(s):" = "Vous avez invité les personnes suivantes :";
"... to attend the following event:" = "... à participer à cette réunion :";
"Receipt: invitation updated" = "Acc. de réception : invitation mise à jour";
"The following attendees(s):" = "Les participants suivants :"
"... have been notified of the changes to the following event:" = "... ont été avisés des changements apportés à cette réunion :";
"Receipt: attendees removed from an event" = "Acc. de réception: invitations annulées";
"You have removed the following attendees(s):" = "Les utilisateurs suivants :";
"... from the following event:" = "... ne sont plus invités à cette réunion :";

View File

@ -33,6 +33,7 @@ Appointments_OBJC_FILES = \
SOGoAptMailDeletion.m \ SOGoAptMailDeletion.m \
SOGoAptMailICalReply.m \ SOGoAptMailICalReply.m \
SOGoAptMailUpdate.m \ SOGoAptMailUpdate.m \
SOGoAptMailReceipt.m \
Appointments_RESOURCE_FILES += \ Appointments_RESOURCE_FILES += \
Version \ Version \

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Vertraulicher Termin)";
vtodo_class0 = "(Öffentliche Aufgabe)"; vtodo_class0 = "(Öffentliche Aufgabe)";
vtodo_class1 = "(Private Aufgabe)"; vtodo_class1 = "(Private Aufgabe)";
vtodo_class2 = "(Vertrauliche Aufgabe)"; vtodo_class2 = "(Vertrauliche Aufgabe)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Bizalmas esemény)";
vtodo_class0 = "(Nyilvános feladat)"; vtodo_class0 = "(Nyilvános feladat)";
vtodo_class1 = "(Magán feladat)"; vtodo_class1 = "(Magán feladat)";
vtodo_class2 = "(Bizalmas feladat)"; vtodo_class2 = "(Bizalmas feladat)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Evento confidenziale)";
vtodo_class0 = "(Attività pubblica)"; vtodo_class0 = "(Attività pubblica)";
vtodo_class1 = "(Attività privata)"; vtodo_class1 = "(Attività privata)";
vtodo_class2 = "(Attività confidenziale)"; vtodo_class2 = "(Attività confidenziale)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Confidential event)";
vtodo_class0 = "(Public task)"; vtodo_class0 = "(Public task)";
vtodo_class1 = "(Private task)"; vtodo_class1 = "(Private task)";
vtodo_class2 = "(Confidential task)"; vtodo_class2 = "(Confidential task)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -2153,7 +2153,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
login = [recipient uid]; login = [recipient uid];
if ([login length]) if ([login length])
{ {
user = [SOGoUser userWithLogin: login roles: nil]; user = [SOGoUser userWithLogin: login];
freebusy = [[user homeFolderInContext: context] freebusy = [[user homeFolderInContext: context]
freeBusyObject: @"freebusy.ifb" freeBusyObject: @"freebusy.ifb"
inContext: context]; inContext: context];
@ -2677,8 +2677,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
rc = [super create]; rc = [super create];
if (rc) if (rc)
{ {
ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context] ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context]];
roles: nil];
userSettings = [ownerUser userSettings]; userSettings = [ownerUser userSettings];
calendarSettings = [userSettings objectForKey: @"Calendar"]; calendarSettings = [userSettings objectForKey: @"Calendar"];
if (!calendarSettings) if (!calendarSettings)
@ -2986,8 +2985,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
// calendarFolders = [NSMutableArray new]; // calendarFolders = [NSMutableArray new];
// [calendarFolders autorelease]; // [calendarFolders autorelease];
// calendarUser = [SOGoUser userWithLogin: [self ownerInContext: context] // calendarUser = [SOGoUser userWithLogin: [self ownerInContext: context]];
// roles: nil];
// userCalendar = [NSMutableDictionary new]; // userCalendar = [NSMutableDictionary new];
// [userCalendar autorelease]; // [userCalendar autorelease];
// [userCalendar setObject: @"/" forKey: @"folder"]; // [userCalendar setObject: @"/" forKey: @"folder"];

View File

@ -241,7 +241,7 @@
// present in the master component. If not, we add it with a participation // present in the master component. If not, we add it with a participation
// status set to "DECLINED". // status set to "DECLINED".
user = [SOGoUser userWithLogin: theUID roles: nil]; user = [SOGoUser userWithLogin: theUID];
person = [iCalPerson elementWithTag: @"attendee"]; person = [iCalPerson elementWithTag: @"attendee"];
[person setCn: [user cn]]; [person setCn: [user cn]];
[person setEmail: [[user allEmails] objectAtIndex: 0]]; [person setEmail: [[user allEmails] objectAtIndex: 0]];
@ -408,6 +408,8 @@
forObject: [newEvent itipEntryWithMethod: @"request"] forObject: [newEvent itipEntryWithMethod: @"request"]
previousObject: oldEvent previousObject: oldEvent
toAttendees: updateAttendees]; toAttendees: updateAttendees];
[self sendReceiptEmailUsingTemplateNamed: @"Update"
forObject: newEvent to: updateAttendees];
} }
- (void) _handleAddedUsers: (NSArray *) attendees - (void) _handleAddedUsers: (NSArray *) attendees
@ -447,6 +449,8 @@
forObject: [newEvent itipEntryWithMethod: @"cancel"] forObject: [newEvent itipEntryWithMethod: @"cancel"]
previousObject: oldEvent previousObject: oldEvent
toAttendees: attendees]; toAttendees: attendees];
[self sendReceiptEmailUsingTemplateNamed: @"Deletion"
forObject: newEvent to: attendees];
} }
attendees = [changes insertedAttendees]; attendees = [changes insertedAttendees];
@ -470,8 +474,10 @@
NSEnumerator *enumerator; NSEnumerator *enumerator;
iCalPerson *currentAttendee; iCalPerson *currentAttendee;
NSString *currentUID; NSString *currentUID;
NSArray *updatedAttendees;
enumerator = [[newEvent attendees] objectEnumerator]; updatedAttendees = [newEvent attendees];
enumerator = [updatedAttendees objectEnumerator];
while ((currentAttendee = [enumerator nextObject])) while ((currentAttendee = [enumerator nextObject]))
{ {
currentUID = [currentAttendee uid]; currentUID = [currentAttendee uid];
@ -480,6 +486,10 @@
forUID: currentUID forUID: currentUID
owner: owner]; owner: owner];
} }
[self sendReceiptEmailUsingTemplateNamed: @"Update"
forObject: newEvent
to: updatedAttendees];
} }
} }
@ -488,26 +498,28 @@
NSArray *originalAttendees; NSArray *originalAttendees;
originalAttendees = [NSArray arrayWithArray: [newEvent attendees]]; originalAttendees = [NSArray arrayWithArray: [newEvent attendees]];
// Send an invitation to new attendees // Send an invitation to new attendees
[self _handleAddedUsers: attendees fromEvent: newEvent]; [self _handleAddedUsers: attendees fromEvent: newEvent];
[self sendEMailUsingTemplateNamed: @"Invitation" [self sendEMailUsingTemplateNamed: @"Invitation"
forObject: [newEvent itipEntryWithMethod: @"request"] forObject: [newEvent itipEntryWithMethod: @"request"]
previousObject: oldEvent previousObject: oldEvent
toAttendees: attendees]; toAttendees: attendees];
[self sendReceiptEmailUsingTemplateNamed: @"Invitation"
forObject: newEvent to: attendees];
} }
} }
- (void) saveComponent: (iCalEvent *) newEvent - (void) saveComponent: (iCalEvent *) newEvent
{ {
iCalEvent *oldEvent; iCalEvent *oldEvent, *oldMasterEvent;
NSArray *attendees; NSArray *attendees;
NSCalendarDate *recurrenceId; NSCalendarDate *recurrenceId;
NSString *recurrenceTime; NSString *recurrenceTime;
SOGoUser *ownerUser; SOGoUser *ownerUser;
[[newEvent parent] setMethod: @""]; [[newEvent parent] setMethod: @""];
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
[self expandGroupsInEvent: newEvent]; [self expandGroupsInEvent: newEvent];
@ -526,6 +538,8 @@
forObject: [newEvent itipEntryWithMethod: @"request"] forObject: [newEvent itipEntryWithMethod: @"request"]
previousObject: nil previousObject: nil
toAttendees: attendees]; toAttendees: attendees];
[self sendReceiptEmailUsingTemplateNamed: @"Invitation"
forObject: newEvent to: attendees];
} }
} }
else else
@ -545,8 +559,10 @@
// If no occurence found, create one // If no occurence found, create one
oldEvent = (iCalEvent*)[self newOccurenceWithID: recurrenceTime]; oldEvent = (iCalEvent*)[self newOccurenceWithID: recurrenceTime];
} }
if ([[[oldEvent parent] firstChildWithTag: [self componentTag]] userIsOrganizer: ownerUser]) oldMasterEvent
= (iCalEvent *) [[oldEvent parent] firstChildWithTag: [self componentTag]];
if ([oldMasterEvent userIsOrganizer: ownerUser])
{ {
// The owner is the organizer of the event; handle the modifications // The owner is the organizer of the event; handle the modifications
@ -697,7 +713,7 @@
// If the current user isn't the organizer of the event // If the current user isn't the organizer of the event
// that has just been updated, we update the event and // that has just been updated, we update the event and
// send a notification // send a notification
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
if (!(ex || [event userIsOrganizer: ownerUser])) if (!(ex || [event userIsOrganizer: ownerUser]))
{ {
if ([[attendee rsvp] isEqualToString: @"true"] if ([[attendee rsvp] isEqualToString: @"true"]
@ -802,7 +818,7 @@
newEvent = [self component: NO secure: NO]; newEvent = [self component: NO secure: NO];
[newEvent removeAllAlarms]; [newEvent removeAllAlarms];
[[newEvent parent] setMethod: @""]; [[newEvent parent] setMethod: @""];
recipientsEnum = [recipients objectEnumerator]; recipientsEnum = [recipients objectEnumerator];
while ((recipient = [recipientsEnum nextObject])) while ((recipient = [recipientsEnum nextObject]))
if ([[recipient lowercaseString] hasPrefix: @"mailto:"]) if ([[recipient lowercaseString] hasPrefix: @"mailto:"])
@ -890,15 +906,16 @@
// We must add an occurence to a non-existing event -- simply retrieve // We must add an occurence to a non-existing event -- simply retrieve
// the event from the organizer's calendar // the event from the organizer's calendar
if (ownerEventObject == nil) if (ownerEventObject == nil)
ownerEventObject = [self _lookupEvent: [newEvent uid] forUID: ownerUID]; ownerEventObject = [self _lookupEvent: [newEvent uid]
forUID: ownerUID];
newEvent = [ownerEventObject component: NO secure: NO]; newEvent = [ownerEventObject component: NO secure: NO];
attendees = [newEvent attendees]; attendees = [newEvent attendees];
found = NO; found = NO;
// We check if the attendee that was added to a single occurence is /* We check if the attendee that was added to a single
// present in the master component. If not, we add it with a participation occurence is present in the master component. If not, we
// status set to "DECLINED" add it with a participation status set to "DECLINED" */
for (i = 0; i < [attendees count]; i++) for (i = 0; i < [attendees count]; i++)
{ {
if ([[attendees objectAtIndex: i] hasSameEmailAddress: person]) if ([[attendees objectAtIndex: i] hasSameEmailAddress: person])
@ -907,7 +924,7 @@
break; break;
} }
} }
if (!found) if (!found)
{ {
[person setParticipationStatus: iCalPersonPartStatDeclined]; [person setParticipationStatus: iCalPersonPartStatDeclined];
@ -939,6 +956,11 @@
addObject: [self _caldavSuccessCodeWithRecipient: recipient]]; addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
} }
[self sendReceiptEmailUsingTemplateNamed: (isUpdate
? @"Update" : @"Invitation")
forObject: emailEvent
to: [newEvent participants]];
return elements; return elements;
} }
@ -980,6 +1002,10 @@
addObject: [self _caldavSuccessCodeWithRecipient: recipient]]; addObject: [self _caldavSuccessCodeWithRecipient: recipient]];
} }
[self sendReceiptEmailUsingTemplateNamed: @"Deletion"
forObject: event
to: [event participants]];
return elements; return elements;
} }
@ -1091,8 +1117,7 @@
event = [self component: NO secure: NO]; event = [self component: NO secure: NO];
[[event parent] setMethod: @""]; [[event parent] setMethod: @""];
ownerUser = [SOGoUser userWithLogin: [[LDAPUserManager sharedUserManager] ownerUser = [SOGoUser userWithLogin: [[LDAPUserManager sharedUserManager]
getUIDForEmail: originator] getUIDForEmail: originator]];
roles: nil];
attendee = [event findParticipant: ownerUser]; attendee = [event findParticipant: ownerUser];
eventUID = [event uid]; eventUID = [event uid];
@ -1173,7 +1198,7 @@
// actually occured. The particpation change will of // actually occured. The particpation change will of
// course be on the attendee that is the owner of the // course be on the attendee that is the owner of the
// calendar where the participation change has occured. // calendar where the participation change has occured.
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
attendee = [event findParticipant: ownerUser]; attendee = [event findParticipant: ownerUser];
if (attendee) if (attendee)
@ -1202,7 +1227,7 @@
if ([[context request] handledByDefaultHandler]) if ([[context request] handledByDefaultHandler])
{ {
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
event = [self component: NO secure: NO]; event = [self component: NO secure: NO];
if (occurence == nil) if (occurence == nil)
@ -1235,6 +1260,9 @@
forObject: [occurence itipEntryWithMethod: @"cancel"] forObject: [occurence itipEntryWithMethod: @"cancel"]
previousObject: nil previousObject: nil
toAttendees: attendees]; toAttendees: attendees];
[self sendReceiptEmailUsingTemplateNamed: @"Deletion"
forObject: occurence
to: attendees];
} }
} }
else if ([occurence userIsParticipant: ownerUser]) else if ([occurence userIsParticipant: ownerUser])
@ -1266,7 +1294,7 @@
NSString *key; NSString *key;
SOGoUser *ownerUser; SOGoUser *ownerUser;
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
allEvents = [calendar events]; allEvents = [calendar events];
max = [allEvents count]; max = [allEvents count];

View File

@ -196,9 +196,13 @@ static NSTimeZone *UTC = nil;
- (NSString *) getBody - (NSString *) getBody
{ {
NSString *body;
[self setIsSubject:NO]; [self setIsSubject:NO];
return [[self generateResponse] contentAsString]; body = [[self generateResponse] contentAsString];
return [body stringByTrimmingCharactersInSet: wsSet];
} }
@end @end

View File

@ -72,6 +72,10 @@
- (void) sendResponseToOrganizer: (iCalRepeatableEntityObject *) newComponent - (void) sendResponseToOrganizer: (iCalRepeatableEntityObject *) newComponent
from: (SOGoUser *) owner; from: (SOGoUser *) owner;
- (void) sendReceiptEmailUsingTemplateNamed: (NSString *) template
forObject: (iCalRepeatableEntityObject *) object
to: (NSArray *) recipients;
// - (BOOL) isOrganizerOrOwner: (SOGoUser *) user; // - (BOOL) isOrganizerOrOwner: (SOGoUser *) user;
- (iCalPerson *) findParticipantWithUID: (NSString *) uid; - (iCalPerson *) findParticipantWithUID: (NSString *) uid;

View File

@ -41,18 +41,20 @@
#import <NGMime/NGMimeMultipartBody.h> #import <NGMime/NGMimeMultipartBody.h>
#import <NGMail/NGMimeMessage.h> #import <NGMail/NGMimeMessage.h>
#import <SoObjects/SOGo/iCalEntityObject+Utilities.h> #import <SOGo/iCalEntityObject+Utilities.h>
#import <SoObjects/SOGo/LDAPUserManager.h> #import <SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/NSCalendarDate+SOGo.h> #import <SOGo/NSCalendarDate+SOGo.h>
#import <SoObjects/SOGo/SOGoMailer.h> #import <SOGo/NSDictionary+Utilities.h>
#import <SoObjects/SOGo/SOGoGroup.h> #import <SOGo/SOGoMailer.h>
#import <SoObjects/SOGo/SOGoPermissions.h> #import <SOGo/SOGoGroup.h>
#import <SoObjects/SOGo/SOGoUser.h> #import <SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/WORequest+SOGo.h> #import <SOGo/SOGoUser.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h> #import <SOGo/WORequest+SOGo.h>
#import <Appointments/SOGoAppointmentFolder.h>
#import "SOGoAptMailICalReply.h" #import "SOGoAptMailICalReply.h"
#import "SOGoAptMailNotification.h" #import "SOGoAptMailNotification.h"
#import "SOGoAptMailReceipt.h"
#import "iCalEntityObject+SOGo.h" #import "iCalEntityObject+SOGo.h"
#import "iCalPerson+SOGo.h" #import "iCalPerson+SOGo.h"
#import "iCalRepeatableEntityObject+SOGo.h" #import "iCalRepeatableEntityObject+SOGo.h"
@ -60,6 +62,7 @@
#import "SOGoComponentOccurence.h" #import "SOGoComponentOccurence.h"
static BOOL sendEMailNotifications = NO; static BOOL sendEMailNotifications = NO;
static BOOL sendEMailReceipts = NO;
@implementation SOGoCalendarComponent @implementation SOGoCalendarComponent
@ -75,6 +78,8 @@ static BOOL sendEMailNotifications = NO;
ud = [NSUserDefaults standardUserDefaults]; ud = [NSUserDefaults standardUserDefaults];
sendEMailNotifications sendEMailNotifications
= [ud boolForKey: @"SOGoAppointmentSendEMailNotifications"]; = [ud boolForKey: @"SOGoAppointmentSendEMailNotifications"];
sendEMailReceipts
= [ud boolForKey: @"SOGoAppointmentSendEMailReceipts"];
} }
} }
@ -587,7 +592,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr
uid = [[LDAPUserManager sharedUserManager] getUIDForEmail: email]; uid = [[LDAPUserManager sharedUserManager] getUIDForEmail: email];
return [[SOGoUser userWithLogin: uid roles: nil] timeZone]; return [[SOGoUser userWithLogin: uid] timeZone];
} }
- (void) sendEMailUsingTemplateNamed: (NSString *) newPageName - (void) sendEMailUsingTemplateNamed: (NSString *) newPageName
@ -616,7 +621,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr
if (count) if (count)
{ {
/* sender */ /* sender */
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
//currentUser = [context activeUser]; //currentUser = [context activeUser];
//shortSenderEmail = [[currentUser allEmails] objectAtIndex: 0]; //shortSenderEmail = [[currentUser allEmails] objectAtIndex: 0];
// senderEmail = [NSString stringWithFormat: @"%@ <%@>", // senderEmail = [NSString stringWithFormat: @"%@ <%@>",
@ -752,7 +757,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr
/* get WOApplication instance */ /* get WOApplication instance */
app = [WOApplication application]; app = [WOApplication application];
//ownerUser = [SOGoUser userWithLogin: owner roles: nil]; //ownerUser = [SOGoUser userWithLogin: owner];
ownerUser = from; ownerUser = from;
language = [ownerUser language]; language = [ownerUser language];
/* create page name */ /* create page name */
@ -831,7 +836,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr
SOGoUser *ownerUser; SOGoUser *ownerUser;
event = [newComponent itipEntryWithMethod: @"reply"]; event = [newComponent itipEntryWithMethod: @"reply"];
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
if (![event userIsOrganizer: ownerUser]) if (![event userIsOrganizer: ownerUser])
{ {
organizer = [event organizer]; organizer = [event organizer];
@ -841,6 +846,55 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr
} }
} }
- (void) sendReceiptEmailUsingTemplateNamed: (NSString *) template
forObject: (iCalRepeatableEntityObject *) object
to: (NSArray *) attendees
{
NSString *pageName, *mailDate, *mailText, *fullSenderEmail, *senderEmail;
SOGoAptMailReceipt *page;
NGMutableHashMap *headerMap;
NGMimeMessage *msg;
SOGoUser *currentUser;
NSDictionary *identity;
if (sendEMailReceipts && [attendees count])
{
pageName = [NSString stringWithFormat: @"SOGoAptMail%@Receipt",
template];
page = [[WOApplication application] pageWithName: pageName
inContext: context];
[page setApt: object];
[page setRecipients: attendees];
currentUser = [context activeUser];
identity = [currentUser primaryIdentity];
/* construct message */
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];
/* text part */
mailText = [page getBody];
[msg setBody: [mailText dataUsingEncoding: NSUTF8StringEncoding]];
/* send the damn thing */
senderEmail = [identity objectForKey: @"email"];
[[SOGoMailer sharedMailer]
sendMimePart: msg
toRecipients: [NSArray arrayWithObject: senderEmail]
sender: senderEmail];
}
}
// - (BOOL) isOrganizerOrOwner: (SOGoUser *) user // - (BOOL) isOrganizerOrOwner: (SOGoUser *) user
// { // {
// BOOL isOrganizerOrOwner; // BOOL isOrganizerOrOwner;
@ -863,7 +917,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr
iCalEntityObject *component; iCalEntityObject *component;
SOGoUser *user; SOGoUser *user;
user = [SOGoUser userWithLogin: uid roles: nil]; user = [SOGoUser userWithLogin: uid];
component = [self component: NO secure: NO]; component = [self component: NO secure: NO];
return [component findParticipant: user]; return [component findParticipant: user];
@ -943,7 +997,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr
organizer = [component organizer]; organizer = [component organizer];
if ([[organizer rfc822Email] length] > 0) if ([[organizer rfc822Email] length] > 0)
{ {
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
if ([component userIsOrganizer: ownerUser]) if ([component userIsOrganizer: ownerUser])
role = SOGoCalendarRole_Organizer; role = SOGoCalendarRole_Organizer;
else if ([component userIsParticipant: ownerUser]) else if ([component userIsParticipant: ownerUser])
@ -1001,7 +1055,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr
{ {
if (component) if (component)
{ {
aclUser = [SOGoUser userWithLogin: uid roles: nil]; aclUser = [SOGoUser userWithLogin: uid];
if ([component userIsOrganizer: aclUser]) if ([component userIsOrganizer: aclUser])
[roles addObject: SOGoCalendarRole_Organizer]; [roles addObject: SOGoCalendarRole_Organizer];
else if ([component userIsParticipant: aclUser]) else if ([component userIsParticipant: aclUser])

View File

@ -124,7 +124,7 @@ static unsigned int freebusyRangeEnd = 0;
int i; int i;
login = [container ownerInContext: context]; login = [container ownerInContext: context];
user = [SOGoUser userWithLogin: login roles: nil]; user = [SOGoUser userWithLogin: login];
calendar = [iCalCalendar groupWithTag: @"vcalendar"]; calendar = [iCalCalendar groupWithTag: @"vcalendar"];
[calendar setProdID: @"//Inverse inc./SOGo 1.0//EN"]; [calendar setProdID: @"//Inverse inc./SOGo 1.0//EN"];

View File

@ -55,7 +55,7 @@
addresses = [NSMutableArray array]; addresses = [NSMutableArray array];
ownerUser = [SOGoUser userWithLogin: owner roles: nil]; ownerUser = [SOGoUser userWithLogin: owner];
emails = [[ownerUser allEmails] objectEnumerator]; emails = [[ownerUser allEmails] objectEnumerator];
while ((currentEmail = [emails nextObject])) while ((currentEmail = [emails nextObject]))
{ {
@ -224,7 +224,7 @@
value = [value substringFromIndex: NSMaxRange (substringRange)]; value = [value substringFromIndex: NSMaxRange (substringRange)];
substringRange = [value rangeOfString: @"/Calendar"]; substringRange = [value rangeOfString: @"/Calendar"];
value = [value substringToIndex: substringRange.location]; value = [value substringToIndex: substringRange.location];
collection = [[SOGoUser userWithLogin: value roles: nil] collection = [[SOGoUser userWithLogin: value]
homeFolderInContext: context]; homeFolderInContext: context];
if (collection) if (collection)
[collections addObject: collection]; [collections addObject: collection];

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Evento confidencial)";
vtodo_class0 = "(Tarea pública)"; vtodo_class0 = "(Tarea pública)";
vtodo_class1 = "(Tarea privada)"; vtodo_class1 = "(Tarea privada)";
vtodo_class2 = "(Tarea confidencial)"; vtodo_class2 = "(Tarea confidencial)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -6,3 +6,20 @@ vevent_class2 = "(Digwyddiad cyfrinachol)";
vtodo_class0 = "(Tasg gyhoeddus)"; vtodo_class0 = "(Tasg gyhoeddus)";
vtodo_class1 = "(Tasg breifat)"; vtodo_class1 = "(Tasg breifat)";
vtodo_class2 = "(Tasg gyfrinachol)"; vtodo_class2 = "(Tasg gyfrinachol)";
/* Receipts */
"Title:" = "Title:";
"Start:" = "Start:";
"End:" = "End:";
"Receipt: users invited to a meeting" = "Receipt: users invited to a meeting";
"You have invited the following attendees(s):" = "You have invited the following attendees(s):";
"... to attend the following event:" = "... to attend the following event:";
"Receipt: invitation updated" = "Receipt: invitation updated";
"The following attendees(s):" = "The following attendees(s):"
"... have been notified of the changes to the following event:" = "... have been notified of the changes to the following event:";
"Receipt: attendees removed from an event" = "Receipt: attendees removed from an event";
"You have removed the following attendees(s):" = "You have removed the following attendees(s):";
"... from the following event:" = "... from the following event:";

View File

@ -30,12 +30,12 @@
- (BOOL) sequenceShouldBeIncreased - (BOOL) sequenceShouldBeIncreased
{ {
NSString *properties[] = {@"organizer", @"startDate", @"endDate", static NSString *properties[] = {@"organizer", @"startDate", @"endDate",
@"due", @"duration", @"due", @"duration",
@"rdate", @"rrule", @"exdate", @"exrule", @"rdate", @"rrule", @"exdate", @"exrule",
@"status", @"location", @"status", @"location",
//@"summary", @"comment", //@"summary", @"comment",
nil}; nil};
NSString **currentProperty; NSString **currentProperty;
BOOL updateRequired; BOOL updateRequired;

View File

@ -75,6 +75,8 @@ extern NSString *SOGoWeekStartFirstFullWeek;
+ (NSString *) language; + (NSString *) language;
+ (SOGoUser *) userWithLogin: (NSString *) newLogin;
+ (SOGoUser *) userWithLogin: (NSString *) login + (SOGoUser *) userWithLogin: (NSString *) login
roles: (NSArray *) roles; roles: (NSArray *) roles;

View File

@ -220,6 +220,11 @@ _timeValue (NSString *key)
return fallbackIMAP4Server; return fallbackIMAP4Server;
} }
+ (SOGoUser *) userWithLogin: (NSString *) newLogin
{
return [self userWithLogin: newLogin roles: nil];
}
+ (SOGoUser *) userWithLogin: (NSString *) newLogin + (SOGoUser *) userWithLogin: (NSString *) newLogin
roles: (NSArray *) newRoles roles: (NSArray *) newRoles
{ {

View File

@ -0,0 +1,30 @@
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE container>
<container
xmlns="http://www.w3.org/1999/xhtml"
xmlns:var="http://www.skyrix.com/od/binding"
xmlns:const="http://www.skyrix.com/od/constant"
xmlns:rsrc="OGo:url"
xmlns:label="OGo:label">
<var:if condition="isSubject">
<var:string label:value="Receipt: attendees removed from an event"
const:escapeHTML="NO"/>
</var:if>
<var:if condition="isSubject" const:negate="YES">
<var:string label:value="You have removed the following attendees(s):"
const:escapeHTML="NO"/>
<var:foreach list="recipients" item="currentRecipient">
<var:string value="currentRecipient.mailAddress" const:escapeHTML="NO"
/></var:foreach>
<var:string label:value="... from the following event:" const:escapeHTML="NO"/>
<var:string label:value="Title:" const:escapeHTML="NO"/><var:string
value="apt.summary" const:escapeHTML="NO"/>
<var:string label:value="Start:" const:escapeHTML="NO"/><var:string
value="aptStartDate" const:escapeHTML="NO"/>
<var:string label:value="End:" const:escapeHTML="NO"/><var:string
value="aptEndDate" const:escapeHTML="NO"/>
</var:if>
</container>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE container>
<container
xmlns="http://www.w3.org/1999/xhtml"
xmlns:var="http://www.skyrix.com/od/binding"
xmlns:const="http://www.skyrix.com/od/constant"
xmlns:rsrc="OGo:url"
xmlns:label="OGo:label">
<var:if condition="isSubject">
<var:string label:value="Receipt: users invited to a meeting"
const:escapeHTML="NO"/>
</var:if>
<var:if condition="isSubject" const:negate="YES">
<var:string label:value="You have invited the following attendees(s):"
const:escapeHTML="NO"/>
<var:foreach list="recipients" item="currentRecipient">
<var:string value="currentRecipient.mailAddress" const:escapeHTML="NO"
/></var:foreach>
<var:string label:value="... to attend the following event:"
const:escapeHTML="NO"/>
<var:string label:value="Title:"/><var:string value="apt.summary"
const:escapeHTML="NO"/>
<var:string label:value="Start:"/><var:string value="aptStartDate"
const:escapeHTML="NO"/>
<var:string label:value="End:"/><var:string value="aptEndDate"
const:escapeHTML="NO"/>
</var:if>
</container>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE container>
<container
xmlns="http://www.w3.org/1999/xhtml"
xmlns:var="http://www.skyrix.com/od/binding"
xmlns:const="http://www.skyrix.com/od/constant"
xmlns:rsrc="OGo:url"
xmlns:label="OGo:label">
<var:if condition="isSubject">
<var:string label:value="Receipt: invitation updated" const:escapeHTML="NO"/>
</var:if>
<var:if condition="isSubject" const:negate="YES">
<var:string label:value="The following attendees(s):" const:escapeHTML="NO"/>
<var:foreach list="recipients" item="currentRecipient">
<var:string value="currentRecipient.mailAddress" const:escapeHTML="NO"
/></var:foreach>
<var:string label:value="... have been notified of the changes to the following event:" const:escapeHTML="NO"/>
<var:string label:value="Title:" const:escapeHTML="NO"
/><var:string value="apt.summary" const:escapeHTML="NO"/>
<var:string label:value="Start:" const:escapeHTML="NO"
/><var:string value="aptStartDate" const:escapeHTML="NO"/>
<var:string label:value="End:" const:escapeHTML="NO"
/><var:string value="aptEndDate" const:escapeHTML="NO"/>
</var:if>
</container>