See ChangeLog

Monotone-Parent: 801c13ca7d8e3a2f3e502ee658399b458681bcab
Monotone-Revision: cf43f2030dbd1c4f0747be7cbd5dc3239cd6bd15

Monotone-Author: ludovic@Sophos.ca
Monotone-Date: 2012-07-10T00:29:13
maint-2.0.2
Ludovic Marcotte 2012-07-10 00:29:13 +00:00
parent 0d713efdd6
commit 03a125ea1f
21 changed files with 480 additions and 234 deletions

View File

@ -1,3 +1,22 @@
2012-07-09 Ludovic Marcotte <lmarcotte@inverse.ca>
* 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 <jraby@inverse.ca>
* Tools/SOGoToolUserPreferences.m:

View File

@ -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;

View File

@ -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

View File

@ -40,6 +40,7 @@
#import <SOPE/NGCards/NSString+NGCards.h>
#import <SOGo/SOGoConstants.h>
#import <SOGo/SOGoUserManager.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSDictionary+Utilities.h>
@ -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.

View File

@ -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 <wsourdeau@inverse.ca>
* Ludovic Marcotte <lmarcotte@inverse.ca>
*
* 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 <SOGo/SOGoConstants.h>
@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

View File

@ -3,6 +3,7 @@
* Copyright (C) 2009-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Ludovic Marcotte <lmarcotte@inverse.ca>
*
* 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

View File

@ -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;

View File

@ -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: <foo@bar.com>
// 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;

View File

@ -44,4 +44,11 @@ typedef enum
// Domain defaults
extern NSString *SOGoPasswordChangeEnabled;
typedef enum
{
EventCreated = 0,
EventDeleted = 1,
EventUpdated = 2,
} SOGoEventOperation;
#endif /* _SOGOCONSTANTS_H_ */

View File

@ -78,6 +78,8 @@
- (BOOL) hideSystemEMail;
- (int) searchMinimumWordLength;
- (BOOL) notifyOnPersonalModifications;
- (BOOL) notifyOnExternalModifications;
@end

View File

@ -324,4 +324,14 @@
return [self integerForKey: @"SOGoSearchMinimumWordLength"];
}
- (BOOL) notifyOnPersonalModifications
{
return [self boolForKey: @"SOGoNotifyOnPersonalModifications"];
}
- (BOOL) notifyOnExternalModifications
{
return [self boolForKey: @"SOGoNotifyOnExternalModifications"];
}
@end

View File

@ -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 <wsourdeau@inverse.ca>
*
@ -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;

View File

@ -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 <wsourdeau@inverse.ca>
*
@ -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"];

View File

@ -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 <wsourdeau@inverse.ca>
* Ludovic Marcotte <lmarcotte@inverse.ca>
*
* 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

View File

@ -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 <wsourdeau@inverse.ca>
* Ludovic Marcotte <lmarcotte@inverse.ca>
*
* 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

View File

@ -1,30 +0,0 @@
<?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

@ -1,31 +0,0 @@
<?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,54 @@
<?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 value="subject"
const:escapeHTML="NO"/>
</var:if>
<var:if condition="isSubject" const:negate="YES">
<var:string label:value="Event details:" const:escapeHTML="NO"/>
<var:string label:value="Title:" const:escapeHTML="NO"/> <var:string
value="apt.summary" const:escapeHTML="NO"/>
<var:if condition="apt.location.length">
<var:string label:value="Location:" const:escapeHTML="NO"/> <var:string
value="apt.location" const:escapeHTML="NO"/>
</var:if>
<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 condition="updatedAttendees.count">
<var:string label:value="The following attendees(s) were notified:"
const:escapeHTML="NO"/>
<var:foreach list="updatedAttendees" item="currentRecipient">
<var:string value="currentRecipient.mailAddress" const:escapeHTML="NO"
/></var:foreach>
</var:if>
<var:if condition="addedAttendees.count">
<var:string label:value="The following attendees(s) were added:"
const:escapeHTML="NO"/>
<var:foreach list="addedAttendees" item="currentRecipient">
<var:string value="currentRecipient.mailAddress" const:escapeHTML="NO"
/></var:foreach>
</var:if>
<var:if condition="deletedAttendees.count">
<var:string label:value="The following attendees(s) were removed:"
const:escapeHTML="NO"/>
<var:foreach list="deletedAttendees" item="currentRecipient">
<var:string value="currentRecipient.mailAddress" const:escapeHTML="NO"
/></var:foreach>
</var:if>
</var:if>
</container>

View File

@ -1,27 +0,0 @@
<?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>

View File

@ -102,6 +102,29 @@
/><var:string label:value="Reload on login"
/></label></div></var:if>
</fieldset>
<fieldset>
<legend><var:string label:value="Notifications"/></legend>
<div><label
><input type="checkbox" const:class="checkBox"
id="notifyOnPersonalModifications" var:checked="notifyOnPersonalModifications"
/><var:string label:value="Receive a mail when I modify my calendar"/></label></div>
<div><label
><input type="checkbox" const:class="checkBox"
id="notifyOnExternalModifications" var:checked="notifyOnExternalModifications"
/><var:string label:value="Receive a mail when someone else modifies my calendar"
/></label></div>
<div><label
><input type="checkbox" const:class="checkBox"
id="notifyUserOnPersonalModifications" var:checked="notifyUserOnPersonalModifications"
/><var:string label:value="When I modify my calendar, send a mail to:"
/></label><span class="content"><input type="text"
name="notifiedUserOnPersonalModifications" id="notifiedUserOnPersonalModifications"
class="textField"
var:value="notifiedUserOnPersonalModifications"
/></span></div>
</fieldset>
</div>
<div id="davLinksView" class="tab">
<var:if condition="isWebCalendar"

View File

@ -2747,8 +2747,8 @@ function onCalendarModify(event) {
var owner = selected.getAttribute("owner");
var url = ApplicationBaseURL + calendarID + "/properties";
var windowID = sanitizeWindowName(calendarID + " properties");
var width = 310;
var height = 294;
var width = 410;
var height = 410;
var isWebCalendar = false;
if (UserSettings['Calendar']
&& UserSettings['Calendar']['WebCalendars']) {