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:
Ludovic Marcotte committed 2008-11-18 00:06:37 +00:00
1 parent 85c9c6e402
commit 3539a06f83
24 files changed
+569 -73

No files matched your search

+10
View File
@@ -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> 2008-11-13 Ludovic Marcotte <lmarcotte@inverse.ca>
* SoObjects/Appointments/SOGoAppointmentObject.m * SoObjects/Appointments/SOGoAppointmentObject.m
+7
View File
@@ -32,6 +32,7 @@ Appointments_OBJC_FILES = \
SOGoAptMailInvitation.m \ SOGoAptMailInvitation.m \
SOGoAptMailDeletion.m \ SOGoAptMailDeletion.m \
SOGoAptMailICalReply.m \ SOGoAptMailICalReply.m \
SOGoAptMailUpdate.m \
Appointments_RESOURCE_FILES += \ Appointments_RESOURCE_FILES += \
Version \ Version \
@@ -45,21 +46,27 @@ Appointments_COMPONENTS += \
SOGoAptMailDutchInvitation.wo \ SOGoAptMailDutchInvitation.wo \
SOGoAptMailDutchICalReply.wo \ SOGoAptMailDutchICalReply.wo \
SOGoAptMailDutchDeletion.wo \ SOGoAptMailDutchDeletion.wo \
SOGoAptMailDutchUpdate.wo \
SOGoAptMailEnglishInvitation.wo \ SOGoAptMailEnglishInvitation.wo \
SOGoAptMailEnglishICalReply.wo \ SOGoAptMailEnglishICalReply.wo \
SOGoAptMailEnglishDeletion.wo \ SOGoAptMailEnglishDeletion.wo \
SOGoAptMailEnglishUpdate.wo \
SOGoAptMailFrenchInvitation.wo \ SOGoAptMailFrenchInvitation.wo \
SOGoAptMailFrenchICalReply.wo \ SOGoAptMailFrenchICalReply.wo \
SOGoAptMailFrenchDeletion.wo \ SOGoAptMailFrenchDeletion.wo \
SOGoAptMailFrenchUpdate.wo \
SOGoAptMailGermanInvitation.wo \ SOGoAptMailGermanInvitation.wo \
SOGoAptMailGermanICalReply.wo \ SOGoAptMailGermanICalReply.wo \
SOGoAptMailGermanDeletion.wo \ SOGoAptMailGermanDeletion.wo \
SOGoAptMailGermanUpdate.wo \
SOGoAptMailItalianInvitation.wo \ SOGoAptMailItalianInvitation.wo \
SOGoAptMailItalianICalReply.wo \ SOGoAptMailItalianICalReply.wo \
SOGoAptMailItalianDeletion.wo \ SOGoAptMailItalianDeletion.wo \
SOGoAptMailItalianUpdate.wo \
SOGoAptMailSpanishInvitation.wo \ SOGoAptMailSpanishInvitation.wo \
SOGoAptMailSpanishICalReply.wo \ SOGoAptMailSpanishICalReply.wo \
SOGoAptMailSpanishDeletion.wo \ SOGoAptMailSpanishDeletion.wo \
SOGoAptMailSpanishUpdate.wo \
ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/ ADDITIONAL_INCLUDE_DIRS += -I../../SOPE/
+52 -28
View File
@@ -1005,19 +1005,19 @@ static Class sogoAppointmentFolderKlass = Nil;
} }
- (void) _appendPropstat: (NSDictionary *) propstat - (void) _appendPropstat: (NSDictionary *) propstat
toResponse: (WOResponse *) r toBuffer: (NSMutableString *) r
{ {
NSArray *properties; NSArray *properties;
unsigned int count, max; unsigned int count, max;
[r appendContentString: @"<D:propstat><D:prop>"]; [r appendString: @"<D:propstat><D:prop>"];
properties = [propstat objectForKey: @"properties"]; properties = [propstat objectForKey: @"properties"];
max = [properties count]; max = [properties count];
for (count = 0; count < max; count++) for (count = 0; count < max; count++)
[r appendContentString: [properties objectAtIndex: count]]; [r appendString: [properties objectAtIndex: count]];
[r appendContentString: @"</D:prop><D:status>"]; [r appendString: @"</D:prop><D:status>"];
[r appendContentString: [propstat objectForKey: @"status"]]; [r appendString: [propstat objectForKey: @"status"]];
[r appendContentString: @"</D:status></D:propstat>"]; [r appendString: @"</D:status></D:propstat>"];
} }
#warning we should use the EOFetchSpecification for that!!! (see doPROPFIND:) #warning we should use the EOFetchSpecification for that!!! (see doPROPFIND:)
@@ -1062,11 +1062,12 @@ static Class sogoAppointmentFolderKlass = Nil;
- (NSString **) _properties: (NSString **) properties - (NSString **) _properties: (NSString **) properties
ofObject: (NSDictionary *) object ofObject: (NSDictionary *) object
{ {
SOGoCalendarComponent *sogoObject;
NSString **currentProperty; NSString **currentProperty;
NSString **values, **currentValue; NSString **values, **currentValue;
SOGoObject *sogoObject;
SoSecurityManager *mgr; SoSecurityManager *mgr;
SEL methodSel; SEL methodSel;
Class c;
#warning things may crash here... #warning things may crash here...
values = calloc (100, sizeof (NSMutableString *)); 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 #warning this check should be done directly in the query... we should fix this sometime
mgr = [SoSecurityManager sharedSecurityManager]; 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 if (activeUserIsOwner
|| [[self ownerInContext: context] || [[self ownerInContext: context]
@@ -1167,35 +1172,35 @@ static Class sogoAppointmentFolderKlass = Nil;
- (void) appendObject: (NSDictionary *) object - (void) appendObject: (NSDictionary *) object
properties: (NSString **) properties properties: (NSString **) properties
withBaseURL: (NSString *) baseURL withBaseURL: (NSString *) baseURL
toComplexResponse: (WOResponse *) r toBuffer: (NSMutableString *) r
{ {
NSArray *propstats; NSArray *propstats;
unsigned int count, max; unsigned int count, max;
[r appendContentString: @"<D:response><D:href>"]; [r appendFormat: @"<D:response><D:href>"];
[r appendContentString: baseURL]; [r appendString: baseURL];
// if (![baseURL hasSuffix: @"/"]) // if (![baseURL hasSuffix: @"/"])
// [r appendContentString: @"/"]; // [r appendContentString: @"/"];
[r appendContentString: [object objectForKey: @"c_name"]]; [r appendString: [object objectForKey: @"c_name"]];
[r appendContentString: @"</D:href>"]; [r appendString: @"</D:href>"];
// NSLog (@"(appendPropstats...): %@", [NSDate date]); // NSLog (@"(appendPropstats...): %@", [NSDate date]);
propstats = [self _propstats: properties ofObject: object]; propstats = [self _propstats: properties ofObject: object];
max = [propstats count]; max = [propstats count];
for (count = 0; count < max; count++) for (count = 0; count < max; count++)
[self _appendPropstat: [propstats objectAtIndex: count] [self _appendPropstat: [propstats objectAtIndex: count]
toResponse: r]; toBuffer: r];
// NSLog (@"/(appendPropstats...): %@", [NSDate date]); // NSLog (@"/(appendPropstats...): %@", [NSDate date]);
[r appendContentString: @"</D:response>"]; [r appendString: @"</D:response>"];
} }
- (void) appendMissingObjectRef: (NSString *) href - (void) appendMissingObjectRef: (NSString *) href
toComplexResponse: (WOResponse *) r toBuffer: (NSMutableString *) r
{ {
[r appendContentString: @"<D:response><D:href>"]; [r appendString: @"<D:response><D:href>"];
[r appendContentString: href]; [r appendString: href];
[r appendContentString: @"</D:href><D:status>HTTP/1.1 404 Not Found</D:status></D:response>"]; [r appendString: @"</D:href><D:status>HTTP/1.1 404 Not Found</D:status></D:response>"];
} }
- (void) _appendTimeRange: (id <DOMElement>) timeRangeElement - (void) _appendTimeRange: (id <DOMElement>) timeRangeElement
@@ -1452,33 +1457,48 @@ static Class sogoAppointmentFolderKlass = Nil;
matchingFilters: (NSArray *) filters matchingFilters: (NSArray *) filters
toResponse: (WOResponse *) response toResponse: (WOResponse *) response
{ {
NSArray *apts; NSArray *apts, *fields;
NSDictionary *currentFilter; NSDictionary *currentFilter;
NSEnumerator *filterList; NSEnumerator *filterList;
NSString *additionalFilters, *baseURL; NSString *additionalFilters, *baseURL;
NSMutableString *buffer;
unsigned int count, max; unsigned int count, max;
baseURL = [[self davURL] absoluteString]; 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]; filterList = [filters objectEnumerator];
while ((currentFilter = [filterList nextObject])) while ((currentFilter = [filterList nextObject]))
{ {
additionalFilters = [self _composeAdditionalFilters: currentFilter]; additionalFilters = [self _composeAdditionalFilters: currentFilter];
// NSLog(@"query"); NSLog(@"query");
apts = [self bareFetchFields: reportQueryFields apts = [self bareFetchFields: fields
from: [currentFilter objectForKey: @"start"] from: [currentFilter objectForKey: @"start"]
to: [currentFilter objectForKey: @"end"] to: [currentFilter objectForKey: @"end"]
title: [currentFilter objectForKey: @"title"] title: [currentFilter objectForKey: @"title"]
component: [currentFilter objectForKey: @"name"] component: [currentFilter objectForKey: @"name"]
additionalFilters: additionalFilters]; additionalFilters: additionalFilters];
// NSLog(@"adding properties"); NSLog(@"adding properties");
max = [apts count]; max = [apts count];
buffer = [[NSMutableString alloc] initWithCapacity: max*512];
for (count = 0; count < max; count++) for (count = 0; count < max; count++)
[self appendObject: [apts objectAtIndex: count] [self appendObject: [apts objectAtIndex: count]
properties: properties properties: properties
withBaseURL: baseURL withBaseURL: baseURL
toComplexResponse: response]; toBuffer: buffer];
// NSLog(@"done"); NSLog(@"done");
[response appendContentString: buffer];
[buffer release];
} }
} }
@@ -1640,6 +1660,7 @@ static Class sogoAppointmentFolderKlass = Nil;
NSDictionary *currentComponent, *components; NSDictionary *currentComponent, *components;
NSString *currentURL, *baseURL; NSString *currentURL, *baseURL;
NSMutableArray *urls; NSMutableArray *urls;
NSMutableString *buffer;
unsigned int count, max; unsigned int count, max;
baseURL = [[self davURL] absoluteString]; baseURL = [[self davURL] absoluteString];
@@ -1656,6 +1677,7 @@ static Class sogoAppointmentFolderKlass = Nil;
components = [self _fetchComponentsMatchingURLs: urls]; components = [self _fetchComponentsMatchingURLs: urls];
max = [urls count]; max = [urls count];
// NSLog (@"adding properties with url"); // NSLog (@"adding properties with url");
buffer = [[NSMutableString alloc] initWithCapacity: max*512];
for (count = 0; count < max; count++) for (count = 0; count < max; count++)
{ {
currentComponent currentComponent
@@ -1664,11 +1686,13 @@ static Class sogoAppointmentFolderKlass = Nil;
[self appendObject: currentComponent [self appendObject: currentComponent
properties: properties properties: properties
withBaseURL: baseURL withBaseURL: baseURL
toComplexResponse: response]; toBuffer: buffer];
else else
[self appendMissingObjectRef: currentURL [self appendMissingObjectRef: currentURL
toComplexResponse: response]; toBuffer: buffer];
} }
[response appendContentString: buffer];
[buffer release];
// NSLog (@"/adding properties with url"); // NSLog (@"/adding properties with url");
[urls release]; [urls release];
+10 -3
View File
@@ -269,8 +269,9 @@
forUID: currentUID]; forUID: currentUID];
} }
[self sendEMailUsingTemplateNamed: @"Invitation" [self sendEMailUsingTemplateNamed: @"Update"
forObject: [newEvent itipEntryWithMethod: @"request"] forObject: [newEvent itipEntryWithMethod: @"request"]
previousObject: oldEvent
toAttendees: updateAttendees]; toAttendees: updateAttendees];
} }
@@ -304,6 +305,7 @@
[self _handleRemovedUsers: attendees]; [self _handleRemovedUsers: attendees];
[self sendEMailUsingTemplateNamed: @"Deletion" [self sendEMailUsingTemplateNamed: @"Deletion"
forObject: [newEvent itipEntryWithMethod: @"cancel"] forObject: [newEvent itipEntryWithMethod: @"cancel"]
previousObject: oldEvent
toAttendees: attendees]; toAttendees: attendees];
} }
@@ -324,6 +326,7 @@
[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
toAttendees: attendees]; toAttendees: attendees];
} }
} }
@@ -349,6 +352,7 @@
[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
toAttendees: attendees]; toAttendees: attendees];
} }
@@ -438,8 +442,8 @@
statusChange: (NSString *) newStatus statusChange: (NSString *) newStatus
inEvent: (iCalEvent *) event inEvent: (iCalEvent *) event
{ {
NSString *newContent, *currentStatus, *currentUser, *organizerUID; NSString *newContent, *currentStatus, *organizerUID;
SOGoUser *ownerUser; SOGoUser *ownerUser, *currentUser;
NSException *ex; NSException *ex;
ex = nil; ex = nil;
@@ -571,6 +575,7 @@
#warning fix this when sendEmailUsing blabla has been cleaned up #warning fix this when sendEmailUsing blabla has been cleaned up
[self sendEMailUsingTemplateNamed: @"Invitation" [self sendEMailUsingTemplateNamed: @"Invitation"
forObject: event forObject: event
previousObject: nil
toAttendees: [NSArray arrayWithObject: person]]; toAttendees: [NSArray arrayWithObject: person]];
[person release]; [person release];
[elements [elements
@@ -604,6 +609,7 @@
#warning fix this when sendEmailUsing blabla has been cleaned up #warning fix this when sendEmailUsing blabla has been cleaned up
[self sendEMailUsingTemplateNamed: @"Deletion" [self sendEMailUsingTemplateNamed: @"Deletion"
forObject: event forObject: event
previousObject: nil
toAttendees: [NSArray arrayWithObject: person]]; toAttendees: [NSArray arrayWithObject: person]];
[person release]; [person release];
[elements [elements
@@ -805,6 +811,7 @@
[self _handleRemovedUsers: attendees]; [self _handleRemovedUsers: attendees];
[self sendEMailUsingTemplateNamed: @"Deletion" [self sendEMailUsingTemplateNamed: @"Deletion"
forObject: [occurence itipEntryWithMethod: @"cancel"] forObject: [occurence itipEntryWithMethod: @"cancel"]
previousObject: nil
toAttendees: attendees]; 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 /> &egrave; stato modificato </#IsSubject>
<#IsBody>
Questo appuntamento, fissato precedentemete in data <#OldAptStartDate /> (<#OldAptLocation />)
alle ore <#OldAptStartTime /> &egrave; 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 @interface SOGoAptMailNotification : SoComponent
{ {
iCalEntityObject* apt; iCalEntityObject *apt;
iCalEntityObject *previousApt;
NSString *homePageURL; NSString *homePageURL;
NSTimeZone *viewTZ; NSTimeZone *viewTZ;
NSCalendarDate *oldStartDate; NSCalendarDate *oldStartDate;
@@ -44,9 +45,16 @@
} }
- (iCalEntityObject *) apt; - (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 *) getSubject;
- (NSString *) getBody; - (NSString *) getBody;
@@ -68,7 +68,11 @@ static NSTimeZone *UTC = nil;
- (void) dealloc - (void) dealloc
{ {
[apt release]; [apt release];
[previousApt release];
[organizerName release]; [organizerName release];
[viewTZ release];
[oldStartDate release];
[newStartDate release];
[super dealloc]; [super dealloc];
} }
@@ -77,11 +81,50 @@ static NSTimeZone *UTC = nil;
return apt; 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 - (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;
}
@@ -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 *fullCalendar;
iCalCalendar *safeCalendar; iCalCalendar *safeCalendar;
iCalCalendar *originalCalendar; iCalCalendar *originalCalendar;
NSString *componentTag;
} }
- (NSString *) componentTag; - (NSString *) componentTag;
- (void) setComponentTag: (NSString *) theTag;
- (iCalCalendar *) calendar: (BOOL) create - (iCalCalendar *) calendar: (BOOL) create
secure: (BOOL) secure; secure: (BOOL) secure;
@@ -61,6 +63,7 @@
- (BOOL) sendEMailNotifications; - (BOOL) sendEMailNotifications;
- (void) sendEMailUsingTemplateNamed: (NSString *) pageName - (void) sendEMailUsingTemplateNamed: (NSString *) pageName
forObject: (iCalRepeatableEntityObject *) object forObject: (iCalRepeatableEntityObject *) object
previousObject: (iCalRepeatableEntityObject *) previousObject
toAttendees: (NSArray *) attendees; toAttendees: (NSArray *) attendees;
- (void) sendIMIPReplyForEvent: (iCalRepeatableEntityObject *) event - (void) sendIMIPReplyForEvent: (iCalRepeatableEntityObject *) event
from: (SOGoUser *) from from: (SOGoUser *) from
+17 -8
View File
@@ -83,6 +83,7 @@ static BOOL sendEMailNotifications = NO;
fullCalendar = nil; fullCalendar = nil;
safeCalendar = nil; safeCalendar = nil;
originalCalendar = nil; originalCalendar = nil;
componentTag = nil;
} }
return self; return self;
@@ -93,6 +94,7 @@ static BOOL sendEMailNotifications = NO;
[fullCalendar release]; [fullCalendar release];
[safeCalendar release]; [safeCalendar release];
[originalCalendar release]; [originalCalendar release];
[componentTag release];
[super dealloc]; [super dealloc];
} }
@@ -103,9 +105,15 @@ static BOOL sendEMailNotifications = NO;
- (NSString *) componentTag - (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 - (void) _filterComponent: (iCalEntityObject *) component
@@ -326,10 +334,9 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
- (iCalCalendar *) calendar: (BOOL) create secure: (BOOL) secure - (iCalCalendar *) calendar: (BOOL) create secure: (BOOL) secure
{ {
NSString *componentTag;
iCalRepeatableEntityObject *newComponent; iCalRepeatableEntityObject *newComponent;
iCalCalendar **calendar, *returnedCopy; iCalCalendar **calendar, *returnedCopy;
NSString *iCalString; NSString *iCalString, *tag;
if (secure) if (secure)
calendar = &safeCalendar; calendar = &safeCalendar;
@@ -356,9 +363,9 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
ASSIGN (*calendar, [iCalCalendar groupWithTag: @"vcalendar"]); ASSIGN (*calendar, [iCalCalendar groupWithTag: @"vcalendar"]);
[*calendar setVersion: @"2.0"]; [*calendar setVersion: @"2.0"];
[*calendar setProdID: @"-//Inverse inc.//SOGo 0.9//EN"]; [*calendar setProdID: @"-//Inverse inc.//SOGo 0.9//EN"];
componentTag = [[self componentTag] uppercaseString]; tag = [[self componentTag] uppercaseString];
newComponent = [[*calendar classForTag: componentTag] newComponent = [[*calendar classForTag: tag]
groupWithTag: componentTag]; groupWithTag: tag];
[newComponent setUid: [self globallyUniqueObjectId]]; [newComponent setUid: [self globallyUniqueObjectId]];
[*calendar addChild: newComponent]; [*calendar addChild: newComponent];
} }
@@ -453,6 +460,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
- (void) sendEMailUsingTemplateNamed: (NSString *) newPageName - (void) sendEMailUsingTemplateNamed: (NSString *) newPageName
forObject: (iCalRepeatableEntityObject *) object forObject: (iCalRepeatableEntityObject *) object
previousObject: (iCalRepeatableEntityObject *) previousObject
toAttendees: (NSArray *) attendees toAttendees: (NSArray *) attendees
{ {
NSString *pageName; NSString *pageName;
@@ -467,7 +475,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
NGMimeMessage *msg; NGMimeMessage *msg;
NGMimeBodyPart *bodyPart; NGMimeBodyPart *bodyPart;
NGMimeMultipartBody *body; NGMimeMultipartBody *body;
SOGoUser *ownerUser, *currentUser; SOGoUser *ownerUser;
if (sendEMailNotifications if (sendEMailNotifications
&& [object isStillRelevant]) && [object isStillRelevant])
@@ -511,6 +519,7 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
/* construct message content */ /* construct message content */
p = [app pageWithName: pageName inContext: context]; p = [app pageWithName: pageName inContext: context];
[p setApt: object]; [p setApt: object];
[p setPreviousApt: previousObject];
if ([[object organizer] cn] && [[[object organizer] cn] length]) if ([[object organizer] cn] && [[[object organizer] cn] length])
{ {
+1 -1
View File
@@ -84,7 +84,7 @@
- (void) renameTo: (NSString *) newName; - (void) renameTo: (NSString *) newName;
- (WOResponse *) subscribe: (BOOL) reallyDo - (WOResponse *) subscribe: (BOOL) reallyDo
inTheNameOf: (NSString *) delegatedUser inTheNamesOf: (NSArray *) delegatedUsers
fromMailInvitation: (BOOL) isMailInvitation fromMailInvitation: (BOOL) isMailInvitation
inContext: (WOContext *) localContext; inContext: (WOContext *) localContext;
+39 -26
View File
@@ -660,59 +660,72 @@ static NSArray *childRecordFields = nil;
} }
- (WOResponse *) subscribe: (BOOL) reallyDo - (WOResponse *) subscribe: (BOOL) reallyDo
inTheNameOf: (NSString *) delegatedUser inTheNamesOf: (NSArray *) delegatedUsers
fromMailInvitation: (BOOL) isMailInvitation fromMailInvitation: (BOOL) isMailInvitation
inContext: (WOContext *) localContext inContext: (WOContext *) localContext
{ {
WOResponse *response; WOResponse *response;
SOGoUser *currentUser, *subscriptionUser; SOGoUser *currentUser;
BOOL validRequest;
response = [localContext response]; response = [localContext response];
currentUser = [localContext activeUser]; currentUser = [localContext activeUser];
if ([delegatedUser length]) if (delegatedUsers && [delegatedUsers count])
{ {
validRequest = ([currentUser isSuperUser]); if (![currentUser isSuperUser])
subscriptionUser = [SOGoUser userWithLogin: delegatedUser roles: nil]; {
} [response setStatus: 403];
else [response appendContentString:
{ @"You cannot subscribe another user to any folder"
validRequest = YES; @" unless you are a super-user."];
subscriptionUser = currentUser; }
} else
{
SOGoUser *subscriptionUser;
int i;
if (validRequest) for (i = 0; i < [delegatedUsers count]; i++)
[self _subscribeUser: subscriptionUser {
reallyDo: reallyDo subscriptionUser = [SOGoUser userWithLogin: [delegatedUsers objectAtIndex: i]
fromMailInvitation: isMailInvitation roles: nil];
inResponse: response];
[self _subscribeUser: subscriptionUser
reallyDo: reallyDo
fromMailInvitation: isMailInvitation
inResponse: response];
}
}
}
else else
{ {
[response setStatus: 403]; [self _subscribeUser: currentUser
[response appendContentString: reallyDo: reallyDo
@"You cannot subscribe another user to any folder" fromMailInvitation: isMailInvitation
@" unless you are a super-user."]; inResponse: response];
} }
return response; return response;
} }
- (NSString *) _parseDAVDelegatedUser: (WOContext *) queryContext - (NSArray *) _parseDAVDelegatedUser: (WOContext *) queryContext
{ {
id <DOMDocument> document; id <DOMDocument> document;
id <DOMNamedNodeMap> attrs; id <DOMNamedNodeMap> attrs;
id o;
document = [[queryContext request] contentAsDOMDocument]; document = [[queryContext request] contentAsDOMDocument];
attrs = [[document documentElement] attributes]; 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 - (id <WOActionResults>) davSubscribe: (WOContext *) queryContext
{ {
return [self subscribe: YES return [self subscribe: YES
inTheNameOf: [self _parseDAVDelegatedUser: queryContext] inTheNamesOf: [self _parseDAVDelegatedUser: queryContext]
fromMailInvitation: NO fromMailInvitation: NO
inContext: queryContext]; inContext: queryContext];
} }
@@ -720,7 +733,7 @@ static NSArray *childRecordFields = nil;
- (id <WOActionResults>) davUnsubscribe: (WOContext *) queryContext - (id <WOActionResults>) davUnsubscribe: (WOContext *) queryContext
{ {
return [self subscribe: NO return [self subscribe: NO
inTheNameOf: [self _parseDAVDelegatedUser: queryContext] inTheNamesOf: [self _parseDAVDelegatedUser: queryContext]
fromMailInvitation: NO fromMailInvitation: NO
inContext: queryContext]; inContext: queryContext];
} }
+2 -2
View File
@@ -81,7 +81,7 @@
[self _setupContext]; [self _setupContext];
return [clientObject subscribe: YES return [clientObject subscribe: YES
inTheNameOf: nil inTheNamesOf: nil
fromMailInvitation: isMailInvitation fromMailInvitation: isMailInvitation
inContext: context]; inContext: context];
} }
@@ -91,7 +91,7 @@
[self _setupContext]; [self _setupContext];
return [clientObject subscribe: NO return [clientObject subscribe: NO
inTheNameOf: nil inTheNamesOf: nil
fromMailInvitation: isMailInvitation fromMailInvitation: isMailInvitation
inContext: context]; inContext: context];
} }