diff --git a/Main/SOGo.m b/Main/SOGo.m index c4adbc410..37de19459 100644 --- a/Main/SOGo.m +++ b/Main/SOGo.m @@ -26,15 +26,16 @@ NSMutableDictionary *localeLUT; } -- (NSDictionary *)currentLocaleConsideringLanguages:(NSArray *)_langs; -- (NSDictionary *)localeForLanguageNamed:(NSString *)_name; +- (NSDictionary *) currentLocaleConsideringLanguages:(NSArray *)_langs; +- (NSDictionary *) localeForLanguageNamed:(NSString *)_name; @end #include "SOGoProductLoader.h" -#include #include +#include #include +#include #include "common.h" @implementation SOGo @@ -44,6 +45,8 @@ static BOOL doCrashOnSessionCreate = NO; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + SoClassSecurityInfo *sInfo; + NSArray *basicRoles; id tmp; doCrashOnSessionCreate = [ud boolForKey:@"SOGoCrashOnSessionCreate"]; @@ -64,18 +67,19 @@ static BOOL doCrashOnSessionCreate = NO; #endif /* SoClass security declarations */ - + sInfo = [self soClassSecurityInfo]; /* require View permission to access the root (bound to authenticated ...) */ - [[self soClassSecurityInfo] declareObjectProtected:SoPerm_View]; - + [sInfo declareObjectProtected: SoPerm_View]; + /* to allow public access to all contained objects (subkeys) */ - [[self soClassSecurityInfo] setDefaultAccess:@"allow"]; - + [sInfo setDefaultAccess: @"allow"]; + + basicRoles = [NSArray arrayWithObjects: SoRole_Authenticated, + SOGoRole_FreeBusy, nil]; + /* require Authenticated role for View and WebDAV */ - [[self soClassSecurityInfo] declareRole: SoRole_Authenticated - asDefaultForPermission: SoPerm_View]; - [[self soClassSecurityInfo] declareRole: SoRole_Authenticated - asDefaultForPermission: SoPerm_WebDAVAccess]; + [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_View]; + [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_WebDAVAccess]; } - (id)init { @@ -108,7 +112,7 @@ static BOOL doCrashOnSessionCreate = NO; /* authenticator */ - (id)authenticatorInContext:(id)_ctx { - return [SOGoAuthenticator sharedSOGoAuthenticator]; + return [$(@"SOGoAuthenticator") sharedSOGoAuthenticator]; } /* name lookup */ diff --git a/SoObjects/Appointments/GNUmakefile b/SoObjects/Appointments/GNUmakefile index c69e92686..57b4cb0f3 100644 --- a/SoObjects/Appointments/GNUmakefile +++ b/SoObjects/Appointments/GNUmakefile @@ -13,6 +13,7 @@ Appointments_OBJC_FILES = \ NSArray+Appointments.m \ iCalEntityObject+Agenor.m \ \ + SOGoCalendarComponent.m \ SOGoAppointmentObject.m \ SOGoTaskObject.m \ SOGoAppointmentFolder.m \ diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.h b/SoObjects/Appointments/SOGoAppointmentFolder.h index 56243dfb1..bfa7b51f2 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.h +++ b/SoObjects/Appointments/SOGoAppointmentFolder.h @@ -72,7 +72,7 @@ to: (NSCalendarDate *) _endDate component: (id) _component; -- (NSArray *) fetchFreebusyInfosFrom: (NSCalendarDate *) _startDate +- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate to: (NSCalendarDate *) _endDate; - (void) deleteEntriesWithIds: (NSArray *) ids; diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index bc7b78907..e15d78cf1 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -25,11 +25,13 @@ #import #import +#import #import #import +#import +#import #import "common.h" -#import #import "SOGoAppointmentObject.h" #import "SOGoTaskObject.h" @@ -42,35 +44,6 @@ @end #endif -@interface NSString (SOGoExtensions) - -- calDavMethodToObjC; - -@end - -@implementation NSString (SOGoExtensions) - -- calDavMethodToObjC -{ - NSMutableString *newName; - NSEnumerator *components; - NSString *component; - - newName = [NSMutableString new]; - [newName autorelease]; - components = [[self componentsSeparatedByString: @"-"] objectEnumerator]; - component = [components nextObject]; - while (component) - { - [newName appendString: [component capitalizedString]]; - component = [components nextObject]; - } - - return newName; -} - -@end - @implementation SOGoAppointmentFolder static NGLogger *logger = nil; @@ -85,6 +58,7 @@ static NSNumber *sharedYes = nil; { NGLoggerManager *lm; static BOOL didInit = NO; + SoClassSecurityInfo *securityInfo; if (didInit) return; didInit = YES; @@ -96,6 +70,16 @@ static NSNumber *sharedYes = nil; lm = [NGLoggerManager defaultLoggerManager]; logger = [lm loggerForDefaultKey:@"SOGoAppointmentFolderDebugEnabled"]; + securityInfo = [self soClassSecurityInfo]; + [securityInfo declareRole: SOGoRole_Delegate + asDefaultForPermission: SoPerm_AddDocumentsImagesAndFiles]; + [securityInfo declareRole: SOGoRole_Delegate + asDefaultForPermission: SoPerm_ChangeImagesAndFiles]; + [securityInfo declareRoles: [NSArray arrayWithObjects: + SOGoRole_Delegate, + SOGoRole_Assistant, nil] + asDefaultForPermission: SoPerm_View]; + sharedYes = [[NSNumber numberWithBool:YES] retain]; } @@ -135,8 +119,7 @@ static NSNumber *sharedYes = nil; SoSelectorInvocation *invocation; NSString *name; - name = [NSString stringWithFormat: @"do%@:", - [_key calDavMethodToObjC]]; + name = [NSString stringWithFormat: @"%@:", [_key davMethodToObjC]]; invocation = [[SoSelectorInvocation alloc] initWithSelectorNamed: name @@ -198,7 +181,7 @@ static NSNumber *sharedYes = nil; - (NSDictionary *) _parseCalendarFilter: (id ) filterElement { NSMutableDictionary *filterData; - id parentNode; + id parentNode; id ranges; NSString *componentName; @@ -274,7 +257,7 @@ static NSNumber *sharedYes = nil; } } -- (id) doCalendarQuery: (id) context +- (id) davCalendarQuery: (id) context { WOResponse *r; NSArray *filters; @@ -415,6 +398,11 @@ static NSNumber *sharedYes = nil; return classes; } +- (NSString *) groupDavResourceType +{ + return @"vevent-collection"; +} + /* vevent UID handling */ - (NSString *) resourceNameForEventUID: (NSString *)_u @@ -799,7 +787,7 @@ static NSNumber *sharedYes = nil; } -- (NSArray *) fetchFreebusyInfosFrom: (NSCalendarDate *) _startDate +- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate to: (NSCalendarDate *) _endDate { static NSArray *infos = nil; // TODO: move to a plist file diff --git a/SoObjects/Appointments/SOGoAppointmentObject.h b/SoObjects/Appointments/SOGoAppointmentObject.h index 3be5fafa1..ccca7fb7f 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.h +++ b/SoObjects/Appointments/SOGoAppointmentObject.h @@ -42,12 +42,14 @@ @class iCalEvent; @class iCalCalendar; -@interface SOGoAppointmentObject : SOGoContentObject +#import "SOGoCalendarComponent.h" + +@interface SOGoAppointmentObject : SOGoCalendarComponent /* accessors */ -- (NSString *)iCalString; -- (iCalEvent *)event; +- (iCalEvent *) event; +- (iCalEvent *) firstEventFromCalendar: (iCalCalendar *) calendar; /* folder management */ @@ -70,7 +72,6 @@ - (NSException *)changeParticipationStatus:(NSString *)_status inContext:(id)_ctx; -- (iCalEvent *) firstEventFromCalendar: (iCalCalendar *) calendar; @end diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index d3f5d3b5f..6f34456ca 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -21,16 +21,17 @@ #import "SOGoAppointmentObject.h" -#import -#import -#import -#import #import #import +#import +#import #import #import #import +#import +#import + #import "SOGoAptMailNotification.h" #import "iCalEntityObject+Agenor.h" @@ -59,35 +60,15 @@ @implementation SOGoAppointmentObject -static id parser = nil; -static SaxObjectDecoder *sax = nil; -static NGLogger *logger = nil; static NSString *mailTemplateDefaultLanguage = nil; + (void)initialize { NSUserDefaults *ud; - NGLoggerManager *lm; - SaxXMLReaderFactory *factory; static BOOL didInit = NO; if (didInit) return; didInit = YES; - lm = [NGLoggerManager defaultLoggerManager]; - logger = [lm loggerForClass:self]; - - factory = [SaxXMLReaderFactory standardXMLReaderFactory]; - parser = [[factory createXMLReaderForMimeType:@"text/calendar"] - retain]; - if (parser == nil) - [logger fatalWithFormat:@"did not find a parser for text/calendar!"]; - sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGCards"]; - if (sax == nil) - [logger fatalWithFormat:@"could not create the iCal SAX handler!"]; - - [parser setContentHandler:sax]; - [parser setErrorHandler:sax]; - ud = [NSUserDefaults standardUserDefaults]; mailTemplateDefaultLanguage = [[ud stringForKey:@"SOGoDefaultLanguage"] retain]; @@ -97,31 +78,9 @@ static NSString *mailTemplateDefaultLanguage = nil; /* accessors */ -- (NSString *) iCalString -{ - // for UI-X appointment viewer - return [self contentAsString]; -} - - (iCalEvent *) event { - iCalEvent *event; - iCalCalendar *calendar; - NSString *iCalString; - - iCalString = [self iCalString]; - if (iCalString) - { - calendar = [iCalCalendar parseSingleFromSource: iCalString]; - if (calendar) - event = [self firstEventFromCalendar: calendar]; - else - event = nil; - } - else - event = nil; - - return event; + return [self firstEventFromCalendar: [self calendar]]; } /* iCal handling */ @@ -273,12 +232,12 @@ static NSString *mailTemplateDefaultLanguage = nil; return allErrors; } -- (iCalEvent *) firstEventFromCalendar: (iCalCalendar *) calendar +- (iCalEvent *) firstEventFromCalendar: (iCalCalendar *) aCalendar { iCalEvent *event; NSArray *events; - events = [calendar childrenWithTag: @"vevent"]; + events = [aCalendar childrenWithTag: @"vevent"]; if ([events count]) event = (iCalEvent *) [[events objectAtIndex: 0] groupWithClass: [iCalEvent class]]; @@ -310,7 +269,7 @@ static NSString *mailTemplateDefaultLanguage = nil; - send iMIP mail for all folders not found */ AgenorUserManager *um; - iCalCalendar *calendar; + iCalCalendar *newCalendar; iCalEvent *oldApt, *newApt; iCalEventChanges *changes; iCalPerson *organizer; @@ -339,10 +298,7 @@ static NSString *mailTemplateDefaultLanguage = nil; oldApt = nil; } else - { - calendar = [iCalCalendar parseSingleFromSource: oldContent]; - oldApt = [self firstEventFromCalendar: calendar]; - } + oldApt = [self firstEventFromCalendar: [self calendar]]; /* compare sequence if requested */ @@ -353,8 +309,8 @@ static NSString *mailTemplateDefaultLanguage = nil; /* handle new content */ - calendar = [iCalCalendar parseSingleFromSource: _iCal]; - newApt = [self firstEventFromCalendar: calendar]; + newCalendar = [iCalCalendar parseSingleFromSource: _iCal]; + newApt = [self firstEventFromCalendar: newCalendar]; if (newApt == nil) { return [NSException exceptionWithHTTPStatus:400 /* Bad Request */ reason:@"could not parse iCalendar content!"]; @@ -462,7 +418,7 @@ static NSString *mailTemplateDefaultLanguage = nil; canceledApt = [newApt copy]; [(iCalCalendar *) [canceledApt parent] setMethod: @"cancel"]; [self sendAttendeeRemovalEMailForAppointment:canceledApt - toAttendees:attendees]; + toAttendees: attendees]; [canceledApt release]; } return nil; @@ -483,18 +439,13 @@ static NSString *mailTemplateDefaultLanguage = nil; - delete in removed folders - send iMIP mail for all folders not found */ - iCalCalendar *calendar; iCalEvent *apt; NSArray *removedUIDs; NSMutableArray *attendees; /* load existing content */ - - calendar = [iCalCalendar parseSingleFromSource: [self iCalString]]; - if (calendar) - apt = [self firstEventFromCalendar: calendar]; - else - NSLog (@"this is not good at all, totally fucked we are going tyo crash..."); + + apt = [self event]; /* compare sequence if requested */ @@ -528,15 +479,9 @@ static NSString *mailTemplateDefaultLanguage = nil; return [self saveContentString:_iCalString baseSequence:0]; } -- (NSException *)delete { - return [self deleteWithBaseSequence:0]; -} - - - (NSException *)changeParticipationStatus:(NSString *)_status inContext:(id)_ctx { - iCalCalendar *calendar; iCalEvent *apt; iCalPerson *p; NSString *newContent; @@ -544,14 +489,7 @@ static NSString *mailTemplateDefaultLanguage = nil; NSString *myEMail; // TODO: do we need to use SOGoAppointment? (prefer iCalEvent?) - calendar = [iCalCalendar parseSingleFromSource: [self iCalString]]; - if (calendar) - apt = [self firstEventFromCalendar: calendar]; - else - { - apt = nil; - NSLog (@"this is not good at all, totally fucked we are going tyo crash..."); - } + apt = [self event]; if (apt == nil) { return [NSException exceptionWithHTTPStatus:500 /* Server Error */ @@ -643,7 +581,7 @@ static NSString *mailTemplateDefaultLanguage = nil; newContentString = contentString; else { - [event setOrganizerWithUid: [self ownerInContext: nil]]; + [event setOrganizerWithUid: [[self container] ownerInContext: nil]]; newContentString = [eventCalendar versitString]; } } @@ -652,10 +590,10 @@ static NSString *mailTemplateDefaultLanguage = nil; baseVersion: baseVersion]; } -- (void)sendEMailUsingTemplateNamed:(NSString *)_pageName - forOldAppointment:(iCalEvent *)_oldApt - andNewAppointment:(iCalEvent *)_newApt - toAttendees:(NSArray *)_attendees +- (void)sendEMailUsingTemplateNamed: (NSString *)_pageName + forOldAppointment: (iCalEvent *)_oldApt + andNewAppointment: (iCalEvent *)_newApt + toAttendees: (NSArray *)_attendees { NSString *pageName; iCalPerson *organizer; @@ -828,4 +766,28 @@ static NSString *mailTemplateDefaultLanguage = nil; return @"text/calendar"; } +- (NSString *) roleOfUser: (NSString *) login + inContext: (WOContext *) context +{ + AgenorUserManager *um; + iCalEvent *event; + NSString *role, *email; + + um = [AgenorUserManager sharedUserManager]; + email = [um getEmailForUID: login]; + + event = [self event]; + if ([event isOrganizer: email]) + role = @"Organizer"; + else if ([event isParticipant: email]) + role = @"Participant"; + else + role = nil; + + return role; +} + @end /* SOGoAppointmentObject */ + + + diff --git a/SoObjects/Appointments/SOGoFreeBusyObject.h b/SoObjects/Appointments/SOGoFreeBusyObject.h index 50e99d753..9d3ea6f5a 100644 --- a/SoObjects/Appointments/SOGoFreeBusyObject.h +++ b/SoObjects/Appointments/SOGoFreeBusyObject.h @@ -45,7 +45,7 @@ - (NSString *)contentAsStringFrom:(NSCalendarDate *)_startDate to:(NSCalendarDate *)_endDate; -- (NSArray *)fetchFreebusyInfosFrom:(NSCalendarDate *)_startDate +- (NSArray *)fetchFreeBusyInfosFrom:(NSCalendarDate *)_startDate to:(NSCalendarDate *)_endDate; @end diff --git a/SoObjects/Appointments/SOGoFreeBusyObject.m b/SoObjects/Appointments/SOGoFreeBusyObject.m index 42df5e53d..1704686ab 100644 --- a/SoObjects/Appointments/SOGoFreeBusyObject.m +++ b/SoObjects/Appointments/SOGoFreeBusyObject.m @@ -20,14 +20,15 @@ */ // $Id: SOGoFreeBusyObject.m 675 2005-07-06 20:56:09Z znek $ -#include "SOGoFreeBusyObject.h" -#include "common.h" -#include -#include +#import +#import -@interface NSDate (UsedPrivates) -- (NSString *) icalString; // declared in NGCards -@end +#import "common.h" + +#import +#import + +#import "SOGoFreeBusyObject.h" @interface SOGoFreeBusyObject (PrivateAPI) - (NSString *) iCalStringForFreeBusyInfos: (NSArray *) _infos @@ -58,19 +59,34 @@ { NSArray *infos; - infos = [self fetchFreebusyInfosFrom:_startDate to:_endDate]; + infos = [self fetchFreeBusyInfosFrom:_startDate to:_endDate]; return [self iCalStringForFreeBusyInfos:infos from:_startDate to:_endDate]; } -- (NSArray *) fetchFreebusyInfosFrom: (NSCalendarDate *) _startDate +- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate to: (NSCalendarDate *) _endDate { id calFolder; + SoSecurityManager *sm; + WOApplication *woApp; + NSArray *infos; + + woApp = [WOApplication application]; calFolder = [container lookupName: @"Calendar" inContext: nil acquire: NO]; + sm = [SoSecurityManager sharedSecurityManager]; + if (![sm validatePermission: SOGoPerm_FreeBusyLookup + onObject: calFolder + inContext: [woApp context]]) + infos = [calFolder fetchFreeBusyInfosFrom: _startDate + to: _endDate]; + else + { + infos = [NSArray new]; + [infos autorelease]; + } - return [calFolder fetchFreebusyInfosFrom: _startDate - to: _endDate]; + return infos; } /* Private API */ diff --git a/SoObjects/Appointments/SOGoGroupAppointmentFolder.m b/SoObjects/Appointments/SOGoGroupAppointmentFolder.m index 50a8cddb1..77c620851 100644 --- a/SoObjects/Appointments/SOGoGroupAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoGroupAppointmentFolder.m @@ -128,6 +128,11 @@ NSMutableArray *result; NSMutableDictionary *uidToRecord; unsigned i, count; + WOContext *context; + SoSecurityManager *securityManager; + + context = [[WOApplication application] context]; + securityManager = [SoSecurityManager sharedSecurityManager]; if ((folders = [[self container] valueForKey:@"memberFolders"]) == nil) { [self errorWithFormat:@"calendar container has no 'memberFolders'?!"]; @@ -158,7 +163,15 @@ [folders objectAtIndex:i]]; continue; } - + + if ([securityManager validatePermission: SoPerm_AccessContentsInformation + onObject: aptFolder + inContext: context]) { + [self debugWithFormat:@"no permission to read the content of calendar: %@", + [folders objectAtIndex:i]]; + continue; + } + results = [aptFolder fetchFields: _fields from: _startDate to: _endDate diff --git a/SoObjects/Appointments/SOGoTaskObject.h b/SoObjects/Appointments/SOGoTaskObject.h index 476fda6cb..20ad9f726 100644 --- a/SoObjects/Appointments/SOGoTaskObject.h +++ b/SoObjects/Appointments/SOGoTaskObject.h @@ -22,7 +22,7 @@ #ifndef __Appointments_SOGoTaskObject_H__ #define __Appointments_SOGoTaskObject_H__ -#import +#import "SOGoCalendarComponent.h" /* SOGoTaskObject @@ -42,12 +42,12 @@ @class iCalToDo; @class iCalCalendar; -@interface SOGoTaskObject : SOGoContentObject +@interface SOGoTaskObject : SOGoCalendarComponent /* accessors */ -- (NSString *) iCalString; - (iCalToDo *) task; +- (iCalToDo *) firstTaskFromCalendar: (iCalCalendar *) calendar; /* folder management */ @@ -70,7 +70,6 @@ - (NSException *)changeParticipationStatus:(NSString *)_status inContext:(id)_ctx; -- (iCalToDo *) firstTaskFromCalendar: (iCalCalendar *) calendar; @end diff --git a/SoObjects/Appointments/SOGoTaskObject.m b/SoObjects/Appointments/SOGoTaskObject.m index bdee3d22a..02eb7cd3d 100644 --- a/SoObjects/Appointments/SOGoTaskObject.m +++ b/SoObjects/Appointments/SOGoTaskObject.m @@ -19,18 +19,18 @@ 02111-1307, USA. */ -#include "SOGoTaskObject.h" +#import "SOGoTaskObject.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "SOGoAptMailNotification.h" -#include "common.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import "SOGoAptMailNotification.h" +#import "common.h" #import "NSArray+Appointments.h" @@ -55,35 +55,15 @@ @implementation SOGoTaskObject -static id parser = nil; -static SaxObjectDecoder *sax = nil; -static NGLogger *logger = nil; static NSString *mailTemplateDefaultLanguage = nil; + (void)initialize { NSUserDefaults *ud; - NGLoggerManager *lm; - SaxXMLReaderFactory *factory; static BOOL didInit = NO; if (didInit) return; didInit = YES; - lm = [NGLoggerManager defaultLoggerManager]; - logger = [lm loggerForClass:self]; - - factory = [SaxXMLReaderFactory standardXMLReaderFactory]; - parser = [[factory createXMLReaderForMimeType:@"text/calendar"] - retain]; - if (parser == nil) - [logger fatalWithFormat:@"did not find a parser for text/calendar!"]; - sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGCards"]; - if (sax == nil) - [logger fatalWithFormat:@"could not create the iCal SAX handler!"]; - - [parser setContentHandler:sax]; - [parser setErrorHandler:sax]; - ud = [NSUserDefaults standardUserDefaults]; mailTemplateDefaultLanguage = [[ud stringForKey:@"SOGoDefaultLanguage"] retain]; @@ -93,32 +73,9 @@ static NSString *mailTemplateDefaultLanguage = nil; /* accessors */ -- (NSString *) iCalString -{ - // for UI-X task viewer - return [self contentAsString]; -} - - (iCalToDo *) task { - iCalToDo *task; - iCalCalendar *calendar; - - NSString *iCalString; - - iCalString = [self iCalString]; - if (iCalString) - { - calendar = [iCalCalendar parseSingleFromSource: iCalString]; - if (calendar) - task = [self firstTaskFromCalendar: calendar]; - else - task = nil; - } - else - task = nil; - - return task; + return [self firstTaskFromCalendar: [self calendar]]; } /* iCal handling */ @@ -271,19 +228,19 @@ static NSString *mailTemplateDefaultLanguage = nil; return allErrors; } -- (iCalToDo *) firstTaskFromCalendar: (iCalCalendar *) calendar +- (iCalToDo *) firstTaskFromCalendar: (iCalCalendar *) aCalendar { - iCalToDo *event; - NSArray *events; + iCalToDo *task; + NSArray *tasks; - events = [calendar childrenWithTag: @"vtodo"]; - if ([events count]) - event = (iCalToDo *) [[events objectAtIndex: 0] + tasks = [aCalendar childrenWithTag: @"vtodo"]; + if ([tasks count]) + task = (iCalToDo *) [[tasks objectAtIndex: 0] groupWithClass: [iCalToDo class]]; else - event = nil; + task = nil; - return event; + return task; } /* "iCal multifolder saves" */ @@ -483,18 +440,13 @@ static NSString *mailTemplateDefaultLanguage = nil; - delete in removed folders - send iMIP mail for all folders not found */ - iCalCalendar *calendar; - iCalToDo *apt; + iCalToDo *task; NSArray *removedUIDs; NSMutableArray *attendees; /* load existing content */ - calendar = [iCalCalendar parseSingleFromSource: [self iCalString]]; - if (calendar) - apt = [self firstTaskFromCalendar: calendar]; - else - NSLog (@"this is not good at all, totally fucked we are going tyo crash..."); + task = [self task]; /* compare sequence if requested */ @@ -502,21 +454,21 @@ static NSString *mailTemplateDefaultLanguage = nil; // TODO } - removedUIDs = [self attendeeUIDsFromTask:apt]; + removedUIDs = [self attendeeUIDsFromTask:task]; /* send notification email to attendees excluding organizer */ - attendees = [NSMutableArray arrayWithArray:[apt attendees]]; - [attendees removePerson:[apt organizer]]; + attendees = [NSMutableArray arrayWithArray:[task attendees]]; + [attendees removePerson:[task organizer]]; /* flag task as being canceled */ - [(iCalCalendar *) [apt parent] setMethod: @"cancel"]; - [apt increaseSequence]; + [(iCalCalendar *) [task parent] setMethod: @"cancel"]; + [task increaseSequence]; /* remove all attendees to signal complete removal */ - [apt removeAllAttendees]; + [task removeAllAttendees]; /* send notification email */ - [self sendTaskDeletionEMailForTask:apt + [self sendTaskDeletionEMailForTask:task toAttendees:attendees]; /* perform */ @@ -527,49 +479,37 @@ static NSString *mailTemplateDefaultLanguage = nil; - (NSException *)saveContentString:(NSString *)_iCalString { return [self saveContentString:_iCalString baseSequence:0]; } -- (NSException *)delete { - return [self deleteWithBaseSequence:0]; -} - - (NSException *)changeParticipationStatus:(NSString *)_status inContext:(id)_ctx { - iCalCalendar *calendar; - iCalToDo *apt; + iCalToDo *task; iCalPerson *p; NSString *newContent; NSException *ex; NSString *myEMail; // TODO: do we need to use SOGoTask? (prefer iCalToDo?) - calendar = [iCalCalendar parseSingleFromSource: [self iCalString]]; - if (calendar) - apt = [self firstTaskFromCalendar: calendar]; - else - { - apt = nil; - NSLog (@"this is not good at all, totally fucked we are going tyo crash..."); - } + task = [self task]; - if (apt == nil) { + if (task == nil) { return [NSException exceptionWithHTTPStatus:500 /* Server Error */ reason:@"unable to parse task record"]; } myEMail = [[_ctx activeUser] email]; - if ((p = [apt findParticipantWithEmail:myEMail]) == nil) { + if ((p = [task findParticipantWithEmail:myEMail]) == nil) { return [NSException exceptionWithHTTPStatus:404 /* Not Found */ reason:@"user does not participate in this " @"task"]; } [p setPartStat:_status]; - newContent = [[apt parent] versitString]; + newContent = [[task parent] versitString]; // TODO: send iMIP reply mails? -// [apt release]; apt = nil; +// [task release]; task = nil; if (newContent == nil) { return [NSException exceptionWithHTTPStatus:500 /* Server Error */ diff --git a/SoObjects/Appointments/product.plist b/SoObjects/Appointments/product.plist index cdbdeaea7..3d502d760 100644 --- a/SoObjects/Appointments/product.plist +++ b/SoObjects/Appointments/product.plist @@ -10,6 +10,13 @@ classes = { SOGoAppointmentFolder = { superclass = "SOGoFolder"; + defaultRoles = { + "Add Documents, Images, and Files" = ( "Owner", "Delegate" ); + "View" = ( "Owner", "Delegate", "Assistant" ); + "WebDAV Access" = ( "Owner", "Delegate", "Assistant" ); + "FreeBusyLookup" = ( "Owner", "Delegate", "Assistant", "FreeBusyLookup" ); + "Access Contents Information" = ( "Owner", "Assistant", "Delegate" ); + }; }; SOGoGroupAppointmentFolder = { @@ -18,14 +25,24 @@ SOGoAppointmentObject = { superclass = "SOGoContentObject"; + defaultRoles = { + "View" = ( "Owner", "Delegate", "Organizer" ); + }; }; SOGoTaskObject = { superclass = "SOGoContentObject"; + defaultRoles = { + "View" = ( "Owner", "Delegate", "Organizer" ); + }; }; - SOGoFreeBusyObject = { superclass = "SOGoContentObject"; + protectedBy = "View"; + defaultRoles = { + "View" = ( "Authenticated", "FreeBusy" ); + "WebDAV Access" = ( "Authenticated", "FreeBusy" ); + }; }; }; } diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.m b/SoObjects/Contacts/SOGoContactGCSFolder.m index da9dbc237..6dd136bb5 100644 --- a/SoObjects/Contacts/SOGoContactGCSFolder.m +++ b/SoObjects/Contacts/SOGoContactGCSFolder.m @@ -174,6 +174,11 @@ return records; } +- (NSString *) groupDavResourceType +{ + return @"vcard-collection"; +} + // /* GET */ // - (id) GETAction: (id)_ctx diff --git a/SoObjects/Contacts/SOGoContactLDAPFolder.m b/SoObjects/Contacts/SOGoContactLDAPFolder.m index 6ab54f5fe..bc4ae3a07 100644 --- a/SoObjects/Contacts/SOGoContactLDAPFolder.m +++ b/SoObjects/Contacts/SOGoContactLDAPFolder.m @@ -393,4 +393,9 @@ return result; } +- (NSString *) groupDavResourceType +{ + return @"vcard-collection"; +} + @end diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index d4ddbdcbd..8f70346bd 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -255,11 +255,11 @@ static BOOL useAltNamespace = NO; // TODO: those should be product.plist bindings? (can't be class bindings // though because they are 'per-account') - if ([_key isEqualToString:draftsFolderName]) { + if ([_key isEqualToString: draftsFolderName]) { if ((obj = [self lookupDraftsFolder:_key inContext:_ctx]) != nil) return obj; } - if ([_key isEqualToString:sieveFolderName]) { + if ([_key isEqualToString: sieveFolderName]) { if ((obj = [self lookupFiltersFolder:_key inContext:_ctx]) != nil) return obj; } diff --git a/SoObjects/SOGo/SOGoAuthenticator.m b/SoObjects/SOGo/SOGoAuthenticator.m index 1c2d9073d..00205e6fd 100644 --- a/SoObjects/SOGo/SOGoAuthenticator.m +++ b/SoObjects/SOGo/SOGoAuthenticator.m @@ -20,6 +20,7 @@ */ #import +#import "SOGoPermissions.h" #include "SOGoAuthenticator.h" #include "SOGoUser.h" @@ -73,6 +74,7 @@ static SOGoAuthenticator *auth = nil; { BOOL result; +// return YES; if ([authMethod isEqualToString: @"LDAP"]) result = [self LDAPCheckLogin: _login password: _pwd]; else @@ -98,29 +100,64 @@ static SOGoAuthenticator *auth = nil; /* create SOGoUser */ -- (SoUser *)userInContext:(WOContext *)_ctx +- (SoUser *) userInContext:(WOContext *)_ctx { - static SoUser *anonymous = nil; + static SoUser *anonymous = nil, *freebusy; NSString *login; - NSArray *uroles; if (!anonymous) anonymous = [[SOGoUser alloc] initWithLogin:@"anonymous" roles: [NSArray arrayWithObject: SoRole_Anonymous]]; - + + if (!freebusy) + freebusy + = [[SOGoUser alloc] initWithLogin: @"freebusy" + roles: [NSArray arrayWithObject: SOGoRole_FreeBusy]]; + if ((login = [self checkCredentialsInContext:_ctx]) == nil) /* some error (otherwise result would have been anonymous */ return nil; - if ([login isEqualToString:@"anonymous"]) + if ([login isEqualToString: @"anonymous"]) return anonymous; + else if ([login isEqualToString: @"freebusy"]) + return freebusy; - uroles = [self rolesForLogin:login]; +// uroles = [NSMutableArray arrayWithArray: ]; - return [[[SOGoUser alloc] initWithLogin:login - roles:uroles] + return [[[SOGoUser alloc] initWithLogin: login + roles: [self rolesForLogin: login]] autorelease]; } +// - (BOOL) renderException: (NSException *) exception +// inContext: (WOContext *) context +// { +// id renderedException; +// WOComponent *tmpComponent; +// WOResponse *response; +// BOOL rc; + +// rc = [super renderException: exception inContext: context]; +// if (!rc) +// { +// tmpComponent = [WOComponent new]; +// renderedException = [tmpComponent pageWithName: @"UIxException"]; +// if (renderedException) +// { +// rc = YES; +// response = [context response]; +// [response setHeader: @"text/html" forKey: @"content-type"]; +// [renderedException setClientObject: exception]; +// [context setPage: renderedException]; +// [renderedException appendToResponse: response +// inContext: context]; +// } +// [tmpComponent release]; +// } + +// return rc; +// } + @end /* SOGoAuthenticator */ diff --git a/SoObjects/SOGo/SOGoFolder.h b/SoObjects/SOGo/SOGoFolder.h index 3e79b2b66..b4a6b92bd 100644 --- a/SoObjects/SOGo/SOGoFolder.h +++ b/SoObjects/SOGo/SOGoFolder.h @@ -22,10 +22,11 @@ #ifndef __SOGo_SOGoFolder_H__ #define __SOGo_SOGoFolder_H__ -#include +#import "SOGoObject.h" @class NSString, NSArray, NSDictionary; @class GCSFolder; +@class SOGoAclsFolder; /* SOGoFolder @@ -54,7 +55,6 @@ - (GCSFolder *)ocsFolder; /* lower level fetches */ - - (NSArray *)fetchContentObjectNames; - (NSDictionary *)fetchContentStringsAndNamesOfAllObjects; @@ -64,4 +64,10 @@ @end +@interface SOGoFolder (GroupDAVExtensions) + +- (NSString *) groupDavResourceType; + +@end + #endif /* __SOGo_SOGoFolder_H__ */ diff --git a/SoObjects/SOGo/SOGoFolder.m b/SoObjects/SOGo/SOGoFolder.m index d21abcb81..d60a89815 100644 --- a/SoObjects/SOGo/SOGoFolder.m +++ b/SoObjects/SOGo/SOGoFolder.m @@ -19,6 +19,8 @@ 02111-1307, USA. */ +#import + #include "SOGoFolder.h" #include "common.h" #include @@ -26,6 +28,8 @@ #include #include +#import "SOGoAclsFolder.h" + @implementation SOGoFolder + (int)version { @@ -143,35 +147,49 @@ return nil; } -- (NSArray *)toOneRelationshipKeys { +- (NSArray *) davResourceType +{ + NSArray *rType, *groupDavCollection; + + if ([self respondsToSelector: @selector (groupDavResourceType)]) + { + groupDavCollection = [NSArray arrayWithObjects: [self groupDavResourceType], + @"http://groupdav.org/", @"G", nil]; + rType = [NSArray arrayWithObjects: @"collection", groupDavCollection, nil]; + } + else + rType = [NSArray arrayWithObject: @"collection"]; + + return rType; +} + +- (NSArray *) toOneRelationshipKeys { /* toOneRelationshipKeys are the 'files' contained in a folder */ NSMutableArray *ma; NSArray *names; - NSString *ext; + NSString *name, *ext; unsigned i, count; + NSRange r; - if ((names = [self fetchContentObjectNames]) == nil) - return names; - - if ((count = [names count]) == 0) - return names; - - if ((ext = [self defaultFilenameExtension]) == nil) - return names; - - ma = [NSMutableArray arrayWithCapacity:count]; - for (i = 0; i < count; i++) { - NSRange r; - NSString *name; - - name = [names objectAtIndex:i]; - r = [name rangeOfString:@"."]; - if (r.length == 0) - name = [[name stringByAppendingString:@"."] stringByAppendingString:ext]; - - [ma addObject:name]; - } - return ma; + names = [self fetchContentObjectNames]; + count = [names count]; + ext = [self defaultFilenameExtension]; + if (count && [ext length] > 0) + { + ma = [NSMutableArray arrayWithCapacity: count]; + for (i = 0; i < count; i++) + { + name = [names objectAtIndex: i]; + r = [name rangeOfString: @"."]; + if (r.length == 0) + name = [[name stringByAppendingString:@"."] stringByAppendingString: ext]; + [ma addObject:name]; + } + + names = ma; + } + + return names; } /* WebDAV */ diff --git a/SoObjects/SOGo/SOGoObject.h b/SoObjects/SOGo/SOGoObject.h index cde474b77..def600ef9 100644 --- a/SoObjects/SOGo/SOGoObject.h +++ b/SoObjects/SOGo/SOGoObject.h @@ -37,6 +37,10 @@ @class NSString, NSArray, NSMutableString, NSException, NSTimeZone; @class GCSFolderManager, GCSFolder; @class SOGoUserFolder, SOGoGroupsFolder; +@class WOContext; +@class SOGoDAVSet; + +#define $(class) NSClassFromString(class) @interface SOGoObject : NSObject { @@ -78,6 +82,8 @@ - (NSException *)delete; - (id)GETAction:(id)_ctx; +- (SOGoDAVSet *) davCurrentUserPrivilegeSet; + /* etag support */ - (NSException *)matchesRequestConditionInContext:(id)_ctx; diff --git a/SoObjects/SOGo/SOGoObject.m b/SoObjects/SOGo/SOGoObject.m index 8a15dd536..3691f9627 100644 --- a/SoObjects/SOGo/SOGoObject.m +++ b/SoObjects/SOGo/SOGoObject.m @@ -19,20 +19,120 @@ 02111-1307, USA. */ -#import "SOGoUser.h" -#import "SOGoObject.h" -#import "SOGoUserFolder.h" -#import "AgenorUserManager.h" #import #import +#import +#import +#import #import "common.h" -#import "NSString+URL.h" +#import "NSArray+Utilities.h" +#import "NSString+Utilities.h" + +#import "SOGoPermissions.h" +#import "SOGoUser.h" +#import "SOGoAclsFolder.h" +#import "SOGoAuthenticator.h" +#import "SOGoUserFolder.h" + +#import "SOGoDAVRendererTypes.h" +#import "AgenorUserManager.h" + +#import "SOGoObject.h" @interface SOGoObject(Content) - (NSString *)contentAsString; @end +@interface SoClassSecurityInfo (SOGoAcls) + ++ (id) defaultWebDAVPermissionsMap; + +- (NSArray *) allPermissions; +- (NSArray *) allDAVPermissions; +- (NSArray *) DAVPermissionsForRole: (NSString *) role; +- (NSArray *) DAVPermissionsForRoles: (NSArray *) roles; + +@end + +@implementation SoClassSecurityInfo (SOGoAcls) + ++ (id) defaultWebDAVPermissionsMap +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + @"read", SoPerm_AccessContentsInformation, + @"read", SoPerm_View, + @"bind", SoPerm_AddDocumentsImagesAndFiles, + @"unbind", SoPerm_DeleteObjects, + @"write-acl", SoPerm_ChangePermissions, + @"write-content", SoPerm_ChangeImagesAndFiles, + @"read-free-busy", SOGoPerm_FreeBusyLookup, + NULL]; +} + +- (NSArray *) allPermissions +{ + return [defRoles allKeys]; +} + +- (NSArray *) allDAVPermissions +{ + NSEnumerator *allPermissions; + NSMutableArray *davPermissions; + NSDictionary *davPermissionsMap; + NSString *sopePermission, *davPermission; + + davPermissions = [NSMutableArray array]; + + davPermissionsMap = [[self class] defaultWebDAVPermissionsMap]; + allPermissions = [[self allPermissions] objectEnumerator]; + sopePermission = [allPermissions nextObject]; + while (sopePermission) + { + davPermission = [davPermissionsMap objectForCaseInsensitiveKey: sopePermission]; + if (davPermission && ![davPermissions containsObject: davPermission]) + [davPermissions addObject: davPermission]; + sopePermission = [allPermissions nextObject]; + } + + return davPermissions; +} +- (NSArray *) DAVPermissionsForRole: (NSString *) role +{ + return [self DAVPermissionsForRoles: [NSArray arrayWithObject: role]]; +} + +- (NSArray *) DAVPermissionsForRoles: (NSArray *) roles +{ + NSEnumerator *allPermissions; + NSMutableArray *davPermissions; + NSDictionary *davPermissionsMap; + NSString *sopePermission, *davPermission; + + davPermissions = [NSMutableArray array]; + + davPermissionsMap = [[self class] defaultWebDAVPermissionsMap]; + allPermissions = [[self allPermissions] objectEnumerator]; + sopePermission = [allPermissions nextObject]; + while (sopePermission) + { + if ([[defRoles objectForCaseInsensitiveKey: sopePermission] + firstObjectCommonWithArray: roles]) + { + davPermission + = [davPermissionsMap objectForCaseInsensitiveKey: sopePermission]; + if (davPermission + && ![davPermissions containsObject: davPermission]) + [davPermissions addObject: davPermission]; + } + sopePermission = [allPermissions nextObject]; + } + + return davPermissions; +} + +@end + @implementation SOGoObject static BOOL kontactGroupDAV = YES; @@ -47,23 +147,23 @@ static NSTimeZone *serverTimeZone = nil; NSString *tzName; NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - + kontactGroupDAV = [ud boolForKey:@"SOGoDisableKontact34GroupDAVHack"] ? NO : YES; /* SoClass security declarations */ /* require View permission to access the root (bound to authenticated ...) */ - [[self soClassSecurityInfo] declareObjectProtected:SoPerm_View]; - + [[self soClassSecurityInfo] declareObjectProtected: SoPerm_View]; + /* to allow public access to all contained objects (subkeys) */ - [[self soClassSecurityInfo] setDefaultAccess:@"allow"]; + [[self soClassSecurityInfo] setDefaultAccess: @"allow"]; /* require Authenticated role for View and WebDAV */ - [[self soClassSecurityInfo] declareRole:SoRole_Authenticated - asDefaultForPermission:SoPerm_View]; - [[self soClassSecurityInfo] declareRole:SoRole_Authenticated - asDefaultForPermission:SoPerm_WebDAVAccess]; + [[self soClassSecurityInfo] declareRole: SoRole_Owner + asDefaultForPermission: SoPerm_View]; + [[self soClassSecurityInfo] declareRole: SoRole_Owner + asDefaultForPermission: SoPerm_WebDAVAccess]; if (!serverTimeZone) { @@ -75,6 +175,51 @@ static NSTimeZone *serverTimeZone = nil; } } ++ (void) _fillDictionary: (NSMutableDictionary *) dictionary + withDAVMethods: (NSString *) firstMethod, ... +{ + va_list ap; + NSString *aclMethodName; + NSString *methodName; + SEL methodSel; + + va_start (ap, firstMethod); + aclMethodName = firstMethod; + while (aclMethodName) + { + methodName = [aclMethodName davMethodToObjC]; + methodSel = NSSelectorFromString (methodName); + if (methodSel && [self instancesRespondToSelector: methodSel]) + [dictionary setObject: methodName + forKey: [NSString stringWithFormat: @"{DAV:}%@", + aclMethodName]]; + else + NSLog(@"************ method '%@' is still unimplemented!", + methodName); + aclMethodName = va_arg (ap, NSString *); + } + + va_end (ap); +} + ++ (NSDictionary *) defaultWebDAVAttributeMap +{ + static NSMutableDictionary *map = nil; + + if (!map) + { + map = [NSMutableDictionary + dictionaryWithDictionary: [super defaultWebDAVAttributeMap]]; + [map retain]; + [self _fillDictionary: map + withDAVMethods: @"owner", @"group", @"supported-privilege-set", + @"current-user-privilege-set", @"acl", @"acl-restrictions", + @"inherited-acl-set", @"principal-collection-set", nil]; + } + + return map; +} + /* containment */ + (id) objectWithName: (NSString *)_name inContainer:(id)_container @@ -87,6 +232,165 @@ static NSTimeZone *serverTimeZone = nil; return object; } +/* DAV ACL properties */ +- (NSString *) _principalForUser: (NSString *) user +{ + WOContext *context; + + context = [[WOApplication application] context]; + + return [NSString stringWithFormat: @"%@users/%@", + [self rootURLInContext: context], + user]; +} + +- (NSString *) davOwner +{ + return [self _principalForUser: [self ownerInContext: nil]]; +} + +- (NSString *) davAclRestrictions +{ + NSMutableString *restrictions; + + restrictions = [NSMutableString string]; + [restrictions appendString: @""]; + [restrictions appendString: @""]; + + return restrictions; +} + +- (SOGoDAVSet *) davPrincipalCollectionSet +{ + NSString *usersUrl; + WOContext *context; + + context = [[WOApplication application] context]; + usersUrl = [NSString stringWithFormat: @"%@users", + [self rootURLInContext: context]]; + + return [SOGoDAVSet davSetWithArray: [NSArray arrayWithObject: usersUrl] + ofValuesTaggedAs: @"D:href"]; +} + +- (SOGoDAVSet *) davCurrentUserPrivilegeSet +{ + SOGoAuthenticator *sAuth; + SoUser *user; + NSArray *roles; + WOContext *context; + SoClassSecurityInfo *sInfo; + NSArray *davPermissions; + + sAuth = [SOGoAuthenticator sharedSOGoAuthenticator]; + context = [[WOApplication application] context]; + user = [sAuth userInContext: context]; + roles = [user rolesForObject: self inContext: context]; + sInfo = [[self class] soClassSecurityInfo]; + + davPermissions + = [[sInfo DAVPermissionsForRoles: roles] stringsWithFormat: @""]; + + return [SOGoDAVSet davSetWithArray: davPermissions + ofValuesTaggedAs: @"D:privilege"]; +} + +- (SOGoDAVSet *) davSupportedPrivilegeSet +{ + SoClassSecurityInfo *sInfo; + NSArray *allPermissions; + + sInfo = [[self class] soClassSecurityInfo]; + + allPermissions = [[sInfo allDAVPermissions] stringsWithFormat: @""]; + + return [SOGoDAVSet davSetWithArray: allPermissions + ofValuesTaggedAs: @"D:privilege"]; +} + +- (NSArray *) _davAcesFromAclsDictionary: (NSDictionary *) aclsDictionary +{ + NSEnumerator *keys; + NSArray *privileges; + NSMutableString *currentAce; + NSMutableArray *davAces; + NSString *currentKey; + SOGoDAVSet *privilegesDS; + + davAces = [NSMutableArray array]; + keys = [[aclsDictionary allKeys] objectEnumerator]; + currentKey = [keys nextObject]; + while (currentKey) + { + currentAce = [NSMutableString string]; + if ([currentKey hasPrefix: @":"]) + [currentAce + appendFormat: @"", + [currentKey substringFromIndex: 1]]; + else + [currentAce + appendFormat: @"%@", + [self _principalForUser: currentKey]]; + privileges = [[aclsDictionary objectForKey: currentKey] + stringsWithFormat: @""]; + privilegesDS = [SOGoDAVSet davSetWithArray: privileges + ofValuesTaggedAs: @"privilege"]; + [currentAce appendString: [privilegesDS stringForTag: @"{DAV:}grant" + rawName: @"grant" + inContext: nil prefixes: nil]]; + [davAces addObject: currentAce]; + currentKey = [keys nextObject]; + } + + return davAces; +} + +- (void) _appendRolesForPseudoPrincipals: (NSMutableDictionary *) aclsDictionary + withClassSecurityInfo: (SoClassSecurityInfo *) sInfo +{ + NSArray *perms; + + perms = [sInfo DAVPermissionsForRole: SoRole_Owner]; + if ([perms count]) + [aclsDictionary setObject: perms forKey: @":owner"]; + perms = [sInfo DAVPermissionsForRole: SoRole_Authenticated]; + if ([perms count]) + [aclsDictionary setObject: perms forKey: @":authenticated"]; + perms = [sInfo DAVPermissionsForRole: SoRole_Anonymous]; + if ([perms count]) + [aclsDictionary setObject: perms forKey: @":unauthenticated"]; +} + +- (SOGoDAVSet *) davAcl +{ + NSArray *role; + NSEnumerator *acls; + NSMutableDictionary *aclsDictionary; + NSDictionary *currentAcl; + SoClassSecurityInfo *sInfo; + + acls = [[[SOGoAclsFolder aclsFolder] aclsForObject: self] objectEnumerator]; + aclsDictionary = [NSMutableDictionary dictionary]; + sInfo = [[self class] soClassSecurityInfo]; + + currentAcl = [acls nextObject]; + while (currentAcl) + { + role = [NSArray arrayWithObject: [currentAcl objectForKey: @"role"]]; + [aclsDictionary setObject: [sInfo DAVPermissionsForRoles: role] + forKey: [currentAcl objectForKey: @"uid"]]; + currentAcl = [acls nextObject]; + } + [self _appendRolesForPseudoPrincipals: aclsDictionary + withClassSecurityInfo: sInfo]; + + return [SOGoDAVSet davSetWithArray: + [self _davAcesFromAclsDictionary: aclsDictionary] + ofValuesTaggedAs: @"D:ace"]; +} + +/* end of properties */ + - (BOOL)doesRetainContainer { return YES; } @@ -143,9 +447,10 @@ static NSTimeZone *serverTimeZone = nil; ma = [NSMutableArray arrayWithCapacity:count + 1]; for (i = 0; i < count; i++) { id folder; - - folder = [self lookupName:[names objectAtIndex:i] inContext:nil - acquire:NO]; + + folder = [self lookupName: [names objectAtIndex:i] + inContext: nil + acquire: NO]; if (folder == nil) continue; if ([folder isKindOfClass:[NSException class]]) diff --git a/SoObjects/SOGo/SOGoUser.h b/SoObjects/SOGo/SOGoUser.h index 851dfb62d..164af564a 100644 --- a/SoObjects/SOGo/SOGoUser.h +++ b/SoObjects/SOGo/SOGoUser.h @@ -34,9 +34,8 @@ context.activeUser */ -@class NSString, NSArray, NSDictionary, NSUserDefaults; - -@class NSString, NSArray, NSURL, NSUserDefaults; +@class NSString, NSArray, NSDictionary, NSURL, NSUserDefaults; +@class WOContext; @interface SOGoUser : SoUser { @@ -68,6 +67,9 @@ - (id)homeFolderInContext:(id)_ctx; - (id)schedulingCalendarInContext:(id)_ctx; +- (NSArray *) rolesForObject: (NSObject *) object + inContext: (WOContext *) context; + @end #endif /* __SOGoUser_H__ */ diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 04922e482..2fdeac572 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -19,9 +19,19 @@ 02111-1307, USA. */ -#include "SOGoUser.h" -#include -#include "common.h" +#import +#import "AgenorUserManager.h" +#import "SOGoAclsFolder.h" +#import "common.h" + +#import "SOGoUser.h" + +@interface NSObject (SOGoRoles) + +- (NSString *) roleOfUser: (NSString *) uid + inContext: (WOContext *) context; + +@end @implementation SOGoUser @@ -131,4 +141,35 @@ return folder; } +- (NSArray *) rolesForObject: (NSObject *) object + inContext: (WOContext *) context +{ + NSMutableArray *rolesForObject; + SOGoAclsFolder *aclsFolder; + NSArray *sogoRoles; + NSString *role; + + rolesForObject + = [NSMutableArray arrayWithArray: [super rolesForObject: object + inContext: context]]; + if ([[object ownerInContext: context] isEqualToString: [self login]]) + [rolesForObject addObject: SoRole_Owner]; + if ([object isKindOfClass: [SOGoObject class]]) + { + aclsFolder = [SOGoAclsFolder new]; + sogoRoles = [aclsFolder aclsForObject: (SOGoObject *) object + forUser: login]; + [rolesForObject addObjectsFromArray: sogoRoles]; + [aclsFolder release]; + } + if ([object respondsToSelector: @selector (roleOfUser:inContext:)]) + { + role = [object roleOfUser: login inContext: context]; + if (role) + [rolesForObject addObject: role]; + } + + return rolesForObject; +} + @end /* SOGoUser */ diff --git a/SoObjects/SOGo/SOGoUserFolder.h b/SoObjects/SOGo/SOGoUserFolder.h index f3e7db425..7f52d41f1 100644 --- a/SoObjects/SOGo/SOGoUserFolder.h +++ b/SoObjects/SOGo/SOGoUserFolder.h @@ -22,7 +22,7 @@ #ifndef __SOGo_SOGoUserFolder_H__ #define __SOGo_SOGoUserFolder_H__ -#include +#import "SOGoFolder.h" /* SOGoUserFolder @@ -37,10 +37,9 @@ */ @class NSString; +@class WOContext; @interface SOGoUserFolder : SOGoFolder -{ -} /* accessors */ @@ -48,7 +47,7 @@ /* ownership */ -- (NSString *) ownerInContext: (id) _ctx; +- (NSString *) ownerInContext: (WOContext *) _ctx; /* pathes */ diff --git a/SoObjects/SOGo/SOGoUserFolder.m b/SoObjects/SOGo/SOGoUserFolder.m index fc7b516df..c52cec8f4 100644 --- a/SoObjects/SOGo/SOGoUserFolder.m +++ b/SoObjects/SOGo/SOGoUserFolder.m @@ -19,207 +19,181 @@ 02111-1307, USA. */ -#import "SOGoUserFolder.h" #import "WOContext+Agenor.h" #import "common.h" #import "SOGoUser.h" #import "Appointments/SOGoAppointmentFolder.h" +#import "Appointments/SOGoFreeBusyObject.h" #import "Contacts/SOGoContactFolders.h" +#import "Mailer/SOGoMailAccounts.h" + +#import "SOGoUserFolder.h" @implementation SOGoUserFolder /* accessors */ -- (NSString *)login { - return [self nameInContainer]; +- (NSString *) login +{ + return nameInContainer; } /* hierarchy */ -- (NSArray *)toManyRelationshipKeys { +- (NSArray *) toManyRelationshipKeys +{ static NSArray *children = nil; - - if (children == nil) { + + if (!children) children = [[NSArray alloc] initWithObjects: @"Calendar", @"Contacts", @"Mail", nil]; - } + return children; } /* ownership */ -- (NSString *)ownerInContext:(id)_ctx { - return [self login]; +- (NSString *) ownerInContext: (WOContext *) _ctx +{ + return nameInContainer; } /* looking up shared objects */ -- (SOGoUserFolder *)lookupUserFolder { +- (SOGoUserFolder *) lookupUserFolder +{ return self; } -- (SOGoGroupsFolder *)lookupGroupsFolder { - return [self lookupName:@"Groups" inContext:nil acquire:NO]; +- (SOGoGroupsFolder *) lookupGroupsFolder +{ + return [self lookupName: @"Groups" inContext: nil acquire: NO]; } /* pathes */ -- (void)setOCSPath:(NSString *)_path { +- (void) setOCSPath: (NSString *) _path +{ [self warnWithFormat: @"rejected attempt to reset user-folder path: '%@'", _path]; } -- (NSString *)ocsPath { - return [@"/Users/" stringByAppendingString:[self login]]; + +- (NSString *) ocsPath +{ + return [@"/Users/" stringByAppendingString: [self login]]; } -- (NSString *)ocsUserPath { +- (NSString *) ocsUserPath +{ return [self ocsPath]; } -- (NSString *)ocsPrivateCalendarPath { + +- (NSString *) ocsPrivateCalendarPath +{ return [[self ocsUserPath] stringByAppendingString:@"/Calendar"]; } -- (NSString *)ocsPrivateContactsPath { + +- (NSString *) ocsPrivateContactsPath +{ return [[self ocsUserPath] stringByAppendingString:@"/Contacts"]; } /* name lookup */ -- (id)privateCalendar:(NSString *)_key inContext:(id)_ctx { - static Class calClass = Nil; - id calendar; +// - (NSString *) permissionForKey: (NSString *) key +// { +// return ([key isEqualToString: @"freebusy.ifb"] +// ? SoPerm_WebDAVAccess +// : [super permissionForKey: key]); +// } + +- (SOGoAppointmentFolder *) privateCalendar: (NSString *) _key + inContext: (WOContext *) _ctx +{ + SOGoAppointmentFolder *calendar; - if (calClass == Nil) - calClass = NSClassFromString(@"SOGoAppointmentFolder"); - if (calClass == Nil) { - [self errorWithFormat:@"missing SOGoAppointmentFolder class!"]; - return nil; - } + calendar = [$(@"SOGoAppointmentFolder") objectWithName: _key inContainer: self]; + [calendar setOCSPath: [self ocsPrivateCalendarPath]]; - calendar = [[calClass alloc] initWithName:_key inContainer:self]; - [calendar setOCSPath:[self ocsPrivateCalendarPath]]; - - return [calendar autorelease]; + return calendar; } -- (SOGoContactFolders *) privateContacts: (NSString *)_key inContext:(id)_ctx +- (SOGoContactFolders *) privateContacts: (NSString *) _key + inContext: (WOContext *) _ctx { - static Class contactsClass = Nil; SOGoContactFolders *contacts; - if (!contactsClass) - contactsClass = NSClassFromString (@"SOGoContactFolders"); - if (!contactsClass) - { - [self errorWithFormat:@"missing SOGoContactFolders class!"]; - contacts = nil; - } - else - { - contacts = [[contactsClass alloc] initWithName:_key inContainer: self]; - [contacts autorelease]; - [contacts setBaseOCSPath: [self ocsPrivateContactsPath]]; - } + contacts = [$(@"SOGoContactFolders") objectWithName:_key inContainer: self]; + [contacts setBaseOCSPath: [self ocsPrivateContactsPath]]; return contacts; } -- (id)groupsFolder:(NSString *)_key inContext:(id)_ctx { - static Class fldClass = Nil; - id folder; - - if (fldClass == Nil) - fldClass = NSClassFromString(@"SOGoGroupsFolder"); - if (fldClass == Nil) { - [self errorWithFormat:@"missing SOGoGroupsFolder class!"]; - return nil; - } - - folder = [[fldClass alloc] initWithName:_key inContainer:self]; - return [folder autorelease]; +- (id) groupsFolder: (NSString *) _key + inContext: (WOContext *) _ctx +{ + return [$(@"SOGoGroupsFolder") objectWithName: _key inContainer: self]; } -- (id)mailAccountsFolder:(NSString *)_key inContext:(id)_ctx { - static Class fldClass = Nil; - id folder; - - if (fldClass == Nil) - fldClass = NSClassFromString(@"SOGoMailAccounts"); - if (fldClass == Nil) { - [self errorWithFormat:@"missing SOGoMailAccounts class!"]; - return nil; - } - - folder = [[fldClass alloc] initWithName:_key inContainer:self]; - return [folder autorelease]; +- (id) mailAccountsFolder: (NSString *) _key + inContext: (WOContext *) _ctx +{ + return [$(@"SOGoMailAccounts") objectWithName: _key inContainer: self]; } -- (id)freeBusyObject:(NSString *)_key inContext:(id)_ctx { - static Class fbClass = Nil; - id fb; - - if (fbClass == Nil) - fbClass = NSClassFromString(@"SOGoFreeBusyObject"); - if (fbClass == Nil) { - [self errorWithFormat:@"missing SOGoFreeBusyObject class!"]; - return nil; - } - - fb = [[fbClass alloc] initWithName:_key inContainer:self]; - return [fb autorelease]; +- (id) freeBusyObject: (NSString *) _key + inContext: (WOContext *) _ctx +{ + return [$(@"SOGoFreeBusyObject") objectWithName: _key inContainer: self]; } -- (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag { +- (id) lookupName: (NSString *) _key + inContext: (WOContext *) _ctx + acquire: (BOOL) _flag +{ id obj; /* first check attributes directly bound to the application */ - if ((obj = [super lookupName:_key inContext:_ctx acquire:NO])) - return obj; - - if ([_key hasPrefix:@"Calendar"]) { - id calendar; - - calendar = [self privateCalendar:@"Calendar" inContext:_ctx]; - if ([_key isEqualToString:@"Calendar"]) - return calendar; - - return [calendar lookupName:[_key pathExtension] - inContext:_ctx acquire:NO]; - } - - if ([_key isEqualToString:@"Contacts"]) - return [self privateContacts:_key inContext:_ctx]; - - if ([_key isEqualToString:@"Groups"]) { - /* Agenor requirement, return 403 to stop acquisition */ - if (![_ctx isAccessFromIntranet]) { - return [NSException exceptionWithHTTPStatus:403 /* Forbidden */]; + obj = [super lookupName: _key inContext: _ctx acquire: NO]; + if (!obj) + { + if ([_key hasPrefix: @"Calendar"]) + { + obj = [self privateCalendar: @"Calendar" inContext: _ctx]; + if (![_key isEqualToString: @"Calendar"]) + obj = [obj lookupName: [_key pathExtension] + inContext: _ctx acquire: NO]; + } + else if ([_key isEqualToString: @"Contacts"]) + obj = [self privateContacts: _key inContext: _ctx]; + else if ([_key isEqualToString: @"Groups"]) + obj = [self groupsFolder: _key inContext: _ctx]; + else if ([_key isEqualToString: @"Mail"]) + obj = [self mailAccountsFolder: _key inContext: _ctx]; + else if ([_key isEqualToString: @"freebusy.ifb"]) + obj = [self freeBusyObject:_key inContext:_ctx]; + else + obj = [NSException exceptionWithHTTPStatus: 404 /* Not Found */]; } - return [self groupsFolder:_key inContext:_ctx]; - } - if ([_key isEqualToString:@"Mail"]) - return [self mailAccountsFolder:_key inContext:_ctx]; - - if ([_key isEqualToString:@"freebusy.ifb"]) - return [self freeBusyObject:_key inContext:_ctx]; - - /* return 404 to stop acquisition */ - return [NSException exceptionWithHTTPStatus:404 /* Not Found */]; + return obj; } /* WebDAV */ -- (NSArray *)fetchContentObjectNames { +- (NSArray *) fetchContentObjectNames +{ static NSArray *cos = nil; - if (!cos) { - cos = [[NSArray alloc] initWithObjects:@"freebusy.ifb", nil]; - } + if (!cos) + cos = [[NSArray alloc] initWithObjects: @"freebusy.ifb", nil]; + return cos; } -- (BOOL) davIsCollection { +- (BOOL) davIsCollection +{ return YES; } diff --git a/UI/Common/GNUmakefile b/UI/Common/GNUmakefile index 9ede1a426..add62ea9a 100644 --- a/UI/Common/GNUmakefile +++ b/UI/Common/GNUmakefile @@ -16,6 +16,7 @@ CommonUI_OBJC_FILES += \ UIxAppNavView.m \ UIxJSClose.m \ \ + UIxAclEditor.m \ UIxElemBuilder.m \ UIxTabView.m \ UIxTabItem.m \ @@ -27,6 +28,9 @@ CommonUI_OBJC_FILES += \ CommonUI_RESOURCE_FILES += \ Version \ product.plist \ + Toolbars/SOGoAclOwner.toolbar \ + Toolbars/SOGoAclAssistant.toolbar \ + CommonUI_LOCALIZED_RESOURCE_FILES += \ Localizable.strings \ diff --git a/UI/Common/UIxPageFrame.m b/UI/Common/UIxPageFrame.m index a9bc62cb7..dfb04557f 100644 --- a/UI/Common/UIxPageFrame.m +++ b/UI/Common/UIxPageFrame.m @@ -138,9 +138,9 @@ return isPopup; } -- (NSString *) pageContentClasses +- (NSString *) bodyClasses { - return (isPopup ? @"pageContent popup" : @"pageContent"); + return (isPopup ? @"popup" : @"main"); } /* page based JavaScript */ diff --git a/UI/Common/product.plist b/UI/Common/product.plist index 86fb6b4fa..8061b201d 100644 --- a/UI/Common/product.plist +++ b/UI/Common/product.plist @@ -1,38 +1,47 @@ -{ +{ /* -*-javascript-*- */ requires = ( MAIN, Mailer ); publicResources = ( - calendar.css, - uix.css, - menu_logo_top.gif, - line_left.gif, - line_stretch.gif, - line_right.gif, - box_topleft.gif, - box_top.gif, - box_topright.gif, - box_left.gif, - box_right.gif, - box_botleft.gif, - box_bottom.gi88f, - box_botright.gif, - tab_selected.gif, - tab_.gif, - corner_right.gif, - closewindow.gif, - OGoLogo.gif, - upward_sorted.gif, - downward_sorted.gif, - non_sorted.gif - ); - + calendar.css, + uix.css, + menu_logo_top.gif, + line_left.gif, + line_stretch.gif, + line_right.gif, + box_topleft.gif, + box_top.gif, + box_topright.gif, + box_left.gif, + box_right.gif, + box_botleft.gif, + box_bottom.gif, + box_botright.gif, + tab_selected.gif, + tab_.gif, + corner_right.gif, + closewindow.gif, + OGoLogo.gif, + upward_sorted.gif, + downward_sorted.gif, + non_sorted.gif + ); + factories = { }; categories = { - SOGoObject = { - methods = { - }; - }; + SOGoFolder = { + methods = { + acls = { + protectedBy = "ReadAcls"; + pageName = "UIxAclEditor"; + }; + saveAcls = { + protectedBy = "SaveAcls"; + pageName = "UIxAclEditor"; + actionName = "saveAcls"; + }; + }; + }; }; } diff --git a/UI/Contacts/GNUmakefile b/UI/Contacts/GNUmakefile index 6f03ae993..2c8b9a36f 100644 --- a/UI/Contacts/GNUmakefile +++ b/UI/Contacts/GNUmakefile @@ -9,9 +9,10 @@ ContactsUI_PRINCIPAL_CLASS = ContactsUIProduct ContactsUI_LANGUAGES = English French ContactsUI_OBJC_FILES = \ - UIxContactsMailerSelection.m \ - UIxContactsCalendarsSelection.m \ + UIxContactsAclsSelection.m \ UIxContactsAddressBooksSelection.m \ + UIxContactsCalendarsSelection.m \ + UIxContactsMailerSelection.m \ \ ContactsUIProduct.m \ UIxContactsFilterPanel.m \ diff --git a/UI/Contacts/UIxContactFoldersView.m b/UI/Contacts/UIxContactFoldersView.m index e389d02d6..ae9ae37ea 100644 --- a/UI/Contacts/UIxContactFoldersView.m +++ b/UI/Contacts/UIxContactFoldersView.m @@ -27,7 +27,7 @@ #import #import -#import +#import #import #import @@ -87,6 +87,11 @@ return [self _selectActionForApplication: @"addressbooks-contacts"]; } +- (id) selectForAclsAction +{ + return [self _selectActionForApplication: @"acls-contacts"]; +} + - (NSArray *) _searchResults: (NSString *) contact { NSMutableArray *results; diff --git a/UI/Contacts/UIxContactsListView.m b/UI/Contacts/UIxContactsListView.m index 1b35e8431..7a3cdd99d 100644 --- a/UI/Contacts/UIxContactsListView.m +++ b/UI/Contacts/UIxContactsListView.m @@ -97,6 +97,13 @@ return self; } +- (id) aclsContactsAction +{ + selectorComponentClass = @"UIxContactsAclsSelection"; + + return self; +} + - (NSString *) defaultSortKey { return @"fn"; diff --git a/UI/Contacts/product.plist b/UI/Contacts/product.plist index 0a4bbe2ad..0a86580de 100644 --- a/UI/Contacts/product.plist +++ b/UI/Contacts/product.plist @@ -1,196 +1,219 @@ -{ +{ /* -*-javascript-*- */ requires = ( MAIN, CommonUI, Contacts ); - publicResources = ( - ); + publicResources = (); - factories = { - }; + factories = {}; categories = { - SOGoContactFolders = { - methods = { - view = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; + SOGoContactFolders = { + methods = { + view = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + }; + new = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + actionName = "new"; + }; + scheduler-contacts = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + actionName = "selectForScheduler"; + }; + mailer-contacts = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + actionName = "selectForMailer"; + }; + calendars-contacts = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + actionName = "selectForCalendars"; + }; + addressbooks-contacts = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + actionName = "selectForAddressBooks"; + }; + acls-contacts = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + actionName = "selectForAcls"; + }; + contactSearch = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + actionName = "contactSearch"; + }; + updateAdditionalAddressBooks = { + protectedBy = "View"; + pageName = "UIxContactFoldersView"; + actionName = "updateAdditionalAddressBooks"; + }; + acls = { + protectedBy = "ReadAcls"; + pageName = "UIxAclEditor"; + }; + saveAcls = { + protectedBy = "SaveAcls"; + pageName = "UIxAclEditor"; + actionName = "saveAcls"; + }; }; - new = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; - actionName = "new"; - }; - scheduler-contacts = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; - actionName = "selectForScheduler"; - }; - mailer-contacts = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; - actionName = "selectForMailer"; - }; - calendars-contacts = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; - actionName = "selectForCalendars"; - }; - addressbooks-contacts = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; - actionName = "selectForAddressBooks"; - }; - contactSearch = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; - actionName = "contactSearch"; - }; - updateAdditionalAddressBooks = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; - actionName = "updateAdditionalAddressBooks"; - }; - }; - }; + }; - SOGoContactGCSFolder = { - slots = { - toolbar = { - protectedBy = "View"; - value = "SOGoContactFolder.toolbar"; + SOGoContactGCSFolder = { + slots = { + toolbar = { + protectedBy = "View"; + value = "SOGoContactFolder.toolbar"; + }; }; - }; - methods = { - view = { - protectedBy = "View"; - pageName = "UIxContactsListView"; + methods = { + view = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + }; + new = { + protectedBy = "View"; + pageName = "UIxContactEditor"; + actionName = "new"; + }; + mailer-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "mailerContacts"; + }; + calendars-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "calendarsContacts"; + }; + acls-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "aclsContacts"; + }; + addressbooks-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "addressBooksContacts"; + }; }; - new = { - protectedBy = "View"; - pageName = "UIxContactEditor"; - actionName = "new"; - }; - mailer-contacts = { - protectedBy = "View"; - pageName = "UIxContactsListView"; - actionName = "mailerContacts"; - }; - calendars-contacts = { - protectedBy = "View"; - pageName = "UIxContactsListView"; - actionName = "calendarsContacts"; - }; - addressbooks-contacts = { - protectedBy = "View"; - pageName = "UIxContactsListView"; - actionName = "addressBooksContacts"; - }; - }; - }; + }; - SOGoContactLDAPFolder = { - slots = { - toolbar = { - protectedBy = "View"; - value = "SOGoContactFolder.toolbar"; + SOGoContactLDAPFolder = { + slots = { + toolbar = { + protectedBy = "View"; + value = "SOGoContactFolder.toolbar"; + }; }; - }; - methods = { - view = { - protectedBy = "View"; - pageName = "UIxContactsListView"; + methods = { + view = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + }; + new = { + protectedBy = "View"; + pageName = "UIxContactEditor"; + actionName = "new"; + }; + scheduler-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "schedulerContacts"; + }; + mailer-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "mailerContacts"; + }; + calendars-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "calendarsContacts"; + }; + acls-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "aclsContacts"; + }; + addressbooks-contacts = { + protectedBy = "View"; + pageName = "UIxContactsListView"; + actionName = "addressBooksContacts"; + }; }; - new = { - protectedBy = "View"; - pageName = "UIxContactEditor"; - actionName = "new"; - }; - scheduler-contacts = { - protectedBy = "View"; - pageName = "UIxContactsListView"; - actionName = "schedulerContacts"; - }; - mailer-contacts = { - protectedBy = "View"; - pageName = "UIxContactsListView"; - actionName = "mailerContacts"; - }; - calendars-contacts = { - protectedBy = "View"; - pageName = "UIxContactsListView"; - actionName = "calendarsContacts"; - }; - addressbooks-contacts = { - protectedBy = "View"; - pageName = "UIxContactsListView"; - actionName = "addressBooksContacts"; - }; - }; - }; + }; - SOGoContactGCSEntry = { - methods = { - view = { - protectedBy = "View"; - pageName = "UIxContactView"; + SOGoContactGCSEntry = { + methods = { + view = { + protectedBy = "View"; + pageName = "UIxContactView"; + }; + delete = { + protectedBy = "View"; + pageName = "UIxContactView"; + actionName = "delete"; + }; + edit = { + protectedBy = "View"; + pageName = "UIxContactEditor"; + }; + save = { + protectedBy = "View"; + pageName = "UIxContactEditor"; + actionName = "save"; + }; + write = { + protectedBy = "View"; + pageName = "UIxContactEditor"; + actionName = "write"; + }; + vcard = { + protectedBy = "View"; + pageName = "UIxContactView"; + actionName = "vcard"; + }; }; - delete = { - protectedBy = "View"; - pageName = "UIxContactView"; - actionName = "delete"; - }; - edit = { - protectedBy = "View"; - pageName = "UIxContactEditor"; - }; - save = { - protectedBy = "View"; - pageName = "UIxContactEditor"; - actionName = "save"; - }; - write = { - protectedBy = "View"; - pageName = "UIxContactEditor"; - actionName = "write"; - }; - vcard = { - protectedBy = "View"; - pageName = "UIxContactView"; - actionName = "vcard"; - }; - }; - }; + }; - SOGoContactLDAPEntry = { - methods = { - view = { - protectedBy = "View"; - pageName = "UIxContactView"; + SOGoContactLDAPEntry = { + methods = { + view = { + protectedBy = "View"; + pageName = "UIxContactView"; + }; + delete = { + protectedBy = "View"; + pageName = "UIxContactView"; + actionName = "delete"; + }; + edit = { + protectedBy = "View"; + pageName = "UIxContactEditor"; + }; + save = { + protectedBy = "View"; + pageName = "UIxContactEditor"; + actionName = "save"; + }; + write = { + protectedBy = "View"; + pageName = "UIxContactEditor"; + actionName = "write"; + }; + vcard = { + protectedBy = "View"; + pageName = "UIxContactView"; + actionName = "vcard"; + }; }; - delete = { - protectedBy = "View"; - pageName = "UIxContactView"; - actionName = "delete"; - }; - edit = { - protectedBy = "View"; - pageName = "UIxContactEditor"; - }; - save = { - protectedBy = "View"; - pageName = "UIxContactEditor"; - actionName = "save"; - }; - write = { - protectedBy = "View"; - pageName = "UIxContactEditor"; - actionName = "write"; - }; - vcard = { - protectedBy = "View"; - pageName = "UIxContactView"; - actionName = "vcard"; - }; - }; - }; + }; }; } + diff --git a/UI/MailerUI/UIxMailEditorAction.m b/UI/MailerUI/UIxMailEditorAction.m index c6fdb32e8..676fddfbc 100644 --- a/UI/MailerUI/UIxMailEditorAction.m +++ b/UI/MailerUI/UIxMailEditorAction.m @@ -50,13 +50,14 @@ Note: we cannot use acquisition to find the nearest drafts folder, because the IMAP4 server might contains an own Drafts folder. */ - SOGoDraftsFolder *drafts; - id client; +// SOGoDraftsFolder *drafts; + SOGoMailAccount *accountFolder; - client = [self clientObject]; - drafts = [[client mailAccountFolder] - lookupName:@"Drafts" inContext:[self context] acquire:NO]; - return drafts; + accountFolder = [[self clientObject] mailAccountFolder]; + + return [accountFolder + lookupName: [accountFolder draftsFolderNameInContext: context] + inContext: context acquire: NO]; } /* errors */ @@ -93,7 +94,7 @@ returnValue = drafts; else { - urlBase = [drafts newObjectBaseURLInContext: [self context]]; + urlBase = [drafts newObjectBaseURLInContext: context]; if ([urlBase isNotNull]) { urlParams = [NSMutableDictionary new]; @@ -119,7 +120,7 @@ [self debugWithFormat:@"compose on %@: %@", drafts, url]; - r = [[self context] response]; + r = [context response]; [r setStatus: 302 /* move d */]; [r setHeader: url forKey: @"location"]; [self reset]; @@ -147,7 +148,7 @@ if ([drafts isKindOfClass:[NSException class]]) return drafts; - return [drafts newObjectInContext:[self context]]; + return [drafts newObjectInContext:context]; } - (NSException *)_setupNewDraft { @@ -178,14 +179,14 @@ return nil; } - url = [self->newDraft baseURLInContext:[self context]]; + url = [self->newDraft baseURLInContext:context]; if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"]; url = [url stringByAppendingString:@"edit"]; // TODO: debug log [self logWithFormat:@"compose on %@", url]; - r = [[self context] response]; + r = [context response]; [r setStatus:302 /* moved */]; [r setHeader:url forKey:@"location"]; [self reset]; diff --git a/UI/MainUI/GNUmakefile b/UI/MainUI/GNUmakefile index ed4b2ec2e..0432e77fa 100644 --- a/UI/MainUI/GNUmakefile +++ b/UI/MainUI/GNUmakefile @@ -17,7 +17,7 @@ MainUI_OBJC_FILES += \ MainUI_RESOURCE_FILES += \ Version \ - product.plist + product.plist MainUI_LOCALIZED_RESOURCE_FILES += \ Locale Localizable.strings diff --git a/UI/MainUI/SOGoUserHomePage.m b/UI/MainUI/SOGoUserHomePage.m index 27a1071ef..01aa6af4e 100644 --- a/UI/MainUI/SOGoUserHomePage.m +++ b/UI/MainUI/SOGoUserHomePage.m @@ -290,7 +290,7 @@ static NSArray *internetAccessStates = nil; for (count = 1; count < intervals; count++) [freeBusyItems addObject: @"0"]; - records = [[fb fetchFreebusyInfosFrom: startDate to: endDate] objectEnumerator]; + records = [[fb fetchFreeBusyInfosFrom: startDate to: endDate] objectEnumerator]; [self _fillFreeBusyItems: freeBusyItems withRecords: records fromStartDate: startDate toEndDate: endDate]; diff --git a/UI/MainUI/product.plist b/UI/MainUI/product.plist index 9f2869c32..ec730eb81 100644 --- a/UI/MainUI/product.plist +++ b/UI/MainUI/product.plist @@ -4,6 +4,53 @@ publicResources = ( ); + factories = { + }; + + classes = { + SOGoRootPage = { + superclass = "SoComponent"; + protectedBy = "View"; + defaultRoles = { + "View" = ( "Authenticated", "FreeBusy" ); + }; + }; + SOGoUserFolder = { + superclass = "SOGoFolder"; + protectedBy = "HomePage Access"; + defaultRoles = { + "Homepage Access" = ( "Owner", "Assistant", "Delegate", "FreeBusy" ); + "WebDAV Access" = ( "Owner", "Assistant", "Delegate", "FreeBusy" ); + "Access Contents Information" = ( "Owner", "Assistant", "Delegate", + "FreeBusy" ); + }; + }; + SOGoFolder = { + superclass = "SOGoObject"; + protectedBy = "Access Contents Information"; + defaultRoles = { + "Add Documents, Images, and Files" = ( "Owner", "Delegate" ); + "View" = ( "Owner", "Delegate", "Assistant" ); + "WebDAV Access" = ( "Owner", "Delegate", "Assistant" ); + "Access Contents Information" = ( "Owner", "Assistant", "Delegate" ); + "ReadAcls" = ( "Owner", "Delegate", "Assistant" ); + "SaveAcls" = ( "Owner" ); + }; + }; + SOGoGroupsFolder = { + superclass = "SOGoObject"; + protectedBy = "View"; + }; + SOGoGroupFolder = { + superclass = "SOGoObject"; + protectedBy = "View"; + }; + SOGoCustomGroupFolder = { + superclass = "SOGoGroupFolder"; + protectedBy = "View"; + }; + }; + categories = { SOGo = { // TODO: move decls to class methods = { @@ -15,31 +62,11 @@ protectedBy = "View"; pageName = "SOGoRootPage"; }; - connect = { - protectedBy = "View"; - pageName = "SOGoRootPage"; - actionName = "connect"; - }; }; }; - }; - - classes = { SOGoRootPage = { - superclass = "SoComponent"; - protectedBy = "View"; - defaultRoles = { - "View" = "Authenticated"; - }; }; - SOGoUserFolder = { - superclass = "SOGoFolder"; - - defaultRoles = { - "HomePage Access" = "Owner"; - }; - methods = { view = { protectedBy = "HomePage Access"; @@ -58,9 +85,7 @@ */ }; }; - SOGoGroupsFolder = { - superclass = "SOGoObject"; methods = { index = { protectedBy = "View"; @@ -69,7 +94,6 @@ }; }; SOGoGroupFolder = { - superclass = "SOGoObject"; methods = { index = { protectedBy = "View"; @@ -78,17 +102,15 @@ }; }; SOGoFreeBusyObject = { - superclass = "SOGoObject"; methods = { ajaxRead = { protectedBy = "View"; - pageName = "SOGoUserHomePage"; - actionName = "readFreeBusy"; + pageName = "SOGoUserHomePage"; + actionName = "readFreeBusy"; }; }; }; SOGoCustomGroupFolder = { - superclass = "SOGoGroupFolder"; methods = { }; }; diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index bae95d80f..f8b194739 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -298,12 +298,12 @@ inContext:[self context]]; [self debugWithFormat:@"group calendar: %@", groupCalendar]; - if (![groupCalendar respondsToSelector:@selector(fetchFreebusyInfosFrom:to:)]) { + if (![groupCalendar respondsToSelector:@selector(fetchFreeBusyInfosFrom:to:)]) { [self errorWithFormat:@"invalid folder to run freebusy query on!"]; return NO; } - infos = [groupCalendar fetchFreebusyInfosFrom:[_apt startDate] + infos = [groupCalendar fetchFreeBusyInfosFrom:[_apt startDate] to:[_apt endDate]]; [self debugWithFormat:@" process: %d events", [infos count]]; diff --git a/UI/Scheduler/UIxAppointmentProposal.m b/UI/Scheduler/UIxAppointmentProposal.m index 283acfbba..978a03146 100644 --- a/UI/Scheduler/UIxAppointmentProposal.m +++ b/UI/Scheduler/UIxAppointmentProposal.m @@ -416,7 +416,7 @@ fb = [fbos objectAtIndex:i]; if (fb != (SOGoFreeBusyObject *)[NSNull null]) { - infos = [fb fetchFreebusyInfosFrom:[self startDate] to:[self endDate]]; + infos = [fb fetchFreeBusyInfosFrom:[self startDate] to:[self endDate]]; [allInfos addObjectsFromArray:infos]; } } diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index 726744ede..9335c23a1 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -284,12 +284,12 @@ inContext:[self context]]; [self debugWithFormat:@"group calendar: %@", groupCalendar]; - if (![groupCalendar respondsToSelector:@selector(fetchFreebusyInfosFrom:to:)]) { + if (![groupCalendar respondsToSelector:@selector(fetchFreeBusyInfosFrom:to:)]) { [self errorWithFormat:@"invalid folder to run freebusy query on!"]; return NO; } - infos = [groupCalendar fetchFreebusyInfosFrom:[_task startDate] + infos = [groupCalendar fetchFreeBusyInfosFrom:[_task startDate] to:[_task due]]; [self debugWithFormat:@" process: %d tasks", [infos count]]; diff --git a/UI/Scheduler/UIxTaskProposal.m b/UI/Scheduler/UIxTaskProposal.m index f2b35e821..c558ccdd2 100644 --- a/UI/Scheduler/UIxTaskProposal.m +++ b/UI/Scheduler/UIxTaskProposal.m @@ -416,7 +416,7 @@ fb = [fbos objectAtIndex:i]; if (fb != (SOGoFreeBusyObject *)[NSNull null]) { - infos = [fb fetchFreebusyInfosFrom:[self startDate] to:[self endDate]]; + infos = [fb fetchFreeBusyInfosFrom:[self startDate] to:[self endDate]]; [allInfos addObjectsFromArray:infos]; } } diff --git a/UI/Scheduler/product.plist b/UI/Scheduler/product.plist index a9329d6c5..1b52a82b8 100644 --- a/UI/Scheduler/product.plist +++ b/UI/Scheduler/product.plist @@ -64,13 +64,13 @@ protectedBy = "View"; pageName = "UIxCalMonthView"; }; - newevent = { - protectedBy = "View"; + newevent = { + protectedBy = "Add Documents, Images, and Files"; pageName = "UIxAppointmentEditor"; actionName = "new"; }; newtask = { - protectedBy = "View"; + protectedBy = "Add Documents, Images, and Files"; pageName = "UIxTaskEditor"; actionName = "new"; }; @@ -89,7 +89,7 @@ actionName = "proposalSearch"; }; batchDelete = { - protectedBy = "View"; + protectedBy = "Delete Objects"; pageName = "UIxCalMainView"; actionName = "batchDelete"; }; @@ -160,7 +160,7 @@ pageName = "UIxAppointmentView"; actionName = "delete"; }; - edit = { + edit = { protectedBy = "View"; pageName = "UIxAppointmentEditor"; }; @@ -219,35 +219,35 @@ actionName = "delete"; }; edit = { - protectedBy = "View"; + protectedBy = "Change Images and Files"; pageName = "UIxTaskEditor"; }; editAsTask = { - protectedBy = "View"; + protectedBy = "Change Images and Files"; pageName = "UIxTaskEditor"; }; save = { - protectedBy = "View"; + protectedBy = "Change Images and Files"; pageName = "UIxTaskEditor"; actionName = "save"; }; saveAsTask = { - protectedBy = "View"; + protectedBy = "Change Images and Files"; pageName = "UIxTaskEditor"; actionName = "save"; }; changeStatus = { - protectedBy = "View"; + protectedBy = "Change Images and Files"; pageName = "UIxTaskEditor"; actionName = "changeStatus"; }; accept = { - protectedBy = "View"; + protectedBy = "Change Images and Files"; pageName = "UIxTaskEditor"; actionName = "accept"; }; decline = { - protectedBy = "View"; + protectedBy = "Change Images and Files"; pageName = "UIxTaskEditor"; actionName = "decline"; }; diff --git a/UI/Templates/ContactsUI/UIxContactSelector.wox b/UI/Templates/ContactsUI/UIxContactSelector.wox index 7fdc40f31..dcc759065 100644 --- a/UI/Templates/ContactsUI/UIxContactSelector.wox +++ b/UI/Templates/ContactsUI/UIxContactSelector.wox @@ -46,19 +46,5 @@
- diff --git a/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox b/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox index 7de8fa810..6ec229f15 100644 --- a/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox +++ b/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox @@ -12,39 +12,24 @@ diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index 2ec1abc45..e460a06bc 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -12,20 +12,15 @@ @@ -33,30 +28,22 @@ @@ -64,33 +51,24 @@ @@ -98,36 +76,26 @@ @@ -135,13 +103,10 @@ @@ -149,20 +114,15 @@ + + + + + + + +
- +
@@ -318,20 +252,20 @@
- +
- - + + - + diff --git a/UI/Templates/SchedulerUI/UIxCalMainView.wox b/UI/Templates/SchedulerUI/UIxCalMainView.wox index e946818d2..bbcd8e86f 100644 --- a/UI/Templates/SchedulerUI/UIxCalMainView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMainView.wox @@ -33,35 +33,31 @@ + + @@ -105,8 +101,4 @@ selectedDate="selectedDate" -->
- -
diff --git a/UI/Templates/UIxPageFrame.wox b/UI/Templates/UIxPageFrame.wox index cd763cc05..8b087e3bb 100644 --- a/UI/Templates/UIxPageFrame.wox +++ b/UI/Templates/UIxPageFrame.wox @@ -28,7 +28,7 @@ />
- +