mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-02-25 03:06:25 +00:00
See ChangeLog
Monotone-Parent: 0400894ebb0d9305dae91e6efb9e8a62a36e6d5b Monotone-Revision: 814be30289e980e05d1340e3dc8d3bad9155344d Monotone-Author: ludovic@Sophos.ca Monotone-Date: 2008-11-18T00:06:37 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
10
ChangeLog
10
ChangeLog
@@ -1,3 +1,13 @@
|
||||
2008-11-17 Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
|
||||
* Added back the appointment update notification
|
||||
templates from RC8 and updated them.
|
||||
* SoObjects/Appointments/SOGoAppointmentFolder.m
|
||||
Greatly improved the speed of getetag calls
|
||||
* SoObjects/SOGo/SOGoGCSFolder.m
|
||||
We now allow multiple users subscribe/unsubscribe
|
||||
requests during one DAV call.
|
||||
|
||||
2008-11-13 Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentObject.m
|
||||
|
||||
@@ -32,6 +32,7 @@ Appointments_OBJC_FILES = \
|
||||
SOGoAptMailInvitation.m \
|
||||
SOGoAptMailDeletion.m \
|
||||
SOGoAptMailICalReply.m \
|
||||
SOGoAptMailUpdate.m \
|
||||
|
||||
Appointments_RESOURCE_FILES += \
|
||||
Version \
|
||||
@@ -45,21 +46,27 @@ Appointments_COMPONENTS += \
|
||||
SOGoAptMailDutchInvitation.wo \
|
||||
SOGoAptMailDutchICalReply.wo \
|
||||
SOGoAptMailDutchDeletion.wo \
|
||||
SOGoAptMailDutchUpdate.wo \
|
||||
SOGoAptMailEnglishInvitation.wo \
|
||||
SOGoAptMailEnglishICalReply.wo \
|
||||
SOGoAptMailEnglishDeletion.wo \
|
||||
SOGoAptMailEnglishUpdate.wo \
|
||||
SOGoAptMailFrenchInvitation.wo \
|
||||
SOGoAptMailFrenchICalReply.wo \
|
||||
SOGoAptMailFrenchDeletion.wo \
|
||||
SOGoAptMailFrenchUpdate.wo \
|
||||
SOGoAptMailGermanInvitation.wo \
|
||||
SOGoAptMailGermanICalReply.wo \
|
||||
SOGoAptMailGermanDeletion.wo \
|
||||
SOGoAptMailGermanUpdate.wo \
|
||||
SOGoAptMailItalianInvitation.wo \
|
||||
SOGoAptMailItalianICalReply.wo \
|
||||
SOGoAptMailItalianDeletion.wo \
|
||||
SOGoAptMailItalianUpdate.wo \
|
||||
SOGoAptMailSpanishInvitation.wo \
|
||||
SOGoAptMailSpanishICalReply.wo \
|
||||
SOGoAptMailSpanishDeletion.wo \
|
||||
SOGoAptMailSpanishUpdate.wo \
|
||||
|
||||
|
||||
ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/
|
||||
|
||||
@@ -1005,19 +1005,19 @@ static Class sogoAppointmentFolderKlass = Nil;
|
||||
}
|
||||
|
||||
- (void) _appendPropstat: (NSDictionary *) propstat
|
||||
toResponse: (WOResponse *) r
|
||||
toBuffer: (NSMutableString *) r
|
||||
{
|
||||
NSArray *properties;
|
||||
unsigned int count, max;
|
||||
|
||||
[r appendContentString: @"<D:propstat><D:prop>"];
|
||||
[r appendString: @"<D:propstat><D:prop>"];
|
||||
properties = [propstat objectForKey: @"properties"];
|
||||
max = [properties count];
|
||||
for (count = 0; count < max; count++)
|
||||
[r appendContentString: [properties objectAtIndex: count]];
|
||||
[r appendContentString: @"</D:prop><D:status>"];
|
||||
[r appendContentString: [propstat objectForKey: @"status"]];
|
||||
[r appendContentString: @"</D:status></D:propstat>"];
|
||||
[r appendString: [properties objectAtIndex: count]];
|
||||
[r appendString: @"</D:prop><D:status>"];
|
||||
[r appendString: [propstat objectForKey: @"status"]];
|
||||
[r appendString: @"</D:status></D:propstat>"];
|
||||
}
|
||||
|
||||
#warning we should use the EOFetchSpecification for that!!! (see doPROPFIND:)
|
||||
@@ -1062,11 +1062,12 @@ static Class sogoAppointmentFolderKlass = Nil;
|
||||
- (NSString **) _properties: (NSString **) properties
|
||||
ofObject: (NSDictionary *) object
|
||||
{
|
||||
SOGoCalendarComponent *sogoObject;
|
||||
NSString **currentProperty;
|
||||
NSString **values, **currentValue;
|
||||
SOGoObject *sogoObject;
|
||||
SoSecurityManager *mgr;
|
||||
SEL methodSel;
|
||||
Class c;
|
||||
|
||||
#warning things may crash here...
|
||||
values = calloc (100, sizeof (NSMutableString *));
|
||||
@@ -1075,7 +1076,11 @@ static Class sogoAppointmentFolderKlass = Nil;
|
||||
|
||||
#warning this check should be done directly in the query... we should fix this sometime
|
||||
mgr = [SoSecurityManager sharedSecurityManager];
|
||||
sogoObject = [self _createChildComponentWithRecord: object];
|
||||
|
||||
//c = [self objectClassForComponentName: [object objectForKey: @"c_component"]];
|
||||
sogoObject = [SOGoCalendarComponent objectWithRecord: object inContainer: self];
|
||||
[sogoObject setComponentTag: [object objectForKey: @"c_component"]];
|
||||
//sogoObject = [self _createChildComponentWithRecord: object];
|
||||
|
||||
if (activeUserIsOwner
|
||||
|| [[self ownerInContext: context]
|
||||
@@ -1167,35 +1172,35 @@ static Class sogoAppointmentFolderKlass = Nil;
|
||||
- (void) appendObject: (NSDictionary *) object
|
||||
properties: (NSString **) properties
|
||||
withBaseURL: (NSString *) baseURL
|
||||
toComplexResponse: (WOResponse *) r
|
||||
toBuffer: (NSMutableString *) r
|
||||
{
|
||||
NSArray *propstats;
|
||||
unsigned int count, max;
|
||||
|
||||
[r appendContentString: @"<D:response><D:href>"];
|
||||
[r appendContentString: baseURL];
|
||||
[r appendFormat: @"<D:response><D:href>"];
|
||||
[r appendString: baseURL];
|
||||
// if (![baseURL hasSuffix: @"/"])
|
||||
// [r appendContentString: @"/"];
|
||||
[r appendContentString: [object objectForKey: @"c_name"]];
|
||||
[r appendContentString: @"</D:href>"];
|
||||
[r appendString: [object objectForKey: @"c_name"]];
|
||||
[r appendString: @"</D:href>"];
|
||||
|
||||
// NSLog (@"(appendPropstats...): %@", [NSDate date]);
|
||||
propstats = [self _propstats: properties ofObject: object];
|
||||
max = [propstats count];
|
||||
for (count = 0; count < max; count++)
|
||||
[self _appendPropstat: [propstats objectAtIndex: count]
|
||||
toResponse: r];
|
||||
toBuffer: r];
|
||||
// NSLog (@"/(appendPropstats...): %@", [NSDate date]);
|
||||
|
||||
[r appendContentString: @"</D:response>"];
|
||||
[r appendString: @"</D:response>"];
|
||||
}
|
||||
|
||||
- (void) appendMissingObjectRef: (NSString *) href
|
||||
toComplexResponse: (WOResponse *) r
|
||||
toBuffer: (NSMutableString *) r
|
||||
{
|
||||
[r appendContentString: @"<D:response><D:href>"];
|
||||
[r appendContentString: href];
|
||||
[r appendContentString: @"</D:href><D:status>HTTP/1.1 404 Not Found</D:status></D:response>"];
|
||||
[r appendString: @"<D:response><D:href>"];
|
||||
[r appendString: href];
|
||||
[r appendString: @"</D:href><D:status>HTTP/1.1 404 Not Found</D:status></D:response>"];
|
||||
}
|
||||
|
||||
- (void) _appendTimeRange: (id <DOMElement>) timeRangeElement
|
||||
@@ -1452,33 +1457,48 @@ static Class sogoAppointmentFolderKlass = Nil;
|
||||
matchingFilters: (NSArray *) filters
|
||||
toResponse: (WOResponse *) response
|
||||
{
|
||||
NSArray *apts;
|
||||
NSArray *apts, *fields;
|
||||
NSDictionary *currentFilter;
|
||||
NSEnumerator *filterList;
|
||||
NSString *additionalFilters, *baseURL;
|
||||
NSMutableString *buffer;
|
||||
unsigned int count, max;
|
||||
|
||||
baseURL = [[self davURL] absoluteString];
|
||||
|
||||
|
||||
// We check if we need to fetch all fields. If the DAV client
|
||||
// has only asked for {DAV:}getetag with no other properties,
|
||||
// we do not load the c_content and other fields from the
|
||||
// database as this can be pretty costly.
|
||||
if ([*properties caseInsensitiveCompare: @"{DAV:}getetag"] == NSOrderedSame &&
|
||||
!*(properties+1))
|
||||
fields =[NSArray arrayWithObjects: @"c_name", @"c_version",
|
||||
@"c_component", nil];
|
||||
else
|
||||
fields = reportQueryFields;
|
||||
|
||||
filterList = [filters objectEnumerator];
|
||||
while ((currentFilter = [filterList nextObject]))
|
||||
{
|
||||
additionalFilters = [self _composeAdditionalFilters: currentFilter];
|
||||
// NSLog(@"query");
|
||||
apts = [self bareFetchFields: reportQueryFields
|
||||
NSLog(@"query");
|
||||
apts = [self bareFetchFields: fields
|
||||
from: [currentFilter objectForKey: @"start"]
|
||||
to: [currentFilter objectForKey: @"end"]
|
||||
title: [currentFilter objectForKey: @"title"]
|
||||
component: [currentFilter objectForKey: @"name"]
|
||||
additionalFilters: additionalFilters];
|
||||
// NSLog(@"adding properties");
|
||||
NSLog(@"adding properties");
|
||||
max = [apts count];
|
||||
buffer = [[NSMutableString alloc] initWithCapacity: max*512];
|
||||
for (count = 0; count < max; count++)
|
||||
[self appendObject: [apts objectAtIndex: count]
|
||||
properties: properties
|
||||
withBaseURL: baseURL
|
||||
toComplexResponse: response];
|
||||
// NSLog(@"done");
|
||||
toBuffer: buffer];
|
||||
NSLog(@"done");
|
||||
[response appendContentString: buffer];
|
||||
[buffer release];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1640,6 +1660,7 @@ static Class sogoAppointmentFolderKlass = Nil;
|
||||
NSDictionary *currentComponent, *components;
|
||||
NSString *currentURL, *baseURL;
|
||||
NSMutableArray *urls;
|
||||
NSMutableString *buffer;
|
||||
unsigned int count, max;
|
||||
|
||||
baseURL = [[self davURL] absoluteString];
|
||||
@@ -1656,6 +1677,7 @@ static Class sogoAppointmentFolderKlass = Nil;
|
||||
components = [self _fetchComponentsMatchingURLs: urls];
|
||||
max = [urls count];
|
||||
// NSLog (@"adding properties with url");
|
||||
buffer = [[NSMutableString alloc] initWithCapacity: max*512];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentComponent
|
||||
@@ -1664,11 +1686,13 @@ static Class sogoAppointmentFolderKlass = Nil;
|
||||
[self appendObject: currentComponent
|
||||
properties: properties
|
||||
withBaseURL: baseURL
|
||||
toComplexResponse: response];
|
||||
toBuffer: buffer];
|
||||
else
|
||||
[self appendMissingObjectRef: currentURL
|
||||
toComplexResponse: response];
|
||||
toBuffer: buffer];
|
||||
}
|
||||
[response appendContentString: buffer];
|
||||
[buffer release];
|
||||
// NSLog (@"/adding properties with url");
|
||||
|
||||
[urls release];
|
||||
|
||||
@@ -269,8 +269,9 @@
|
||||
forUID: currentUID];
|
||||
}
|
||||
|
||||
[self sendEMailUsingTemplateNamed: @"Invitation"
|
||||
[self sendEMailUsingTemplateNamed: @"Update"
|
||||
forObject: [newEvent itipEntryWithMethod: @"request"]
|
||||
previousObject: oldEvent
|
||||
toAttendees: updateAttendees];
|
||||
}
|
||||
|
||||
@@ -304,6 +305,7 @@
|
||||
[self _handleRemovedUsers: attendees];
|
||||
[self sendEMailUsingTemplateNamed: @"Deletion"
|
||||
forObject: [newEvent itipEntryWithMethod: @"cancel"]
|
||||
previousObject: oldEvent
|
||||
toAttendees: attendees];
|
||||
}
|
||||
|
||||
@@ -324,6 +326,7 @@
|
||||
[self _handleAddedUsers: attendees fromEvent: newEvent];
|
||||
[self sendEMailUsingTemplateNamed: @"Invitation"
|
||||
forObject: [newEvent itipEntryWithMethod: @"request"]
|
||||
previousObject: oldEvent
|
||||
toAttendees: attendees];
|
||||
}
|
||||
}
|
||||
@@ -349,6 +352,7 @@
|
||||
[self _handleAddedUsers: attendees fromEvent: newEvent];
|
||||
[self sendEMailUsingTemplateNamed: @"Invitation"
|
||||
forObject: [newEvent itipEntryWithMethod: @"request"]
|
||||
previousObject: oldEvent
|
||||
toAttendees: attendees];
|
||||
}
|
||||
|
||||
@@ -438,8 +442,8 @@
|
||||
statusChange: (NSString *) newStatus
|
||||
inEvent: (iCalEvent *) event
|
||||
{
|
||||
NSString *newContent, *currentStatus, *currentUser, *organizerUID;
|
||||
SOGoUser *ownerUser;
|
||||
NSString *newContent, *currentStatus, *organizerUID;
|
||||
SOGoUser *ownerUser, *currentUser;
|
||||
NSException *ex;
|
||||
|
||||
ex = nil;
|
||||
@@ -571,6 +575,7 @@
|
||||
#warning fix this when sendEmailUsing blabla has been cleaned up
|
||||
[self sendEMailUsingTemplateNamed: @"Invitation"
|
||||
forObject: event
|
||||
previousObject: nil
|
||||
toAttendees: [NSArray arrayWithObject: person]];
|
||||
[person release];
|
||||
[elements
|
||||
@@ -604,6 +609,7 @@
|
||||
#warning fix this when sendEmailUsing blabla has been cleaned up
|
||||
[self sendEMailUsingTemplateNamed: @"Deletion"
|
||||
forObject: event
|
||||
previousObject: nil
|
||||
toAttendees: [NSArray arrayWithObject: person]];
|
||||
[person release];
|
||||
[elements
|
||||
@@ -805,6 +811,7 @@
|
||||
[self _handleRemovedUsers: attendees];
|
||||
[self sendEMailUsingTemplateNamed: @"Deletion"
|
||||
forObject: [occurence itipEntryWithMethod: @"cancel"]
|
||||
previousObject: nil
|
||||
toAttendees: attendees];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<#IsSubject>The appointment for the <#OldAptStartDate /> at <#OldAptStartTime /> has changed</#IsSubject>
|
||||
<#IsBody>
|
||||
This appointment, previously set for <#OldAptStartDate /> at <#OldAptStartTime /> (<#OldAptLocation />) is now scheduled for <#NewAptStartDate /> at <#NewAptStartTime /> (<#NewAptLocation />).
|
||||
Please make a decision for these new settings.
|
||||
</#IsBody>
|
||||
@@ -0,0 +1,47 @@
|
||||
OldAptStartDate: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptStartTime: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartDate: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartTime: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
Organizer: WOString {
|
||||
value = organizerName;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptLocation: WOString {
|
||||
value = previousApt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptLocation: WOString {
|
||||
value = apt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
IsSubject: WOConditional {
|
||||
condition = isSubject;
|
||||
}
|
||||
|
||||
IsBody: WOConditional {
|
||||
condition = isSubject;
|
||||
negate = YES;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<#IsSubject>The appointment for the <#OldAptStartDate /> at <#OldAptStartTime /> has changed</#IsSubject>
|
||||
<#IsBody>
|
||||
This appointment, previously set for <#OldAptStartDate /> at <#OldAptStartTime /> (<#OldAptLocation />) is now scheduled for <#NewAptStartDate /> at <#NewAptStartTime /> (<#NewAptLocation />).
|
||||
Please make a decision for these new settings.
|
||||
</#IsBody>
|
||||
@@ -0,0 +1,47 @@
|
||||
OldAptStartDate: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptStartTime: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartDate: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartTime: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
Organizer: WOString {
|
||||
value = organizerName;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptLocation: WOString {
|
||||
value = previousApt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptLocation: WOString {
|
||||
value = apt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
IsSubject: WOConditional {
|
||||
condition = isSubject;
|
||||
}
|
||||
|
||||
IsBody: WOConditional {
|
||||
condition = isSubject;
|
||||
negate = YES;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<#IsSubject>Le rendez-vous du <#OldAptStartDate /> à <#OldAptStartTime /> est modifié</#IsSubject>
|
||||
<#IsBody>
|
||||
La réunion qui devait se dérouler le <#OldAptStartDate /> à <#OldAptStartTime /> (<#OldAptLocation />) est maintenant prévue le <#NewAptStartDate /> à <#NewAptStartTime /> (<#NewAptLocation />).
|
||||
Vous êtes invité à accepter ou refuser de participer à la réunion pour cette nouvelle date.
|
||||
</#IsBody>
|
||||
@@ -0,0 +1,47 @@
|
||||
OldAptStartDate: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptStartTime: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartDate: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartTime: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
Organizer: WOString {
|
||||
value = organizerName;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptLocation: WOString {
|
||||
value = previousApt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptLocation: WOString {
|
||||
value = apt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
IsSubject: WOConditional {
|
||||
condition = isSubject;
|
||||
}
|
||||
|
||||
IsBody: WOConditional {
|
||||
condition = isSubject;
|
||||
negate = YES;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<#IsSubject>The appointment for the <#OldAptStartDate /> at <#OldAptStartTime /> has changed</#IsSubject>
|
||||
<#IsBody>
|
||||
This appointment, previously set for <#OldAptStartDate /> at <#OldAptStartTime /> (<#OldAptLocation />) is now scheduled for <#NewAptStartDate /> at <#NewAptStartTime /> (<#NewAptLocation />).
|
||||
Please make a decision for these new settings.
|
||||
</#IsBody>
|
||||
@@ -0,0 +1,47 @@
|
||||
OldAptStartDate: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptStartTime: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartDate: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartTime: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
Organizer: WOString {
|
||||
value = organizerName;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptLocation: WOString {
|
||||
value = previousApt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptLocation: WOString {
|
||||
value = apt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
IsSubject: WOConditional {
|
||||
condition = isSubject;
|
||||
}
|
||||
|
||||
IsBody: WOConditional {
|
||||
condition = isSubject;
|
||||
negate = YES;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<#IsSubject>L'appuntamento fissato in data <#OldAptStartDate /> alle ore <#OldAptStartTime /> è stato modificato </#IsSubject>
|
||||
<#IsBody>
|
||||
Questo appuntamento, fissato precedentemete in data <#OldAptStartDate /> (<#OldAptLocation />)
|
||||
alle ore <#OldAptStartTime /> è ora programmato il <#NewAptStartDate
|
||||
/> alle ore <#NewAptStartTime
|
||||
/> (<#NewAptLocation />)
|
||||
Per confermare o disdire.
|
||||
</#IsBody>
|
||||
@@ -0,0 +1,47 @@
|
||||
OldAptStartDate: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptStartTime: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartDate: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartTime: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
Organizer: WOString {
|
||||
value = organizerName;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptLocation: WOString {
|
||||
value = previousApt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptLocation: WOString {
|
||||
value = apt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
IsSubject: WOConditional {
|
||||
condition = isSubject;
|
||||
}
|
||||
|
||||
IsBody: WOConditional {
|
||||
condition = isSubject;
|
||||
negate = YES;
|
||||
}
|
||||
@@ -34,7 +34,8 @@
|
||||
*/
|
||||
@interface SOGoAptMailNotification : SoComponent
|
||||
{
|
||||
iCalEntityObject* apt;
|
||||
iCalEntityObject *apt;
|
||||
iCalEntityObject *previousApt;
|
||||
NSString *homePageURL;
|
||||
NSTimeZone *viewTZ;
|
||||
NSCalendarDate *oldStartDate;
|
||||
@@ -44,9 +45,16 @@
|
||||
}
|
||||
|
||||
- (iCalEntityObject *) apt;
|
||||
- (void) setApt: (iCalEntityObject *) newApt;
|
||||
- (void) setApt: (iCalEntityObject *) theApt;
|
||||
|
||||
/* Content Generation */
|
||||
- (iCalEntityObject *) previousApt;
|
||||
- (void) setPreviousApt: (iCalEntityObject *) theApt;
|
||||
|
||||
- (void) setOrganizerName: (NSString *) theString;
|
||||
- (NSString *) organizerName;
|
||||
|
||||
- (BOOL) hasSentBy;
|
||||
- (NSString *) sentBy;
|
||||
|
||||
- (NSString *) getSubject;
|
||||
- (NSString *) getBody;
|
||||
|
||||
@@ -68,7 +68,11 @@ static NSTimeZone *UTC = nil;
|
||||
- (void) dealloc
|
||||
{
|
||||
[apt release];
|
||||
[previousApt release];
|
||||
[organizerName release];
|
||||
[viewTZ release];
|
||||
[oldStartDate release];
|
||||
[newStartDate release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@@ -77,11 +81,50 @@ static NSTimeZone *UTC = nil;
|
||||
return apt;
|
||||
}
|
||||
|
||||
- (void) setApt: (iCalEntityObject *) newApt
|
||||
- (void) setApt: (iCalEntityObject *) theApt
|
||||
{
|
||||
ASSIGN (apt, newApt);
|
||||
ASSIGN(apt, theApt);
|
||||
}
|
||||
|
||||
- (iCalEntityObject *) previousApt
|
||||
{
|
||||
return previousApt;
|
||||
}
|
||||
|
||||
- (void) setPreviousApt: (iCalEntityObject *) theApt
|
||||
{
|
||||
ASSIGN(previousApt, theApt);
|
||||
}
|
||||
|
||||
- (NSTimeZone *) viewTZ
|
||||
{
|
||||
if (self->viewTZ) return self->viewTZ;
|
||||
return UTC;
|
||||
}
|
||||
- (void) setViewTZ: (NSTimeZone *) _viewTZ
|
||||
{
|
||||
ASSIGN(self->viewTZ, _viewTZ);
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) oldStartDate
|
||||
{
|
||||
if (!self->oldStartDate)
|
||||
{
|
||||
ASSIGN(self->oldStartDate, [[self previousApt] startDate]);
|
||||
[self->oldStartDate setTimeZone: [self viewTZ]];
|
||||
}
|
||||
return self->oldStartDate;
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) newStartDate
|
||||
{
|
||||
if (!self->newStartDate)
|
||||
{
|
||||
ASSIGN(self->newStartDate, [[self apt] startDate]);
|
||||
[self->newStartDate setTimeZone:[self viewTZ]];
|
||||
}
|
||||
return self->newStartDate;
|
||||
}
|
||||
|
||||
- (BOOL) isSubject
|
||||
{
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<#IsSubject>The appointment for the <#OldAptStartDate /> at <#OldAptStartTime /> has changed</#IsSubject>
|
||||
<#IsBody>
|
||||
This appointment, previously set for <#OldAptStartDate /> at <#OldAptStartTime /> (<#OldAptLocation />) is now scheduled for <#NewAptStartDate /> at <#NewAptStartTime /> (<#NewAptLocation />).
|
||||
Please make a decision for these new settings.
|
||||
</#IsBody>
|
||||
@@ -0,0 +1,47 @@
|
||||
OldAptStartDate: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptStartTime: WOString {
|
||||
value = oldStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartDate: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%d/%m/%y";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptStartTime: WOString {
|
||||
value = newStartDate;
|
||||
dateformat = "%H:%M";
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
Organizer: WOString {
|
||||
value = organizerName;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
OldAptLocation: WOString {
|
||||
value = previousApt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
NewAptLocation: WOString {
|
||||
value = apt.location;
|
||||
escapeHTML = NO;
|
||||
}
|
||||
|
||||
IsSubject: WOConditional {
|
||||
condition = isSubject;
|
||||
}
|
||||
|
||||
IsBody: WOConditional {
|
||||
condition = isSubject;
|
||||
negate = YES;
|
||||
}
|
||||
57
SoObjects/Appointments/SOGoAptMailUpdate.m
Normal file
57
SoObjects/Appointments/SOGoAptMailUpdate.m
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of OpenGroupware.org.
|
||||
|
||||
OGo 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
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with OGo; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "SOGoAptMailNotification.h"
|
||||
|
||||
@interface SOGoAptMailEnglishUpdate : SOGoAptMailNotification
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SOGoAptMailEnglishUpdate
|
||||
@end
|
||||
|
||||
@interface SOGoAptMailFrenchUpdate : SOGoAptMailNotification
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SOGoAptMailFrenchUpdate
|
||||
@end
|
||||
|
||||
|
||||
@interface SOGoAptMailGermanUpdate : SOGoAptMailNotification
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SOGoAptMailGermanUpdate
|
||||
@end
|
||||
|
||||
|
||||
@interface SOGoAptMailItalianUpdate : SOGoAptMailNotification
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SOGoAptMailItalianUpdate
|
||||
@end
|
||||
|
||||
@@ -42,9 +42,11 @@
|
||||
iCalCalendar *fullCalendar;
|
||||
iCalCalendar *safeCalendar;
|
||||
iCalCalendar *originalCalendar;
|
||||
NSString *componentTag;
|
||||
}
|
||||
|
||||
- (NSString *) componentTag;
|
||||
- (void) setComponentTag: (NSString *) theTag;
|
||||
|
||||
- (iCalCalendar *) calendar: (BOOL) create
|
||||
secure: (BOOL) secure;
|
||||
@@ -61,6 +63,7 @@
|
||||
- (BOOL) sendEMailNotifications;
|
||||
- (void) sendEMailUsingTemplateNamed: (NSString *) pageName
|
||||
forObject: (iCalRepeatableEntityObject *) object
|
||||
previousObject: (iCalRepeatableEntityObject *) previousObject
|
||||
toAttendees: (NSArray *) attendees;
|
||||
- (void) sendIMIPReplyForEvent: (iCalRepeatableEntityObject *) event
|
||||
from: (SOGoUser *) from
|
||||
|
||||
@@ -83,6 +83,7 @@ static BOOL sendEMailNotifications = NO;
|
||||
fullCalendar = nil;
|
||||
safeCalendar = nil;
|
||||
originalCalendar = nil;
|
||||
componentTag = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -93,6 +94,7 @@ static BOOL sendEMailNotifications = NO;
|
||||
[fullCalendar release];
|
||||
[safeCalendar release];
|
||||
[originalCalendar release];
|
||||
[componentTag release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@@ -103,9 +105,15 @@ static BOOL sendEMailNotifications = NO;
|
||||
|
||||
- (NSString *) componentTag
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
if (!componentTag)
|
||||
[self subclassResponsibility: _cmd];
|
||||
|
||||
return nil;
|
||||
return componentTag;
|
||||
}
|
||||
|
||||
- (void) setComponentTag: (NSString *) theTag
|
||||
{
|
||||
ASSIGN(componentTag, theTag);
|
||||
}
|
||||
|
||||
- (void) _filterComponent: (iCalEntityObject *) component
|
||||
@@ -326,10 +334,9 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
|
||||
|
||||
- (iCalCalendar *) calendar: (BOOL) create secure: (BOOL) secure
|
||||
{
|
||||
NSString *componentTag;
|
||||
iCalRepeatableEntityObject *newComponent;
|
||||
iCalCalendar **calendar, *returnedCopy;
|
||||
NSString *iCalString;
|
||||
NSString *iCalString, *tag;
|
||||
|
||||
if (secure)
|
||||
calendar = &safeCalendar;
|
||||
@@ -356,9 +363,9 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
|
||||
ASSIGN (*calendar, [iCalCalendar groupWithTag: @"vcalendar"]);
|
||||
[*calendar setVersion: @"2.0"];
|
||||
[*calendar setProdID: @"-//Inverse inc.//SOGo 0.9//EN"];
|
||||
componentTag = [[self componentTag] uppercaseString];
|
||||
newComponent = [[*calendar classForTag: componentTag]
|
||||
groupWithTag: componentTag];
|
||||
tag = [[self componentTag] uppercaseString];
|
||||
newComponent = [[*calendar classForTag: tag]
|
||||
groupWithTag: tag];
|
||||
[newComponent setUid: [self globallyUniqueObjectId]];
|
||||
[*calendar addChild: newComponent];
|
||||
}
|
||||
@@ -453,6 +460,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
|
||||
|
||||
- (void) sendEMailUsingTemplateNamed: (NSString *) newPageName
|
||||
forObject: (iCalRepeatableEntityObject *) object
|
||||
previousObject: (iCalRepeatableEntityObject *) previousObject
|
||||
toAttendees: (NSArray *) attendees
|
||||
{
|
||||
NSString *pageName;
|
||||
@@ -467,7 +475,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
|
||||
NGMimeMessage *msg;
|
||||
NGMimeBodyPart *bodyPart;
|
||||
NGMimeMultipartBody *body;
|
||||
SOGoUser *ownerUser, *currentUser;
|
||||
SOGoUser *ownerUser;
|
||||
|
||||
if (sendEMailNotifications
|
||||
&& [object isStillRelevant])
|
||||
@@ -511,6 +519,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
|
||||
/* construct message content */
|
||||
p = [app pageWithName: pageName inContext: context];
|
||||
[p setApt: object];
|
||||
[p setPreviousApt: previousObject];
|
||||
|
||||
if ([[object organizer] cn] && [[[object organizer] cn] length])
|
||||
{
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
- (void) renameTo: (NSString *) newName;
|
||||
|
||||
- (WOResponse *) subscribe: (BOOL) reallyDo
|
||||
inTheNameOf: (NSString *) delegatedUser
|
||||
inTheNamesOf: (NSArray *) delegatedUsers
|
||||
fromMailInvitation: (BOOL) isMailInvitation
|
||||
inContext: (WOContext *) localContext;
|
||||
|
||||
|
||||
@@ -660,59 +660,72 @@ static NSArray *childRecordFields = nil;
|
||||
}
|
||||
|
||||
- (WOResponse *) subscribe: (BOOL) reallyDo
|
||||
inTheNameOf: (NSString *) delegatedUser
|
||||
inTheNamesOf: (NSArray *) delegatedUsers
|
||||
fromMailInvitation: (BOOL) isMailInvitation
|
||||
inContext: (WOContext *) localContext
|
||||
{
|
||||
WOResponse *response;
|
||||
SOGoUser *currentUser, *subscriptionUser;
|
||||
BOOL validRequest;
|
||||
SOGoUser *currentUser;
|
||||
|
||||
response = [localContext response];
|
||||
currentUser = [localContext activeUser];
|
||||
|
||||
if ([delegatedUser length])
|
||||
if (delegatedUsers && [delegatedUsers count])
|
||||
{
|
||||
validRequest = ([currentUser isSuperUser]);
|
||||
subscriptionUser = [SOGoUser userWithLogin: delegatedUser roles: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
validRequest = YES;
|
||||
subscriptionUser = currentUser;
|
||||
}
|
||||
if (![currentUser isSuperUser])
|
||||
{
|
||||
[response setStatus: 403];
|
||||
[response appendContentString:
|
||||
@"You cannot subscribe another user to any folder"
|
||||
@" unless you are a super-user."];
|
||||
}
|
||||
else
|
||||
{
|
||||
SOGoUser *subscriptionUser;
|
||||
int i;
|
||||
|
||||
if (validRequest)
|
||||
[self _subscribeUser: subscriptionUser
|
||||
reallyDo: reallyDo
|
||||
fromMailInvitation: isMailInvitation
|
||||
inResponse: response];
|
||||
for (i = 0; i < [delegatedUsers count]; i++)
|
||||
{
|
||||
subscriptionUser = [SOGoUser userWithLogin: [delegatedUsers objectAtIndex: i]
|
||||
roles: nil];
|
||||
|
||||
[self _subscribeUser: subscriptionUser
|
||||
reallyDo: reallyDo
|
||||
fromMailInvitation: isMailInvitation
|
||||
inResponse: response];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[response setStatus: 403];
|
||||
[response appendContentString:
|
||||
@"You cannot subscribe another user to any folder"
|
||||
@" unless you are a super-user."];
|
||||
[self _subscribeUser: currentUser
|
||||
reallyDo: reallyDo
|
||||
fromMailInvitation: isMailInvitation
|
||||
inResponse: response];
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
- (NSString *) _parseDAVDelegatedUser: (WOContext *) queryContext
|
||||
- (NSArray *) _parseDAVDelegatedUser: (WOContext *) queryContext
|
||||
{
|
||||
id <DOMDocument> document;
|
||||
id <DOMNamedNodeMap> attrs;
|
||||
|
||||
id o;
|
||||
document = [[queryContext request] contentAsDOMDocument];
|
||||
attrs = [[document documentElement] attributes];
|
||||
|
||||
return [[attrs namedItem: @"user"] nodeValue];
|
||||
o = [attrs namedItem: @"users"];
|
||||
|
||||
if (o) return [[o nodeValue] componentsSeparatedByString: @","];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) davSubscribe: (WOContext *) queryContext
|
||||
{
|
||||
return [self subscribe: YES
|
||||
inTheNameOf: [self _parseDAVDelegatedUser: queryContext]
|
||||
inTheNamesOf: [self _parseDAVDelegatedUser: queryContext]
|
||||
fromMailInvitation: NO
|
||||
inContext: queryContext];
|
||||
}
|
||||
@@ -720,7 +733,7 @@ static NSArray *childRecordFields = nil;
|
||||
- (id <WOActionResults>) davUnsubscribe: (WOContext *) queryContext
|
||||
{
|
||||
return [self subscribe: NO
|
||||
inTheNameOf: [self _parseDAVDelegatedUser: queryContext]
|
||||
inTheNamesOf: [self _parseDAVDelegatedUser: queryContext]
|
||||
fromMailInvitation: NO
|
||||
inContext: queryContext];
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
[self _setupContext];
|
||||
|
||||
return [clientObject subscribe: YES
|
||||
inTheNameOf: nil
|
||||
inTheNamesOf: nil
|
||||
fromMailInvitation: isMailInvitation
|
||||
inContext: context];
|
||||
}
|
||||
@@ -91,7 +91,7 @@
|
||||
[self _setupContext];
|
||||
|
||||
return [clientObject subscribe: NO
|
||||
inTheNameOf: nil
|
||||
inTheNamesOf: nil
|
||||
fromMailInvitation: isMailInvitation
|
||||
inContext: context];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user