diff --git a/ChangeLog b/ChangeLog index 26387fc00..1be32028e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,23 @@ 2007-11-26 Wolfgang Sourdeau + * SoObjects/Appointments/SOGoAppointmentFolder.m + ([SOGoAppointmentFolder + -roleForComponentsWithAccessClass:accessClassforUser:uid]): cache + acl to reduce method calls. + ([SOGoAppointmentFolder + -fetchFields:_fieldsfromFolder:_folderfrom:_startDateto:_endDatetitle:titlecomponent:_component]): + if the user is not the current user, we strip the useless info + from the meta data. + + * UI/Common/WODirectAction+SOGo.m ([WODirectAction + -labelForKey:key]): new category method. + + * UI/Scheduler/UIxAppointmentEditor.m ([UIxAppointmentEditor + -event]): same as below. + + * UI/Scheduler/UIxTaskEditor.m ([UIxTaskEditor -todo]): request a + secured version of the component. + * UI/MailPartViewers/UIxMailPartViewer.m ([-fallbackStringEncoding]): removed method. ([UIxMailPartViewer -flatContentAsString]): we no longer use [self diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.h b/SoObjects/Appointments/SOGoAppointmentFolder.h index 851b4855b..c359f65e0 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.h +++ b/SoObjects/Appointments/SOGoAppointmentFolder.h @@ -38,6 +38,8 @@ #import "SOGo/SOGoGCSFolder.h" +#import + @class NSArray; @class NSCalendarDate; @class NSException; @@ -46,11 +48,12 @@ @class NSTimeZone; @class GCSFolder; -#import @interface SOGoAppointmentFolder : SOGoGCSFolder { NSTimeZone *timeZone; NSMutableDictionary *uidToFilename; + NSMutableDictionary *aclMatrix; + NSMutableArray *stripFields; } - (BOOL) isActive; diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 9d740ed7f..a356abde2 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -35,6 +35,7 @@ #import #import #import +#import #import #import #import @@ -110,6 +111,9 @@ static NSNumber *sharedYes = nil; if ((self = [super initWithName: name inContainer: newContainer])) { timeZone = [[context activeUser] timeZone]; + aclMatrix = [NSMutableDictionary new]; + stripFields = nil; + uidToFilename = nil; } return self; @@ -117,6 +121,8 @@ static NSNumber *sharedYes = nil; - (void) dealloc { + [aclMatrix release]; + [stripFields release]; [uidToFilename release]; [super dealloc]; } @@ -774,6 +780,7 @@ static NSNumber *sharedYes = nil; { NSString *accessRole, *prefix, *currentRole, *suffix; NSEnumerator *acls; + NSMutableDictionary *userRoles; accessRole = nil; @@ -784,20 +791,74 @@ static NSNumber *sharedYes = nil; else prefix = @"Confidential"; - acls = [[self aclsForUser: uid] objectEnumerator]; - currentRole = [acls nextObject]; - while (currentRole && !accessRole) - if ([currentRole hasPrefix: prefix]) - { - suffix = [currentRole substringFromIndex: [prefix length]]; - accessRole = [NSString stringWithFormat: @"Component%@", suffix]; - } - else + userRoles = [aclMatrix objectForKey: uid]; + if (!userRoles) + { + userRoles = [NSMutableDictionary dictionaryWithCapacity: 3]; + [aclMatrix setObject: userRoles forKey: uid]; + } + + accessRole = [userRoles objectForKey: prefix]; + if (!accessRole) + { + acls = [[self aclsForUser: uid] objectEnumerator]; currentRole = [acls nextObject]; + while (currentRole && !accessRole) + if ([currentRole hasPrefix: prefix]) + { + suffix = [currentRole substringFromIndex: [prefix length]]; + accessRole = [NSString stringWithFormat: @"Component%@", suffix]; + } + else + currentRole = [acls nextObject]; + if (!accessRole) + accessRole = @""; + [userRoles setObject: accessRole forKey: prefix]; + } return accessRole; } +- (void) _buildStripFieldsFromFields: (NSArray *) fields +{ + stripFields = [[NSMutableArray alloc] initWithCapacity: [fields count]]; + [stripFields setArray: fields]; + [stripFields removeObjectsInArray: [NSArray arrayWithObjects: @"c_name", + @"c_uid", @"c_startdate", + @"c_enddate", @"c_isallday", + @"c_iscycle", + @"c_classification", + @"c_component", nil]]; +} + +- (void) _fixupProtectedInformation: (NSEnumerator *) ma + inFields: (NSArray *) fields + forUser: (NSString *) uid +{ + NSMutableDictionary *currentRecord; + NSString *roles[] = {nil, nil, nil}; + iCalAccessClass accessClass; + NSString *role; + + if (!stripFields) + [self _buildStripFieldsFromFields: fields]; + + while ((currentRecord = [ma nextObject])) + { + accessClass + = [[currentRecord objectForKey: @"c_classification"] intValue]; + role = roles[accessClass]; + if (!role) + { + role = [[self roleForComponentsWithAccessClass: accessClass + forUser: uid] substringFromIndex: 9]; + roles[accessClass] = role; + } + if ([role isEqualToString: @"DAndTViewer"]) + [currentRecord removeObjectsForKeys: stripFields]; + } +} + - (NSArray *) fetchFields: (NSArray *) _fields fromFolder: (GCSFolder *) _folder from: (NSCalendarDate *) _startDate @@ -809,7 +870,7 @@ static NSNumber *sharedYes = nil; NSMutableArray *fields, *ma = nil; NSArray *records; NSString *sql, *dateSqlString, *titleSqlString, *componentSqlString, - *privacySqlString; + *privacySqlString, *currentLogin; NGCalendarDateRange *r; if (_folder == nil) { @@ -896,6 +957,11 @@ static NSNumber *sharedYes = nil; if (logger) [self debugWithFormat:@"returning %i records", [ma count]]; + currentLogin = [[context activeUser] login]; + if (![currentLogin isEqualToString: owner]) + [self _fixupProtectedInformation: [ma objectEnumerator] + inFields: _fields + forUser: currentLogin]; // [ma makeObjectsPerform: @selector (setObject:forKey:) // withObject: owner // withObject: @"owner"]; diff --git a/UI/Common/WODirectAction+SOGo.h b/UI/Common/WODirectAction+SOGo.h index 067046b69..aa518c6d6 100644 --- a/UI/Common/WODirectAction+SOGo.h +++ b/UI/Common/WODirectAction+SOGo.h @@ -34,6 +34,8 @@ - (WOResponse *) responseWith204; - (WOResponse *) redirectToLocation: (NSString *) newLocation; +- (NSString *) labelForKey: (NSString *) _str; + @end #endif /* WODIRECTACTION_SOGO_H */ diff --git a/UI/Common/WODirectAction+SOGo.m b/UI/Common/WODirectAction+SOGo.m index 13c8b86d8..6c1c3adfa 100644 --- a/UI/Common/WODirectAction+SOGo.m +++ b/UI/Common/WODirectAction+SOGo.m @@ -20,10 +20,14 @@ * Boston, MA 02111-1307, USA. */ +#import -#import +#import #import +#import +#import + #import "WODirectAction+SOGo.h" @implementation WODirectAction (SOGoExtension) @@ -53,5 +57,33 @@ return response; } +- (NSString *) labelForKey: (NSString *) key +{ + NSString *userLanguage, *label; + NSArray *paths; + NSBundle *bundle; + NSDictionary *strings; + bundle = [NSBundle bundleForClass: [self class]]; + if (!bundle) + bundle = [NSBundle mainBundle]; + + userLanguage = [[context activeUser] language]; + paths = [bundle pathsForResourcesOfType: @"strings" + inDirectory: [NSString stringWithFormat: @"%@.lproj", + userLanguage] + forLocalization: userLanguage]; + if ([paths count] > 0) + { + strings = [NSDictionary + dictionaryFromStringsFile: [paths objectAtIndex: 0]]; + label = [strings objectForKey: key]; + if (!label) + label = key; + } + else + label = key; + + return label; +} @end diff --git a/UI/SOGoUI/UIxComponent.m b/UI/SOGoUI/UIxComponent.m index a376ba607..50e6bf253 100644 --- a/UI/SOGoUI/UIxComponent.m +++ b/UI/SOGoUI/UIxComponent.m @@ -489,12 +489,6 @@ static BOOL uixDebugEnabled = NO; if ([lTable hasPrefix:@"$"]) lTable = [self valueForKeyPath:[lTable substringFromIndex:1]]; -#if 0 - if ([lVal hasPrefix:@"$"]) - lVal = [self valueForKeyPath:[lVal substringFromIndex:1]]; - -#endif - /* lookup string */ return [rm stringForKey: lKey inTableNamed: lTable diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index dbc48efc5..aa8e4c08a 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -413,5 +413,13 @@ validate_endbeforestart = "Enddate is before startdate!"; "Location" = "Location"; "(Private Event)" = "(Private Event)"; +vevent_class0 = "(Public event)"; +vevent_class1 = "(Private event)"; +vevent_class2 = "(Confidential event)"; + +vtodo_class0 = "(Public task)"; +vtodo_class1 = "(Private task)"; +vtodo_class2 = "(Confidential task)"; + "closeThisWindowMessage" = "Thank you! You may now close this window or view your "; "Multicolumn Day View" = "Multicolumn Day View"; diff --git a/UI/Scheduler/French.lproj/Localizable.strings b/UI/Scheduler/French.lproj/Localizable.strings index f04263bb2..d0f002d0f 100644 --- a/UI/Scheduler/French.lproj/Localizable.strings +++ b/UI/Scheduler/French.lproj/Localizable.strings @@ -412,5 +412,13 @@ validate_endbeforestart = "La date de fin est avant la date de début !"; "Location" = "Lieu"; "(Private Event)" = "(Événement privé)"; +vevent_class0 = "(Événement public)"; +vevent_class1 = "(Événement privé)"; +vevent_class2 = "(Événement confidentiel)"; + +vtodo_class0 = "(Tâche publique)"; +vtodo_class1 = "(Tâche privée)"; +vtodo_class2 = "(Tâche confidentielle)"; + "closeThisWindowMessage" = "Merci! Vous pouvez maintenant fermer cette fenêtre ou consulter votre "; "Multicolumn Day View" = "Multicolonne"; diff --git a/UI/Scheduler/German.lproj/Localizable.strings b/UI/Scheduler/German.lproj/Localizable.strings index da5f595b2..1f65637c7 100644 --- a/UI/Scheduler/German.lproj/Localizable.strings +++ b/UI/Scheduler/German.lproj/Localizable.strings @@ -400,5 +400,14 @@ validate_endbeforestart = "Ihr Beginn ist nach dem Ende"; "Location" = "Ort"; "(Private Event)" = "(Privater Termin)"; +/* event list */ +vevent_class0 = "(Public event)"; +vevent_class1 = "(Private event)"; +vevent_class2 = "(Confidential event)"; + +vtodo_class0 = "(Public task)"; +vtodo_class1 = "(Private task)"; +vtodo_class2 = "(Confidential task)"; + "closeThisWindowMessage" = "Vielen Dank! Sie können dieses Fenster jetzt schließen."; "Multicolumn Day View" = "Multicolonne"; diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index 23d899902..a5147130f 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -71,7 +71,7 @@ { if (!event) { - event = (iCalEvent *) [[self clientObject] component: NO secure: NO]; + event = (iCalEvent *) [[self clientObject] component: NO secure: YES]; [event retain]; } @@ -270,7 +270,7 @@ unsigned int minutes; iCalRecurrenceRule *rule; - event = (iCalEvent *) [[self clientObject] component: NO secure: YES]; + [self event]; if (event) { startDate = [event startDate]; @@ -382,7 +382,7 @@ iCalRecurrenceRule *rule; clientObject = [self clientObject]; - event = (iCalEvent *) [clientObject component: YES secure: NO]; + [self event]; [super takeValuesFromRequest: _rq inContext: _ctx]; diff --git a/UI/Scheduler/UIxCalListingActions.h b/UI/Scheduler/UIxCalListingActions.h index cb81e40f7..99f4ee0e6 100644 --- a/UI/Scheduler/UIxCalListingActions.h +++ b/UI/Scheduler/UIxCalListingActions.h @@ -23,8 +23,7 @@ #ifndef UIXCALLISTINGACTIONVIEW_H #define UIXCALLISTINGACTIONVIEW_H - -#import +#import @class NSCalendarDate; @class NSMutableDictionary; diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m index 3346c739e..f5a25d5a9 100644 --- a/UI/Scheduler/UIxCalListingActions.m +++ b/UI/Scheduler/UIxCalListingActions.m @@ -185,22 +185,6 @@ } } -- (void) _updatePrivacyInComponent: (NSMutableDictionary *) component - fromFolder: (SOGoAppointmentFolder *) folder -{ - int privacyFlag; - NSString *roleString; - - privacyFlag = [[component objectForKey: @"classification"] intValue]; - roleString = [folder roleForComponentsWithAccessClass: privacyFlag - forUser: userLogin]; - if ([roleString isEqualToString: @"ComponentDAndTViewer"]) - { - [component setObject: @"" forKey: @"c_title"]; - [component setObject: @"" forKey: @"c_location"]; - } -} - - (SOGoAppointmentFolder *) _aptFolder: (NSString *) folder withClientObject: (SOGoAppointmentFolder *) clientObject { @@ -220,6 +204,17 @@ return aptFolder; } +- (void) _fixComponentTitle: (NSMutableDictionary *) component + withType: (NSString *) type +{ + NSString *labelKey; + + labelKey = [NSString stringWithFormat: @"%@_class%@", + type, [component objectForKey: @"c_classification"]]; + [component setObject: [self labelForKey: labelKey] + forKey: @"c_title"]; +} + - (NSArray *) _fetchFields: (NSArray *) fields forComponentOfType: (NSString *) component { @@ -232,28 +227,29 @@ marker = [NSNull null]; - clientObject = [self clientObject]; + clientObject = [self clientObject]; folders = [[clientObject subFolders] objectEnumerator]; currentFolder = [folders nextObject]; infos = [NSMutableArray array]; + while (currentFolder) { if ([currentFolder isActive]) { - currentInfos = [[currentFolder fetchCoreInfosFrom: startDate - to: endDate - title: title - component: component] objectEnumerator]; + currentInfos + = [[currentFolder fetchCoreInfosFrom: startDate + to: endDate + title: title + component: component] objectEnumerator]; while ((newInfo = [currentInfos nextObject])) { - [self _updatePrivacyInComponent: newInfo - fromFolder: currentFolder]; [newInfo setObject: [currentFolder nameInContainer] forKey: @"c_folder"]; - + if (![[newInfo objectForKey: @"c_title"] length]) + [self _fixComponentTitle: newInfo withType: component]; [infos addObject: [newInfo objectsForKeys: fields notFoundMarker: marker]]; } @@ -323,7 +319,7 @@ newEvents = [NSMutableArray array]; fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status", @"c_title", @"c_startdate", @"c_enddate", @"c_location", - @"c_isallday", nil]; + @"c_isallday", @"c_classification", nil]; events = [[self _fetchFields: fields forComponentOfType: @"vevent"] objectEnumerator]; oldEvent = [events nextObject]; @@ -399,7 +395,7 @@ [self _setupContext]; fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status", - @"c_title", @"c_enddate", nil]; + @"c_title", @"c_enddate", @"c_classification", nil]; tasks = [[self _fetchFields: fields forComponentOfType: @"vtodo"] objectEnumerator]; diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index 8ea3b9edf..759726dd1 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -73,7 +73,7 @@ { if (!todo) { - todo = (iCalToDo *) [[self clientObject] component: NO secure: NO]; + todo = (iCalToDo *) [[self clientObject] component: NO secure: YES]; [todo retain]; } @@ -289,7 +289,7 @@ NSString *duration; unsigned int minutes; - todo = (iCalToDo *) [[self clientObject] component: NO secure: YES]; + [self todo]; if (todo) { startDate = [todo startDate]; @@ -383,10 +383,7 @@ - (void) takeValuesFromRequest: (WORequest *) _rq inContext: (WOContext *) _ctx { - SOGoTaskObject *clientObject; - - clientObject = [self clientObject]; - todo = (iCalToDo *) [clientObject component: YES secure: NO]; + [self todo]; [super takeValuesFromRequest: _rq inContext: _ctx]; @@ -438,12 +435,9 @@ - (id) changeStatusAction { - SOGoTaskObject *clientObject; NSString *newStatus; - clientObject = [self clientObject]; - todo = (iCalToDo *) [clientObject component: NO secure: NO]; - [todo retain]; + [self todo]; if (todo) { newStatus = [self queryParameterForKey: @"status"]; @@ -455,7 +449,7 @@ [todo setPercentComplete: @"0"]; [todo setStatus: @"IN-PROCESS"]; } - [clientObject saveComponent: todo]; + [[self clientObject] saveComponent: todo]; } return [self responseWith204]; diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 8fa264d22..32ea684af 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -356,12 +356,12 @@ function eventsListCallback(http) { td = document.createElement("td"); row.appendChild(td); Event.observe(td, "mousedown", listRowMouseDownHandler, true); - td.appendChild(document.createTextNode(data[i][8])); + td.appendChild(document.createTextNode(data[i][9])); td = document.createElement("td"); row.appendChild(td); Event.observe(td, "mousedown", listRowMouseDownHandler, true); - td.appendChild(document.createTextNode(data[i][9])); + td.appendChild(document.createTextNode(data[i][10])); td = document.createElement("td"); row.appendChild(td);