diff --git a/ChangeLog b/ChangeLog index a9455e1fa..bb9b8fbc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,86 @@ +2007-05-23 Wolfgang Sourdeau + + * UI/MailerUI/UIxMailSplashView.m: removed. + + * SoObjects/Appointments/SOGoCalendarComponent.m + ([SOGoCalendarComponent -getUIDsForICalPersons:iCalPersons]): add + the uid to the list only when the user email is recognized by the + user manager. + +2007-05-22 Wolfgang Sourdeau + + * SoObjects/Mailer/SOGoMailObject.m ([SOGoMailObject + -isDeletionAllowed]): completed method with the new imap acl api. + + * SoObjects/SOGo/SOGoObject.m ([SOGoObject -defaultAclRoles]): + removed method. + + * SoObjects/SOGo/SOGoPermissions.m: added the new role + "SOGoMailRole_MessageEraser". + + * UI/Common/UIxAclEditor.m ([UIxAclEditor -defaultUserID]) + ([UIxAclEditor -_prepareUsers]): take the new SOGoObject's + "defaultUserID" method into account. + + * UI/Common/UIxUserRightsEditor.m ([UIxUserRightsEditor -userIsDefaultUser]) + ([UIxUserRightsEditor -_initRights]): take the new SOGoObject's + "defaultUserID" method into account. + + * UI/MailerUI/UIxMailUserRightsEditor.m: added all the missing + methods to support the IMAP acls mentionned in the RFC 4314, + removed the ones specific to Cyrus. + + * SoObjects/SOGo/SOGoObject.m ([SOGoObject -defaultUserID]): new + mandatory method for subclasses. Removed the SOGoDefaultUserID + global var. + + * SoObjects/SOGo/SOGoFolder.m ([SOGoFolder -defaultUserID]): + overriden method to return @"". + + * SoObjects/SOGo/SOGoContentObject.m ([SOGoContentObject + -defaultUserID]): overriden method to return @"". + + * SoObjects/Mailer/SOGoMailFolder.m ([SOGoMailFolder + -aclsForUser:uid]): overriden method. + ([SOGoMailFolder -removeAclsForUsers:users]): overriden method. + ([SOGoMailFolder -setRoles:rolesforUser:uid]): overriden method. + ([SOGoMailFolder -defaultUserID]): overriden method. + ([SOGoMailFolder -hasSupportForDefaultRoles]): overriden method. + 2007-05-18 Wolfgang Sourdeau + * SoObjects/SOGo/SOGoFolder.m ([SOGoFolder + -aclUsersForObjectAtPath:objectPathArray]): new method that being + forwarded the calles to aclUsers for the GCS-based subclasses of + SOGoObject. + + * SoObjects/Mailer/SOGoMailFolder.m: removed all the previous + methods that would have been used to support IMAP acls. Replaced + them with the new protocol for them that has been implemented in + SOGo during the last few weeks. + + * SoObjects/SOGo/SOGoContentObject.m ([SOGoContentObject + -hasSupportForDefaultRoles]): override method by returning "YES". + + * SoObjects/SOGo/NSArray+Utilities.m ([NSMutableArray + -addObjectUniquely:object]): new method with an explicit name. + + * SoObjects/SOGo/SOGoObject.m ([SOGoObject -aclUsers]): renamed + "acl" to "aclUsers". Now designed to return only the uid of the + users involved in an ACL. + ([SOGoObject -hasSupportForDefaultRoles]): new method returning + "NO" by default. To indicate to the acl editor that we don't want + to handle a default user. + + * SoObjects/SOGo/SOGoPermissions.[hm]: added the + SOGoRole_ObjectReader, SOGoRole_Folder*, and SOGoMailRole_* + symbols. + + * UI/MailerUI/UIxMailUserRightsEditor.[hm]: new class module that + provides a view to the IMAP acls. + + * UI/MailerUI/UIxMailFolderACLEditor.m: removed obsolete module. + * UI/WebServerResources/MailerUI.js: replaced all invocations of addEventListener to the use of prototype's Event object. Also, configured all menus programmatically following descriptions lists diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 5d708c38f..a2cea22ac 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -1296,13 +1296,4 @@ static NSNumber *sharedYes = nil; return @"IPF.Appointment"; } -/* acls */ -- (NSArray *) defaultAclRoles -{ - return [NSArray arrayWithObjects: - SOGoCalendarRole_PublicViewer, - SOGoCalendarRole_ConfidentialDAndTViewer, - nil]; -} - @end /* SOGoAppointmentFolder */ diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index 9e8c841e6..14267daf8 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -513,7 +513,7 @@ static BOOL sendEMailNotifications = NO; iCalPerson *currentPerson; NSEnumerator *persons; NSMutableArray *uids; - NSString *email; + NSString *email, *uid; LDAPUserManager *um; uids = [NSMutableArray array]; @@ -523,8 +523,9 @@ static BOOL sendEMailNotifications = NO; currentPerson = [persons nextObject]; while (currentPerson) { - email = [currentPerson rfc822Email]; - [uids addObject: [um getUIDForEmail: email]]; + uid = [um getUIDForEmail: [currentPerson rfc822Email]]; + if (uid) + [uids addObject: uid]; currentPerson = [persons nextObject]; } diff --git a/SoObjects/Mailer/SOGoMailFolder.h b/SoObjects/Mailer/SOGoMailFolder.h index ce49d2a4c..a698bdaaa 100644 --- a/SoObjects/Mailer/SOGoMailFolder.h +++ b/SoObjects/Mailer/SOGoMailFolder.h @@ -41,17 +41,6 @@ NSArray *filenames; NSString *folderType; NGImap4MailboxInfo *selectInfo; - struct { - int didCheckMyRights:1; - int isDeleteAndExpungeAllowed:1; - int isReadAllowed:1; - int isWriteAllowed:1; - int isInsertAllowed:1; - int isPostAllowed:1; - int isCreateAllowed:1; - int hasAdminAccess:1; - int reserved:24; - } somfFlags; } /* messages */ @@ -63,16 +52,6 @@ - (NSException *)expunge; -/* permissions */ - -- (BOOL)isDeleteAndExpungeAllowed; -- (BOOL)isReadAllowed; -- (BOOL)isWriteAllowed; -- (BOOL)isInsertAllowed; -- (BOOL)isPostAllowed; -- (BOOL)isCreateAllowed; -- (BOOL)hasAdminAccess; - /* flags */ - (NSException *)addFlagsToAllMessages:(id)_f; diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index cf537404a..6c7c84cb1 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -19,13 +19,27 @@ 02111-1307, USA. */ -#include "SOGoMailFolder.h" -#include "SOGoMailObject.h" -#include "SOGoMailAccount.h" -#include "SOGoMailManager.h" -#include -#include "SOGoMailFolderDataSource.h" -#include "common.h" +#import + +#import +#import +#import +#import + +#import +#import +#import + +#import +#import + +#import "SOGoMailObject.h" +#import "SOGoMailAccount.h" +#import "SOGoMailManager.h" +#import "SOGoMailFolderDataSource.h" +#import "SOGoMailFolder.h" + +static NSString *defaultUserID = @"anyone"; @implementation SOGoMailFolder @@ -46,9 +60,9 @@ static BOOL useAltNamespace = NO; } - (void)dealloc { - [self->selectInfo release]; - [self->filenames release]; - [self->folderType release]; + [selectInfo release]; + [filenames release]; + [folderType release]; [super dealloc]; } @@ -68,15 +82,15 @@ static BOOL useAltNamespace = NO; NSArray *uids; unsigned count; - if (self->filenames != nil) - return [self->filenames isNotNull] ? self->filenames : nil; + if (filenames != nil) + return [filenames isNotNull] ? filenames : nil; uids = [self fetchUIDsMatchingQualifier:nil sortOrdering:@"DATE"]; if ([uids isKindOfClass:[NSException class]]) return nil; if ((count = [uids count]) == 0) { - self->filenames = [[NSArray alloc] init]; + filenames = [[NSArray alloc] init]; } else { NSMutableArray *keys; @@ -90,10 +104,10 @@ static BOOL useAltNamespace = NO; k = [k stringByAppendingString:@".mail"]; [keys addObject:k]; } - self->filenames = [keys copy]; + filenames = [keys copy]; [keys release]; } - return self->filenames; + return filenames; } - (EODataSource *)contentDataSourceInContext:(id)_ctx { @@ -110,98 +124,17 @@ static BOOL useAltNamespace = NO; /* returns nil if fetch was successful */ id info; - if (self->selectInfo != nil) + if (selectInfo != nil) return nil; /* select info exists, => no error */ info = [[self imap4Connection] infoForMailboxAtURL:[self imap4URL]]; if ([info isKindOfClass:[NSException class]]) return info; - self->selectInfo = [info retain]; + selectInfo = [info retain]; return nil; /* no error */ } -/* permissions */ - -- (void)_loadACLPermissionFlags { - NSString *rights; - unsigned i, len; - - if (self->somfFlags.didCheckMyRights) - return; - - rights = [[self imap4Connection] myRightsForMailboxAtURL:[self imap4URL]]; - if ([rights isKindOfClass:[NSException class]]) { - [self logWithFormat:@"ERROR: could not retrieve ACL: %@", rights]; - return; - } - - // [self logWithFormat:@"GOT PERM: %@", rights]; - - self->somfFlags.didCheckMyRights = 1; - - /* reset flags */ - self->somfFlags.isDeleteAndExpungeAllowed = 0; - self->somfFlags.isReadAllowed = 0; - self->somfFlags.isWriteAllowed = 0; - self->somfFlags.isInsertAllowed = 0; - self->somfFlags.isPostAllowed = 0; - self->somfFlags.isCreateAllowed = 0; - self->somfFlags.hasAdminAccess = 0; - - for (i = 0, len = [rights length]; i < len; i++) { - switch ([rights characterAtIndex:i]) { - case 'd': self->somfFlags.isDeleteAndExpungeAllowed = 1; break; - case 'r': self->somfFlags.isReadAllowed = 1; break; - case 'w': self->somfFlags.isWriteAllowed = 1; break; - case 'i': self->somfFlags.isInsertAllowed = 1; break; - case 'p': self->somfFlags.isPostAllowed = 1; break; - case 'c': self->somfFlags.isCreateAllowed = 1; break; - case 'a': self->somfFlags.hasAdminAccess = 1; break; - } - } -} - -- (BOOL)isDeleteAndExpungeAllowed { - [self _loadACLPermissionFlags]; - return self->somfFlags.isDeleteAndExpungeAllowed ? YES : NO; -} -- (BOOL)isReadAllowed { - [self _loadACLPermissionFlags]; - return self->somfFlags.isReadAllowed ? YES : NO; -} -- (BOOL)isWriteAllowed { - [self _loadACLPermissionFlags]; - return self->somfFlags.isWriteAllowed ? YES : NO; -} -- (BOOL)isInsertAllowed { - [self _loadACLPermissionFlags]; - return self->somfFlags.isInsertAllowed ? YES : NO; -} -- (BOOL)isPostAllowed { - [self _loadACLPermissionFlags]; - return self->somfFlags.isPostAllowed ? YES : NO; -} - -- (BOOL)isCreateAllowedInACL { - /* we call this directly from UIxMailAccountView */ - [self _loadACLPermissionFlags]; - return self->somfFlags.isCreateAllowed ? YES : NO; -} -- (BOOL)isCreateAllowed { - if (useAltNamespace) { - /* with altnamespace, Cyrus doesn't allow mailboxes under INBOX */ - if ([[self outlookFolderClass] isEqualToString:@"IPF.Inbox"]) - return NO; - } - return [self isCreateAllowedInACL]; -} - -- (BOOL)hasAdminAccess { - [self _loadACLPermissionFlags]; - return self->somfFlags.hasAdminAccess ? YES : NO; -} - /* messages */ - (NSArray *)fetchUIDsMatchingQualifier:(id)_q sortOrdering:(id)_so { @@ -369,22 +302,181 @@ static BOOL useAltNamespace = NO; SOGoMailAccount *account; NSString *n; - if (self->folderType != nil) - return self->folderType; + if (folderType != nil) + return folderType; account = [self mailAccountFolder]; n = [self nameInContainer]; if ([n isEqualToString:[account trashFolderNameInContext:nil]]) - self->folderType = @"IPF.Trash"; + folderType = @"IPF.Trash"; else if ([n isEqualToString:[account inboxFolderNameInContext:nil]]) - self->folderType = @"IPF.Inbox"; + folderType = @"IPF.Inbox"; else if ([n isEqualToString:[account sentFolderNameInContext:nil]]) - self->folderType = @"IPF.Sent"; + folderType = @"IPF.Sent"; else - self->folderType = @"IPF.Folder"; + folderType = @"IPF.Folder"; - return self->folderType; + return folderType; +} + +/* acls */ + +- (NSArray *) _imapAclsToSOGoAcls: (NSString *) imapAcls +{ + unsigned int count, max; + NSMutableArray *SOGoAcls; + + SOGoAcls = [NSMutableArray array]; + max = [imapAcls length]; + for (count = 0; count < max; count++) + { + switch ([imapAcls characterAtIndex: count]) + { + case 'l': + [SOGoAcls addObjectUniquely: SOGoRole_ObjectViewer]; + break; + case 'r': + [SOGoAcls addObjectUniquely: SOGoRole_ObjectReader]; + break; + case 's': + [SOGoAcls addObjectUniquely: SOGoMailRole_SeenKeeper]; + break; + case 'w': + [SOGoAcls addObjectUniquely: SOGoMailRole_Writer]; + break; + case 'i': + [SOGoAcls addObjectUniquely: SOGoRole_ObjectCreator]; + break; + case 'p': + [SOGoAcls addObjectUniquely: SOGoMailRole_Poster]; + break; + case 'k': + [SOGoAcls addObjectUniquely: SOGoRole_FolderCreator]; + break; + case 'x': + [SOGoAcls addObjectUniquely: SOGoRole_ObjectEraser]; + break; + case 't': + [SOGoAcls addObjectUniquely: SOGoMailRole_MessageEraser]; + break; + case 'e': + [SOGoAcls addObjectUniquely: SOGoMailRole_Expunger]; + break; + case 'a': + [SOGoAcls addObjectUniquely: SOGoMailRole_Administrator]; + break; + } + } + + return SOGoAcls; +} + +- (NSString *) _sogoAclsToImapAcls: (NSArray *) sogoAcls +{ + NSMutableString *imapAcls; + NSEnumerator *acls; + NSString *currentAcl; + char character; + + imapAcls = [NSMutableString string]; + acls = [sogoAcls objectEnumerator]; + currentAcl = [acls nextObject]; + while (currentAcl) + { + if ([currentAcl isEqualToString: SOGoRole_ObjectViewer]) + character = 'l'; + else if ([currentAcl isEqualToString: SOGoRole_ObjectReader]) + character = 'r'; + else if ([currentAcl isEqualToString: SOGoMailRole_SeenKeeper]) + character = 's'; + else if ([currentAcl isEqualToString: SOGoMailRole_Writer]) + character = 'w'; + else if ([currentAcl isEqualToString: SOGoRole_ObjectCreator]) + character = 'i'; + else if ([currentAcl isEqualToString: SOGoMailRole_Poster]) + character = 'p'; + else if ([currentAcl isEqualToString: SOGoRole_FolderCreator]) + character = 'k'; + else if ([currentAcl isEqualToString: SOGoRole_ObjectEraser]) + character = 'x'; + else if ([currentAcl isEqualToString: SOGoMailRole_MessageEraser]) + character = 't'; + else if ([currentAcl isEqualToString: SOGoMailRole_Expunger]) + character = 'e'; + else if ([currentAcl isEqualToString: SOGoMailRole_Administrator]) + character = 'a'; + else + character = 0; + + if (character) + [imapAcls appendFormat: @"%c", character]; + + currentAcl = [acls nextObject]; + } + + return imapAcls; +} + +- (NSArray *) aclUsers +{ + NSDictionary *imapAcls; + + imapAcls = [imap4 aclForMailboxAtURL: [self imap4URL]]; + + return [imapAcls allKeys]; +} + +- (NSArray *) aclsForUser: (NSString *) uid +{ + NSDictionary *imapAcls; + NSString *userAcls; + + imapAcls = [imap4 aclForMailboxAtURL: [self imap4URL]]; + userAcls = [imapAcls objectForKey: uid]; + if (!([userAcls length] || [uid isEqualToString: defaultUserID])) + userAcls = [imapAcls objectForKey: defaultUserID]; + + return [self _imapAclsToSOGoAcls: userAcls]; +} + +- (void) removeAclsForUsers: (NSArray *) users +{ + NSEnumerator *uids; + NSString *currentUID; + NSString *folderName; + NGImap4Client *client; + + folderName = [imap4 imap4FolderNameForURL: [self imap4URL]]; + client = [imap4 client]; + + uids = [users objectEnumerator]; + currentUID = [uids nextObject]; + while (currentUID) + { + [client deleteACL: folderName uid: currentUID]; + currentUID = [uids nextObject]; + } +} + +- (void) setRoles: (NSArray *) roles + forUser: (NSString *) uid +{ + NSString *acls, *folderName; + + acls = [self _sogoAclsToImapAcls: roles]; + folderName = [imap4 imap4FolderNameForURL: [self imap4URL]]; + [[imap4 client] setACL: folderName rights: acls uid: uid]; +} + +- (NSString *) defaultUserID +{ + return defaultUserID; +} + +- (BOOL) hasSupportForDefaultRoles +{ + return YES; } @end /* SOGoMailFolder */ diff --git a/SoObjects/Mailer/SOGoMailObject.m b/SoObjects/Mailer/SOGoMailObject.m index 749882e16..68ec6326a 100644 --- a/SoObjects/Mailer/SOGoMailObject.m +++ b/SoObjects/Mailer/SOGoMailObject.m @@ -19,15 +19,35 @@ 02111-1307, USA. */ -#include "SOGoMailObject.h" -#include "SOGoMailFolder.h" -#include "SOGoMailAccount.h" -#include "SOGoMailManager.h" -#include "SOGoMailBodyPart.h" -#include -#include -#include -#include "common.h" +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import "SOGoMailFolder.h" +#import "SOGoMailAccount.h" +#import "SOGoMailManager.h" +#import "SOGoMailBodyPart.h" + +#import "SOGoMailObject.h" @implementation SOGoMailObject @@ -639,8 +659,15 @@ static BOOL debugSoParts = NO; /* permissions */ -- (BOOL)isDeletionAllowed { - return [[self container] isDeleteAndExpungeAllowed]; +- (BOOL) isDeletionAllowed +{ + NSArray *parentAcl; + NSString *login; + + login = [[context activeUser] login]; + parentAcl = [[self container] aclsForUser: login]; + + return [parentAcl containsObject: SOGoMailRole_MessageEraser]; } /* name lookup */ diff --git a/SoObjects/SOGo/NSArray+Utilities.h b/SoObjects/SOGo/NSArray+Utilities.h index 15cbb174b..2617538d3 100644 --- a/SoObjects/SOGo/NSArray+Utilities.h +++ b/SoObjects/SOGo/NSArray+Utilities.h @@ -39,4 +39,10 @@ @end +@interface NSMutableArray (SOGoArrayUtilities) + +- (void) addObjectUniquely: (id) object; + +@end + #endif /* NSARRAY_UTILITIES_H */ diff --git a/SoObjects/SOGo/NSArray+Utilities.m b/SoObjects/SOGo/NSArray+Utilities.m index ed30b5e5a..75dec348c 100644 --- a/SoObjects/SOGo/NSArray+Utilities.m +++ b/SoObjects/SOGo/NSArray+Utilities.m @@ -59,3 +59,14 @@ } @end + +@implementation NSMutableArray (SOGoArrayUtilities) + +- (void) addObjectUniquely: (id) object +{ + if (![self containsObject: object]) + [self addObject: object]; +} + +@end + diff --git a/SoObjects/SOGo/SOGoContentObject.m b/SoObjects/SOGo/SOGoContentObject.m index ed75b3ce3..e2b11a44e 100644 --- a/SoObjects/SOGo/SOGoContentObject.m +++ b/SoObjects/SOGo/SOGoContentObject.m @@ -218,9 +218,9 @@ : 0 /* 0 means 'do not check' */; /* attempt a save */ - - if ((error = [self saveContentString:[rq contentAsString] - baseVersion:baseVersion]) != nil) + + if ((error = [self saveContentString: [rq contentAsString] + baseVersion: baseVersion]) != nil) return error; /* setup response */ @@ -303,9 +303,9 @@ /* acls */ -- (NSArray *) acls +- (NSArray *) aclUsers { - return [container aclsForObjectAtPath: [self pathArrayToSoObject]]; + return [container aclUsersForObjectAtPath: [self pathArrayToSoObject]]; } - (NSArray *) aclsForUser: (NSString *) uid @@ -343,6 +343,16 @@ forObjectAtPath: [self pathArrayToSoObject]]; } +- (NSString *) defaultUserID +{ + return @""; +} + +- (BOOL) hasSupportForDefaultRoles +{ + return YES; +} + /* message type */ - (NSString *) outlookMessageClass diff --git a/SoObjects/SOGo/SOGoFolder.h b/SoObjects/SOGo/SOGoFolder.h index b5527d498..a6aaf18d6 100644 --- a/SoObjects/SOGo/SOGoFolder.h +++ b/SoObjects/SOGo/SOGoFolder.h @@ -72,7 +72,7 @@ - (NSException *) delete; /* acls as a container */ -- (NSArray *) aclsForObjectAtPath: (NSArray *) objectPathArray; +- (NSArray *) aclUsersForObjectAtPath: (NSArray *) objectPathArray; - (NSArray *) aclsForUser: (NSString *) uid forObjectAtPath: (NSArray *) objectPathArray; - (void) setRoles: (NSArray *) roles diff --git a/SoObjects/SOGo/SOGoFolder.m b/SoObjects/SOGo/SOGoFolder.m index a55c3dad2..2e3b7469f 100644 --- a/SoObjects/SOGo/SOGoFolder.m +++ b/SoObjects/SOGo/SOGoFolder.m @@ -31,6 +31,8 @@ #import #import +static NSString *defaultUserID = @""; + @implementation SOGoFolder + (int) version @@ -266,16 +268,18 @@ /* acls as a container */ -- (NSArray *) aclsForObjectAtPath: (NSArray *) objectPathArray; +- (NSArray *) aclUsersForObjectAtPath: (NSArray *) objectPathArray; { EOQualifier *qualifier; NSString *qs; + NSArray *records; qs = [NSString stringWithFormat: @"c_object = '/%@'", [objectPathArray componentsJoinedByString: @"/"]]; qualifier = [EOQualifier qualifierWithQualifierFormat: qs]; + records = [[self ocsFolder] fetchAclMatchingQualifier: qualifier]; - return [[self ocsFolder] fetchAclMatchingQualifier: qualifier]; + return [records valueForKey: @"c_uid"]; } - (NSArray *) _fetchAclsForUser: (NSString *) uid @@ -339,8 +343,8 @@ [self _cacheRoles: acls forUser: uid forObjectAtPath: objectPath]; } - if (!([acls count] || [uid isEqualToString: SOGoDefaultUserID])) - acls = [self aclsForUser: SOGoDefaultUserID + if (!([acls count] || [uid isEqualToString: defaultUserID])) + acls = [self aclsForUser: defaultUserID forObjectAtPath: objectPathArray]; return acls; @@ -418,15 +422,9 @@ } /* acls */ -- (NSArray *) defaultAclRoles +- (NSArray *) aclUsers { -#warning this should be changed to something useful - return nil; -} - -- (NSArray *) acls -{ - return [self aclsForObjectAtPath: [self pathArrayToSoObject]]; + return [self aclUsersForObjectAtPath: [self pathArrayToSoObject]]; } - (NSArray *) aclsForUser: (NSString *) uid @@ -449,6 +447,16 @@ forObjectAtPath: [self pathArrayToSoObject]]; } +- (NSString *) defaultUserID +{ + return defaultUserID; +} + +- (BOOL) hasSupportForDefaultRoles +{ + return YES; +} + /* WebDAV */ - (BOOL) davIsCollection diff --git a/SoObjects/SOGo/SOGoObject.h b/SoObjects/SOGo/SOGoObject.h index e5a77e739..b265699ef 100644 --- a/SoObjects/SOGo/SOGoObject.h +++ b/SoObjects/SOGo/SOGoObject.h @@ -52,8 +52,6 @@ #define $(class) NSClassFromString(class) -extern NSString *SOGoDefaultUserID; - @interface SOGoObject : NSObject { WOContext *context; @@ -100,12 +98,13 @@ extern NSString *SOGoDefaultUserID; /* acls */ -- (NSArray *) defaultAclRoles; -- (NSArray *) acls; +- (NSArray *) aclUsers; - (NSArray *) aclsForUser: (NSString *) uid; - (void) setRoles: (NSArray *) roles forUser: (NSString *) uid; - (void) removeAclsForUsers: (NSArray *) users; +- (NSString *) defaultUserID; +- (BOOL) hasSupportForDefaultRoles; /* description */ diff --git a/SoObjects/SOGo/SOGoObject.m b/SoObjects/SOGo/SOGoObject.m index 57b13cd78..5ca5809f7 100644 --- a/SoObjects/SOGo/SOGoObject.m +++ b/SoObjects/SOGo/SOGoObject.m @@ -47,8 +47,6 @@ #import "SOGoObject.h" -NSString *SOGoDefaultUserID = @""; - @interface SOGoObject(Content) - (NSString *)contentAsString; @end @@ -354,23 +352,23 @@ static BOOL kontactGroupDAV = YES; - (SOGoDAVSet *) davAcl { - NSArray *role; - NSEnumerator *acls; + NSArray *roles; + NSEnumerator *uids; NSMutableDictionary *aclsDictionary; - NSDictionary *currentAcl; + NSString *currentUID; SoClassSecurityInfo *sInfo; - acls = [[self acls] objectEnumerator]; aclsDictionary = [NSMutableDictionary dictionary]; + uids = [[self aclUsers] objectEnumerator]; sInfo = [[self class] soClassSecurityInfo]; - currentAcl = [acls nextObject]; - while (currentAcl) + currentUID = [uids nextObject]; + while (currentUID) { - role = [NSArray arrayWithObject: [currentAcl objectForKey: @"role"]]; - [aclsDictionary setObject: [sInfo DAVPermissionsForRoles: role] - forKey: [currentAcl objectForKey: @"uid"]]; - currentAcl = [acls nextObject]; + roles = [self aclsForUser: currentUID]; + [aclsDictionary setObject: [sInfo DAVPermissionsForRoles: roles] + forKey: currentUID]; + currentUID = [uids nextObject]; } [self _appendRolesForPseudoPrincipals: aclsDictionary withClassSecurityInfo: sInfo]; @@ -707,7 +705,7 @@ static BOOL kontactGroupDAV = YES; /* acls */ -- (NSArray *) acls +- (NSArray *) aclUsers { [self subclassResponsibility: _cmd]; @@ -721,13 +719,6 @@ static BOOL kontactGroupDAV = YES; return nil; } -- (NSArray *) defaultAclRoles -{ - [self subclassResponsibility: _cmd]; - - return nil; -} - - (void) setRoles: (NSArray *) roles forUser: (NSString *) uid { @@ -739,6 +730,18 @@ static BOOL kontactGroupDAV = YES; [self subclassResponsibility: _cmd]; } +- (NSString *) defaultUserID +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + +- (BOOL) hasSupportForDefaultRoles +{ + return NO; +} + /* description */ - (void)appendAttributesToDescription:(NSMutableString *)_ms { diff --git a/SoObjects/SOGo/SOGoPermissions.h b/SoObjects/SOGo/SOGoPermissions.h index 67ee64bee..2b4e60cf5 100644 --- a/SoObjects/SOGo/SOGoPermissions.h +++ b/SoObjects/SOGo/SOGoPermissions.h @@ -28,17 +28,25 @@ #import extern NSString *SOGoRole_ObjectCreator; +extern NSString *SOGoRole_ObjectReader; extern NSString *SOGoRole_ObjectEraser; extern NSString *SOGoRole_ObjectViewer; extern NSString *SOGoRole_ObjectEditor; + +extern NSString *SOGoRole_FolderCreator; +extern NSString *SOGoRole_FolderReader; extern NSString *SOGoRole_AuthorizedSubscriber; extern NSString *SOGoRole_None; - extern NSString *SOGoRole_FreeBusy; extern NSString *SOGoRole_FreeBusyLookup; -extern NSString *SOGoPerm_ReadAcls; -extern NSString *SOGoPerm_FreeBusyLookup; +extern NSString *SOGoMailRole_SeenKeeper; +extern NSString *SOGoMailRole_Writer; +extern NSString *SOGoMailRole_Poster; +extern NSString *SOGoMailRole_Expunger; +extern NSString *SOGoMailRole_Creator; +extern NSString *SOGoMailRole_Administrator; +extern NSString *SOGoMailRole_MessageEraser; extern NSString *SOGoCalendarRole_Organizer; extern NSString *SOGoCalendarRole_Participant; @@ -61,6 +69,9 @@ extern NSString *SOGoCalendarRole_ComponentDAndTViewer; extern NSString *SOGoCalendarRole_ComponentModifier; extern NSString *SOGoCalendarRole_ComponentResponder; +extern NSString *SOGoPerm_ReadAcls; +extern NSString *SOGoPerm_FreeBusyLookup; + extern NSString *SOGoCalendarPerm_ViewWholePublicRecords; extern NSString *SOGoCalendarPerm_ViewDAndTOfPublicRecords; extern NSString *SOGoCalendarPerm_ModifyPublicRecords; diff --git a/SoObjects/SOGo/SOGoPermissions.m b/SoObjects/SOGo/SOGoPermissions.m index e750ef31b..f5cb1f172 100644 --- a/SoObjects/SOGo/SOGoPermissions.m +++ b/SoObjects/SOGo/SOGoPermissions.m @@ -26,7 +26,12 @@ NSString *SOGoRole_ObjectCreator = @"ObjectCreator"; NSString *SOGoRole_ObjectEraser = @"ObjectEraser"; NSString *SOGoRole_ObjectViewer = @"ObjectViewer"; +NSString *SOGoRole_ObjectReader = @"ObjectReader"; NSString *SOGoRole_ObjectEditor = @"ObjectEditor"; +NSString *SOGoRole_FolderCreator = @"FolderCreator"; +NSString *SOGoRole_FolderEraser = @"FolderEraser"; +NSString *SOGoRole_FolderViewer = @"FolderViewer"; +NSString *SOGoRole_FolderReader = @"FolderReader"; NSString *SOGoRole_AuthorizedSubscriber = @"AuthorizedSubscriber"; NSString *SOGoRole_None = @"None"; @@ -60,6 +65,13 @@ NSString *SOGoCalendarRole_ComponentDAndTViewer = @"ComponentDAndTViewer"; NSString *SOGoCalendarRole_ComponentModifier = @"ComponentModifier"; NSString *SOGoCalendarRole_ComponentResponder = @"ComponentResponder"; +NSString *SOGoMailRole_SeenKeeper = @"MailSeenKeeper"; +NSString *SOGoMailRole_Writer = @"MailWriter"; +NSString *SOGoMailRole_Poster = @"MailPoster"; +NSString *SOGoMailRole_Expunger = @"MailExpunger"; +NSString *SOGoMailRole_Administrator = @"MailAdministrator"; +NSString *SOGoMailRole_MessageEraser = @"MailMessageEraser"; + /* permissions */ NSString *SOGoPerm_ReadAcls = @"ReadAcls"; /* the equivalent of "read-acl" in the WebDAV acls spec, which is @@ -83,3 +95,4 @@ NSString *SOGoCalendarPerm_ViewAllComponent = @"ViewAllComponent"; NSString *SOGoCalendarPerm_ViewDAndT = @"ViewDAndT"; NSString *SOGoCalendarPerm_ModifyComponent = @"ModifyComponent"; NSString *SOGoCalendarPerm_RespondToComponent = @"RespondToComponent"; + diff --git a/UI/Common/UIxAclEditor.h b/UI/Common/UIxAclEditor.h index e4d0b1d35..f8104ceed 100644 --- a/UI/Common/UIxAclEditor.h +++ b/UI/Common/UIxAclEditor.h @@ -29,10 +29,11 @@ { BOOL prepared; BOOL publishInFreeBusy; - NSArray *acls; + NSArray *aclUsers; NSArray *savedUIDs; NSMutableArray *users; NSString *currentUser; + NSString *defaultUserID; } - (NSArray *) aclsForObject; diff --git a/UI/Common/UIxAclEditor.m b/UI/Common/UIxAclEditor.m index e0328ace9..e6dccdfe0 100644 --- a/UI/Common/UIxAclEditor.m +++ b/UI/Common/UIxAclEditor.m @@ -29,6 +29,7 @@ #import #import #import +#import #import "UIxAclEditor.h" @@ -38,11 +39,12 @@ { if ((self = [super init])) { - acls = nil; + aclUsers = nil; prepared = NO; publishInFreeBusy = NO; users = [NSMutableArray new]; currentUser = nil; + defaultUserID = nil; savedUIDs = nil; } @@ -54,15 +56,16 @@ [savedUIDs release]; [users release]; [currentUser release]; + [defaultUserID release]; [super dealloc]; } - (NSArray *) aclsForObject { - if (!acls) - acls = [[self clientObject] acls]; + if (!aclUsers) + aclUsers = [[self clientObject] aclUsers]; - return acls; + return aclUsers; } - (NSString *) _displayNameForUID: (NSString *) uid @@ -86,30 +89,32 @@ - (NSString *) defaultUserID { - return SOGoDefaultUserID; + if (!defaultUserID) + ASSIGN (defaultUserID, [[self clientObject] defaultUserID]); + + return defaultUserID; } - (void) _prepareUsers { NSEnumerator *aclsEnum; - NSDictionary *currentAcl; NSString *currentUID, *ownerLogin; ownerLogin = [[self clientObject] ownerInContext: context]; + if (!defaultUserID) + ASSIGN (defaultUserID, [[self clientObject] defaultUserID]); aclsEnum = [[self aclsForObject] objectEnumerator]; - currentAcl = [aclsEnum nextObject]; - while (currentAcl) + currentUID = [aclsEnum nextObject]; + while (currentUID) { - currentUID = [currentAcl objectForKey: @"c_uid"]; if (!([currentUID isEqualToString: ownerLogin] - || [currentUID isEqualToString: SOGoDefaultUserID] - || [users containsObject: currentUID])) - [users addObject: currentUID]; - currentAcl = [aclsEnum nextObject]; - - prepared = YES; + || [currentUID isEqualToString: defaultUserID])) + [users addObjectUniquely: currentUID]; + currentUID = [aclsEnum nextObject]; } + + prepared = YES; } - (NSArray *) usersForObject diff --git a/UI/Common/UIxUserRightsEditor.h b/UI/Common/UIxUserRightsEditor.h index 35cfe1568..0bef18e57 100644 --- a/UI/Common/UIxUserRightsEditor.h +++ b/UI/Common/UIxUserRightsEditor.h @@ -34,6 +34,7 @@ { NSMutableArray *userRights; NSString *uid; + NSString *defaultUserID; } - (NSString *) userDisplayName; diff --git a/UI/Common/UIxUserRightsEditor.m b/UI/Common/UIxUserRightsEditor.m index 8ec44dd46..ad674f63e 100644 --- a/UI/Common/UIxUserRightsEditor.m +++ b/UI/Common/UIxUserRightsEditor.m @@ -25,6 +25,7 @@ #import #import #import +#import #import "UIxUserRightsEditor.h" @@ -36,6 +37,7 @@ { uid = nil; userRights = [NSMutableArray new]; + defaultUserID = nil; } return self; @@ -45,6 +47,7 @@ { [uid release]; [userRights release]; + [defaultUserID release]; [super dealloc]; } @@ -55,7 +58,10 @@ - (BOOL) userIsDefaultUser { - return [uid isEqualToString: SOGoDefaultUserID]; + if (!defaultUserID) + ASSIGN (defaultUserID, [[self clientObject] defaultUserID]); + + return [uid isEqualToString: defaultUserID]; } - (NSString *) userDisplayName @@ -75,24 +81,22 @@ NSString *newUID; LDAPUserManager *um; SOGoObject *clientObject; - unsigned int count; response = NO; newUID = [[context request] formValueForKey: @"uid"]; if ([newUID length] > 0) { + if (!defaultUserID) + ASSIGN (defaultUserID, [[self clientObject] defaultUserID]); + um = [LDAPUserManager sharedUserManager]; - if ([newUID isEqualToString: SOGoDefaultUserID] + if ([newUID isEqualToString: defaultUserID] || [[um getEmailForUID: newUID] length] > 0) { ASSIGN (uid, newUID); clientObject = [self clientObject]; [userRights addObjectsFromArray: [clientObject aclsForUser: uid]]; - count = [userRights count]; - if (!count || (count == 1 && [[userRights objectAtIndex: 0] - isEqualToString: SOGoRole_None])) - [userRights setArray: [clientObject defaultAclRoles]]; response = YES; } diff --git a/UI/Contacts/English.lproj/Localizable.strings b/UI/Contacts/English.lproj/Localizable.strings index cca322a0b..16704ace6 100644 --- a/UI/Contacts/English.lproj/Localizable.strings +++ b/UI/Contacts/English.lproj/Localizable.strings @@ -43,7 +43,7 @@ "New Card" = "New Card"; "New List" = "New List"; "Modify" = "Modify"; -"Access Rights..." = "Access Rights..."; +"Sharing..." = "Sharing..."; "Write" = "Write"; "Delete" = "Delete"; "Instant Message" = "Instant Message"; diff --git a/UI/Contacts/French.lproj/Localizable.strings b/UI/Contacts/French.lproj/Localizable.strings index aaf6e2075..0d73332ed 100644 --- a/UI/Contacts/French.lproj/Localizable.strings +++ b/UI/Contacts/French.lproj/Localizable.strings @@ -50,7 +50,7 @@ "New Card" = "Nouvelle fiche"; "New List" = "Nouvelle liste"; "Modify" = "Modifier"; -"Access Rights..." = "Partage..."; +"Sharing..." = "Partage..."; "Write" = "Écrire"; "Delete" = "Effacer"; "Instant Message" = "Message instantané"; diff --git a/UI/MailPartViewers/UIxMailPartTextViewer.m b/UI/MailPartViewers/UIxMailPartTextViewer.m index ae25992ef..e6d7e66a2 100644 --- a/UI/MailPartViewers/UIxMailPartTextViewer.m +++ b/UI/MailPartViewers/UIxMailPartTextViewer.m @@ -39,9 +39,7 @@ - (NSString *) flatContentAsString { NSMutableString *content; - NSString *superContent, *urlText, *newUrlText; - NSRange httpRange, rest, currentURL; - unsigned int length; + NSString *superContent; content = [NSMutableString string]; superContent = [[super flatContentAsString] stringByEscapingHTMLString]; diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings index 49ea90505..b7c739f71 100644 --- a/UI/MailerUI/English.lproj/Localizable.strings +++ b/UI/MailerUI/English.lproj/Localizable.strings @@ -35,6 +35,24 @@ "Account: " = "Account: "; "Shared Account: " = "Shared Account: "; +/* acls */ +"Default Roles" = "Default Roles"; + +"List and see this folder" = "List and see this folder"; +"Read mails from this folder" = "Read mails from this folder"; +"Mark mails read and unread" = "Mark mails read and unread"; +"Modify the flags of the mails in this folder" = "Modify the flags of the mails in this folder"; +"Insert, copy and move mails into this folder" = "Insert, copy and move mails into this folder"; +"Post mails" = "Post mails"; +"Add subfolders to this folder" = "Add subfolders to this folder"; +"Remove this folder" = "Remove this folder"; +"Erase mails from this folder" = "Erase mails from this folder"; +"Expunge this folder" = "Expunge this folder"; +"Modify the acl of this folder" = "Modify the acl of this folder"; + +"Update" = "Update"; +"Cancel" = "Cancel"; + /* Mail edition */ "From" = "From"; diff --git a/UI/MailerUI/French.lproj/Localizable.strings b/UI/MailerUI/French.lproj/Localizable.strings index 6ba4a8d3e..f313571c3 100644 --- a/UI/MailerUI/French.lproj/Localizable.strings +++ b/UI/MailerUI/French.lproj/Localizable.strings @@ -34,6 +34,24 @@ "Account: " = "Compte : "; "Shared Account: " = "Compte Partagé "; +/* acls */ +"Default Roles" = "Rôles par défaut"; + +"List and see this folder" = "Lister et voir ce dossier"; +"Read mails from this folder" = "Lire les messages de ce dossier"; +"Mark mails read and unread" = "Marquer les messages comme lus ou non-lus"; +"Modify the flags of the mails in this folder" = "Modifier les indicateurs sur les messages"; +"Insert, copy and move mails into this folder" = "Insérer, copier et déplacer des messages dans ce dossier"; +"Post mails" = "Poster des messages"; +"Add subfolders to this folder" = "Ajouter des sous-dossiers à ce dossier"; +"Remove this folder" = "Effacer ce dossier"; +"Erase mails from this folder" = "Effacer des messages de ce dossier"; +"Expunge this folder" = "Compacter ce dossier"; +"Modify the acl of this folder" = "Administrer les droits sur ce dossier"; + +"Update" = "Mettre à jour"; +"Cancel" = "Annuler"; + /* Mail edition */ "From" = "De"; @@ -106,7 +124,7 @@ "New Folder..." = "Nouveau dossier..."; "Compact This Folder" = "Compacter ce dossier"; "Search Messages..." = "Rechercher dans les messages..."; -"Properties..." = "Propriétés"; +"Sharing..." = "Partage..."; "New Subfolder..." = "Nouveau sous-dossier..."; "Rename Folder..." = "Renommer le dossier..."; "Delete Folder" = "Supprimer le dossier..."; diff --git a/UI/MailerUI/GNUmakefile b/UI/MailerUI/GNUmakefile index 8b3f2108d..c917d42c5 100644 --- a/UI/MailerUI/GNUmakefile +++ b/UI/MailerUI/GNUmakefile @@ -21,7 +21,6 @@ MailerUI_OBJC_FILES += \ UIxMailTreeBlock.m \ UIxMailTreeBlockJS.m \ UIxMailFolderMenu.m \ - UIxMailSplashView.m \ \ UIxMailListView.m \ UIxMailView.m \ @@ -39,7 +38,7 @@ MailerUI_OBJC_FILES += \ \ UIxFilterList.m \ \ - UIxMailFolderACLEditor.m + UIxMailUserRightsEditor.m # UIxSieveEditor.m MailerUI_RESOURCE_FILES += \ diff --git a/UI/MailerUI/MailerUIProduct.m b/UI/MailerUI/MailerUIProduct.m index 05c33d988..031a7dd78 100644 --- a/UI/MailerUI/MailerUIProduct.m +++ b/UI/MailerUI/MailerUIProduct.m @@ -18,7 +18,6 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// $Id: MailerUIProduct.m 603 2005-02-22 23:12:45Z helge $ #import @@ -28,7 +27,5 @@ @end -#include "common.h" - @implementation MailerUIProduct @end /* MailerUIProduct */ diff --git a/UI/MailerUI/UIxMailFolderACLEditor.m b/UI/MailerUI/UIxMailFolderACLEditor.m deleted file mode 100644 index 9606edb1c..000000000 --- a/UI/MailerUI/UIxMailFolderACLEditor.m +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2005 SKYRIX Software AG - - This file is part of OpenGroupware.org. - - OGo is free software; you can redistribute it and/or modify it under - the terms of the GNU Lesser General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - OGo is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with OGo; see the file COPYING. If not, write to the - Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. -*/ - -#include - -// TODO: implement - -/* - UIxMailFolderACLEditor - - A component to edit IMAP4 ACLs on folders. It works on SOGoMailFolder - objects. -*/ - -@interface UIxMailFolderACLEditor : UIxComponent -{ -} - -@end - -#include "common.h" - -@implementation UIxMailFolderACLEditor -@end /* UIxMailFolderACLEditor */ diff --git a/UI/MailerUI/UIxMailSplashView.m b/UI/MailerUI/UIxMailSplashView.m deleted file mode 100644 index 628011889..000000000 --- a/UI/MailerUI/UIxMailSplashView.m +++ /dev/null @@ -1,29 +0,0 @@ -/* UIxMailSplashView - this file is part of SOGo - * - * Copyright (C) 2006 Inverse groupe conseil - * - * Author: Wolfgang Sourdeau - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#import - -@interface UIxMailSplashView : UIxComponent -@end - -@implementation UIxMailSplashView -@end /* UIxMailSplashView */ diff --git a/UI/MailerUI/UIxMailUserRightsEditor.h b/UI/MailerUI/UIxMailUserRightsEditor.h new file mode 100644 index 000000000..289c95c93 --- /dev/null +++ b/UI/MailerUI/UIxMailUserRightsEditor.h @@ -0,0 +1,58 @@ +/* UIxMailUserRightsEditor.h - this file is part of SOGo + * + * Copyright (C) 2007 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef UIXMAILUSERRIGHTSEDITOR_H +#define UIXMAILUSERRIGHTSEDITOR_H + +#import + +@interface UIxMailUserRightsEditor : UIxUserRightsEditor + +- (void) setUserCanReadMails: (BOOL) userCanReadMails; +- (BOOL) userCanReadMails; + +- (void) setUserCanWriteMails: (BOOL) userCanWriteMails; +- (BOOL) userCanWriteMails; + +- (void) setUserCanInsertMails: (BOOL) userCanInsertMails; +- (BOOL) userCanInsertMails; + +- (void) setUserCanMarkMailsRead: (BOOL) userCanMarkMailsRead; +- (BOOL) userCanMarkMailsRead; + +- (void) setUserCanEraseMails: (BOOL) userCanEraseMails; +- (BOOL) userCanEraseMails; + +- (void) setUserCanCreateSubfolders: (BOOL) userCanCreateSubfolders; +- (BOOL) userCanCreateSubfolders; + +- (void) setUserCanPostMails: (BOOL) userCanPostMails; +- (BOOL) userCanPostMails; + +- (void) setUserIsAdministrator: (BOOL) userIsAdministrator; +- (BOOL) userIsAdministrator; + +- (void) updateRights; + +@end + +#endif /* UIXMAILUSERRIGHTSEDITOR_H */ diff --git a/UI/MailerUI/UIxMailUserRightsEditor.m b/UI/MailerUI/UIxMailUserRightsEditor.m new file mode 100644 index 000000000..2478b5c5a --- /dev/null +++ b/UI/MailerUI/UIxMailUserRightsEditor.m @@ -0,0 +1,238 @@ +/* UIxMailUserRightsEditor.m - this file is part of SOGo + * + * Copyright (C) 2007 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import +#import +#import + +#import "UIxMailUserRightsEditor.h" + +@implementation UIxMailUserRightsEditor + +- (void) setUserCanSeeFolder: (BOOL) userCanSeeFolder +{ + if (userCanSeeFolder) + [self appendRight: SOGoRole_ObjectViewer]; + else + [self removeRight: SOGoRole_ObjectViewer]; +} + +- (BOOL) userCanSeeFolder +{ + return [userRights containsObject: SOGoRole_ObjectViewer]; +} + +- (void) setUserCanReadMails: (BOOL) userCanReadMails +{ + if (userCanReadMails) + [self appendRight: SOGoRole_ObjectReader]; + else + [self removeRight: SOGoRole_ObjectReader]; +} + +- (BOOL) userCanReadMails +{ + return [userRights containsObject: SOGoRole_ObjectReader]; +} + +- (void) setUserCanMarkMailsRead: (BOOL) userCanMarkMailsRead +{ + if (userCanMarkMailsRead) + [self appendRight: SOGoMailRole_SeenKeeper]; + else + [self removeRight: SOGoMailRole_SeenKeeper]; +} + +- (BOOL) userCanMarkMailsRead +{ + return [userRights containsObject: SOGoMailRole_SeenKeeper]; +} + +- (void) setUserCanWriteMails: (BOOL) userCanWriteMails +{ + if (userCanWriteMails) + [self appendRight: SOGoMailRole_Writer]; + else + [self removeRight: SOGoMailRole_Writer]; +} + +- (BOOL) userCanWriteMails +{ + return [userRights containsObject: SOGoMailRole_Writer]; +} + +- (void) setUserCanInsertMails: (BOOL) userCanInsertMails +{ + if (userCanInsertMails) + [self appendRight: SOGoRole_ObjectCreator]; + else + [self removeRight: SOGoRole_ObjectCreator]; +} + +- (BOOL) userCanInsertMails +{ + return [userRights containsObject: SOGoRole_ObjectCreator]; +} + +- (void) setUserCanPostMails: (BOOL) userCanPostMails +{ + if (userCanPostMails) + [self appendRight: SOGoMailRole_Poster]; + else + [self removeRight: SOGoMailRole_Poster]; +} + +- (BOOL) userCanPostMails +{ + return [userRights containsObject: SOGoMailRole_Poster]; +} + +- (void) setUserCanCreateSubfolders: (BOOL) userCanCreateSubfolders +{ + if (userCanCreateSubfolders) + [self appendRight: SOGoRole_FolderCreator]; + else + [self removeRight: SOGoRole_FolderCreator]; +} + +- (BOOL) userCanCreateSubfolders +{ + return [userRights containsObject: SOGoRole_FolderCreator]; +} + +- (void) setUserCanRemoveFolder: (BOOL) userCanRemoveFolder +{ + if (userCanRemoveFolder) + [self appendRight: SOGoRole_ObjectEraser]; + else + [self removeRight: SOGoRole_ObjectEraser]; +} + +- (BOOL) userCanRemoveFolder +{ + return [userRights containsObject: SOGoRole_ObjectEraser]; +} + +- (void) setUserCanEraseMails: (BOOL) userCanEraseMails +{ + if (userCanEraseMails) + [self appendRight: SOGoMailRole_MessageEraser]; + else + [self removeRight: SOGoMailRole_MessageEraser]; +} + +- (BOOL) userCanEraseMails +{ + return [userRights containsObject: SOGoMailRole_MessageEraser]; +} + +- (void) setUserCanExpungeFolder: (BOOL) userCanExpungeFolder +{ + if (userCanExpungeFolder) + [self appendRight: SOGoMailRole_Expunger]; + else + [self removeRight: SOGoMailRole_Expunger]; +} + +- (BOOL) userCanExpungeFolder +{ + return [userRights containsObject: SOGoMailRole_Expunger]; +} + +- (void) setUserIsAdministrator: (BOOL) userIsAdministrator +{ + if (userIsAdministrator) + [self appendRight: SOGoMailRole_Administrator]; + else + [self removeRight: SOGoMailRole_Administrator]; +} + +- (BOOL) userIsAdministrator +{ + return [userRights containsObject: SOGoMailRole_Administrator]; +} + +- (void) updateRights +{ + WORequest *request; + + request = [context request]; + + if ([[request formValueForKey: SOGoRole_ObjectViewer] length] > 0) + [self appendRight: SOGoRole_ObjectViewer]; + else + [self removeRight: SOGoRole_ObjectViewer]; + + if ([[request formValueForKey: SOGoRole_ObjectReader] length] > 0) + [self appendRight: SOGoRole_ObjectReader]; + else + [self removeRight: SOGoRole_ObjectReader]; + + if ([[request formValueForKey: SOGoMailRole_SeenKeeper] length] > 0) + [self appendRight: SOGoMailRole_SeenKeeper]; + else + [self removeRight: SOGoMailRole_SeenKeeper]; + + if ([[request formValueForKey: SOGoMailRole_Writer] length] > 0) + [self appendRight: SOGoMailRole_Writer]; + else + [self removeRight: SOGoMailRole_Writer]; + + if ([[request formValueForKey: SOGoRole_ObjectCreator] length] > 0) + [self appendRight: SOGoRole_ObjectCreator]; + else + [self removeRight: SOGoRole_ObjectCreator]; + + if ([[request formValueForKey: SOGoMailRole_Poster] length] > 0) + [self appendRight: SOGoMailRole_Poster]; + else + [self removeRight: SOGoMailRole_Poster]; + + if ([[request formValueForKey: SOGoRole_FolderCreator] length] > 0) + [self appendRight: SOGoRole_FolderCreator]; + else + [self removeRight: SOGoRole_FolderCreator]; + + if ([[request formValueForKey: SOGoRole_ObjectEraser] length] > 0) + [self appendRight: SOGoRole_ObjectEraser]; + else + [self removeRight: SOGoRole_ObjectEraser]; + + if ([[request formValueForKey: SOGoMailRole_MessageEraser] length] > 0) + [self appendRight: SOGoMailRole_MessageEraser]; + else + [self removeRight: SOGoMailRole_MessageEraser]; + + if ([[request formValueForKey: SOGoMailRole_Expunger] length] > 0) + [self appendRight: SOGoMailRole_Expunger]; + else + [self removeRight: SOGoMailRole_Expunger]; + + if ([[request formValueForKey: SOGoMailRole_Administrator] length] > 0) + [self appendRight: SOGoMailRole_Administrator]; + else + [self removeRight: SOGoMailRole_Administrator]; +} + +@end + diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index 0979d877f..1f44d4698 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -1,5 +1,5 @@ { /* -*-javascript-*- */ - requires = ( MAIN, CommonUI, Mailer ); /* , Sieve */ + requires = ( MAIN, MainUI, CommonUI, Mailer ); /* , Sieve */ publicResources = ( "uix.css", @@ -131,15 +131,20 @@ pageName = "UIxMailListView"; actionName = "deleteFolder"; }; - editACL = { - protectedBy = "View"; - pageName = "UIxMailFolderACLEditor"; - }; compose = { protectedBy = "View"; actionClass = "UIxMailEditorAction"; actionName = "compose"; }; + userRights = { + protectedBy = "ReadAcls"; + pageName = "UIxMailUserRightsEditor"; + }; + saveUserRights = { + protectedBy = "SaveAcls"; + pageName = "UIxMailUserRightsEditor"; + actionName = "saveUserRights"; + }; }; }; @@ -255,24 +260,16 @@ }; }; methods = { - view = { - protectedBy = "View"; - pageName = "UIxMailAccountView"; - }; - getMail = { - protectedBy = "View"; - pageName = "UIxMailAccountView"; - }; compose = { protectedBy = "View"; actionClass = "UIxMailEditorAction"; actionName = "compose"; }; - createFolder = { - protectedBy = "View"; - pageName = "UIxMailAccountView"; - actionName = "createFolder"; - }; + mailboxes = { + protectedBy = "View"; + pageName = "UIxMailAccountView"; + actionName = "listMailboxes"; + }; }; }; diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index 050f12def..05d991c9a 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -70,7 +70,7 @@ "New Calendar..." = "New Calendar..."; "Delete Calendar" = "Delete Calendar"; -"Access Rights..." = "Access Rights..."; +"Sharing..." = "Sharing..."; "Export Calendar..." = "Export Calendar..."; "Publish Calendar..." = "Publish Calendar..."; "Reload Remote Calendars" = "Reload Remote Calendars"; diff --git a/UI/Scheduler/French.lproj/Localizable.strings b/UI/Scheduler/French.lproj/Localizable.strings index 46b02d33a..44e9be99e 100644 --- a/UI/Scheduler/French.lproj/Localizable.strings +++ b/UI/Scheduler/French.lproj/Localizable.strings @@ -71,7 +71,7 @@ "New Calendar..." = "Nouvel agenda..."; "Delete Calendar" = "Effacer l'agenda"; -"Access Rights..." = "Partage"; +"Sharing..." = "Partage..."; "Export Calendar..." = "Exporter l'agenda..."; "Publish Calendar..." = "Publier l'agenda..."; "Reload Remote Calendars" = "Recharger les agendas distants"; diff --git a/UI/Templates/ContactsUI/UIxContactsFilterPanel.wox b/UI/Templates/ContactsUI/UIxContactsFilterPanel.wox index 916ce36c4..8e92f86d5 100644 --- a/UI/Templates/ContactsUI/UIxContactsFilterPanel.wox +++ b/UI/Templates/ContactsUI/UIxContactsFilterPanel.wox @@ -7,9 +7,8 @@ > diff --git a/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox b/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox index f53445b0d..8a2d86556 100644 --- a/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox +++ b/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox @@ -14,23 +14,24 @@ diff --git a/UI/Templates/MailerUI/UIxMailAccountView.wox b/UI/Templates/MailerUI/UIxMailAccountView.wox deleted file mode 100644 index 26cef689e..000000000 --- a/UI/Templates/MailerUI/UIxMailAccountView.wox +++ /dev/null @@ -1,43 +0,0 @@ - -
-

- SOGo Mail - - - - - - -

- -
- - -
-
- -

Email

-

-
-
-

- -

Accounts

-

- View settings for this account
- Create a new account [TBD: not in Agenor]
-

- -

Advanced Features

-

- Search messages
- Manage message filters
- Manage folder subscriptions
- Offline settings [TBD: not in Agenor]
-

-
diff --git a/UI/Templates/MailerUI/UIxMailFolderACLEditor.wox b/UI/Templates/MailerUI/UIxMailFolderACLEditor.wox deleted file mode 100644 index 421c98cad..000000000 --- a/UI/Templates/MailerUI/UIxMailFolderACLEditor.wox +++ /dev/null @@ -1,13 +0,0 @@ - - - TODO: IMAP4 ACL editor - diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index f02e8c878..e5e57d9dc 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -30,7 +30,7 @@
  • -
  • +
  • @@ -46,7 +46,7 @@
  • -
  • +
  • @@ -63,7 +63,7 @@
  • -
  • +
  • diff --git a/UI/Templates/MailerUI/UIxMailSplashView.wox b/UI/Templates/MailerUI/UIxMailSplashView.wox deleted file mode 100644 index 26cef689e..000000000 --- a/UI/Templates/MailerUI/UIxMailSplashView.wox +++ /dev/null @@ -1,43 +0,0 @@ - -
    -

    - SOGo Mail - - - - - - -

    - -
    - - -
    -
    - -

    Email

    -

    -
    -
    -

    - -

    Accounts

    -

    - View settings for this account
    - Create a new account [TBD: not in Agenor]
    -

    - -

    Advanced Features

    -

    - Search messages
    - Manage message filters
    - Manage folder subscriptions
    - Offline settings [TBD: not in Agenor]
    -

    -
    diff --git a/UI/Templates/MailerUI/UIxMailUserRightsEditor.wox b/UI/Templates/MailerUI/UIxMailUserRightsEditor.wox new file mode 100644 index 000000000..998f5b6f7 --- /dev/null +++ b/UI/Templates/MailerUI/UIxMailUserRightsEditor.wox @@ -0,0 +1,88 @@ + + + +
    + +
    + + + + +
    +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    +
    +
    + + +
    +
    +
    diff --git a/UI/Templates/SchedulerUI/UIxCalFilterPanel.wox b/UI/Templates/SchedulerUI/UIxCalFilterPanel.wox index 44c03cade..c0b6f513b 100644 --- a/UI/Templates/SchedulerUI/UIxCalFilterPanel.wox +++ b/UI/Templates/SchedulerUI/UIxCalFilterPanel.wox @@ -7,9 +7,7 @@ > diff --git a/UI/Templates/SchedulerUI/UIxCalMainView.wox b/UI/Templates/SchedulerUI/UIxCalMainView.wox index 62d0d9c25..6c075ace7 100644 --- a/UI/Templates/SchedulerUI/UIxCalMainView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMainView.wox @@ -14,10 +14,7 @@ - +
    diff --git a/UI/WebServerResources/ContactsUI.js b/UI/WebServerResources/ContactsUI.js index a3e2ed5cf..3b9dd8e9b 100644 --- a/UI/WebServerResources/ContactsUI.js +++ b/UI/WebServerResources/ContactsUI.js @@ -91,7 +91,7 @@ function contactsListCallback(http) { function onContactFoldersContextMenu(event) { var menu = $("contactFoldersMenu"); Event.observe(menu, "hideMenu", onContactFoldersContextMenuHide, false); - onMenuClick(event, "contactFoldersMenu"); + popupMenu(event, "contactFoldersMenu", this); var topNode = $("contactFolders"); var selectedNodes = topNode.getSelectedRows(); @@ -105,7 +105,7 @@ function onContactFoldersContextMenu(event) { function onContactContextMenu(event, element) { var menu = $("contactMenu"); Event.observe(menu, "hideMenu", onContactContextMenuHide, false); - onMenuClick(event, "contactMenu"); + popupMenu(event, "contactMenu", element); var topNode = $("contactsList"); var selectedNodes = topNode.getSelectedRows(); @@ -235,31 +235,23 @@ function onContactRowDblClick(event, node) { return false; } -function onMenuEditContact(event, node) { - var node = getParentMenu(node).menuTarget.parentNode; - var contactId = node.getAttribute('id'); +function onMenuEditContact(event) { + var contactId = document.menuTarget.getAttribute('id'); openContactWindow(null, URLForFolderID(currentContactFolder) + "/" + contactId + "/edit"); - - return false; } -function onMenuWriteToContact(event, node) { - var node = getParentMenu(node).menuTarget.parentNode; - var contactId = node.getAttribute('id'); +function onMenuWriteToContact(event) { + var contactId = document.menuTarget.getAttribute('id'); - openMailComposeWindow(ApplicationBaseURL + currentContactFolder - + "/" + contactId + "/write"); - - return false; + openMailComposeWindow(ApplicationBaseURL + currentContactFolder + + "/" + contactId + "/write"); } -function onMenuDeleteContact(event, node) { - uixDeleteSelectedContacts(node); - - return false; +function onMenuDeleteContact(event) { + uixDeleteSelectedContacts(this); } function onToolbarEditSelectedContacts(event) { @@ -594,9 +586,8 @@ function configureContactFolders() { if (contactFolders) { Event.observe(contactFolders, "selectionchange", onFolderSelectionChange, false); var lis = contactFolders.childNodesWithTag("li"); - for (var i = 0; i < lis.length; i++) { + for (var i = 0; i < lis.length; i++) setEventsOnContactFolder(lis[i]); - } lookupDeniedFolders(); contactFolders.setStyle({ visibility: 'visible' }); @@ -612,21 +603,27 @@ function setEventsOnContactFolder(node) { Event.observe(node, "contextmenu", onContactFoldersContextMenu, false); } -function onAccessRightsMenuEntryMouseUp(event) { - var folders = $("contactFolders"); - var selected = folders.getSelectedNodes()[0]; - var title = this.innerHTML; - var url = URLForFolderID(selected.getAttribute("id")) +function onMenuSharing(event) { + var folders = $("contactFolders"); + var selected = folders.getSelectedNodes()[0]; + var title = this.innerHTML; + var url = URLForFolderID(selected.getAttribute("id")); - openAclWindow(url + "/acls", title); + openAclWindow(url + "/acls", title); } function initializeMenus() { - var menus = new Array("contactFoldersMenu", "contactMenu", "searchMenu"); - initMenusNamed(menus); + menus["menuIds"] = new Array("contactFoldersMenu", "contactMenu", + "searchMenu"); + menus["contactFoldersMenu"] = new Array(null, "-", null, + null, "-", null, "-", + onMenuSharing); + menus["contactMenu"] = new Array(onMenuEditContact, "-", + onMenuWriteToContact, null, "-", + onMenuDeleteContact); + menus["searchMenu"] = new Array(setSearchCriteria); - var menuEntry = $("accessRightsMenuEntry"); - Event.observe(menuEntry, "mouseup", onAccessRightsMenuEntryMouseUp, false); + initMenus(); } function configureSearchField() { diff --git a/UI/WebServerResources/HTMLElement.js b/UI/WebServerResources/HTMLElement.js index 524232490..44e876b99 100644 --- a/UI/WebServerResources/HTMLElement.js +++ b/UI/WebServerResources/HTMLElement.js @@ -1,178 +1,236 @@ -Element.addMethods({ - - addInterface: function(element, objectInterface) { - element = $(element); - Object.extend(element, objectInterface); - if (element.bind) - element.bind(); - }, - - childNodesWithTag: function(element, tagName) { - element = $(element); - var matchingNodes = new Array(); - var tagName = tagName.toUpperCase(); - - for (var i = 0; i < element.childNodes.length; i++) { - if (typeof(element.childNodes[i]) == "object" - && element.childNodes[i].tagName - && element.childNodes[i].tagName.toUpperCase() == tagName) - matchingNodes.push(element.childNodes[i]); - } +if (navigator.vendor == "Apple Computer, Inc." || navigator.vendor == "KDE") { // WebCore/KHTML + /* + Crossbrowser HTMLElement Prototyping + Copyright (C) 2005 Jason Davis, http://www.browserland.org + Additional thanks to Brothercake, http://www.brothercake.com - return matchingNodes; - }, + This code is licensed under the LGPL: + http://www.gnu.org/licenses/lgpl.html + */ - getParentWithTagName: function(element, tagName) { - element = $(element); - var currentElement = element; - tagName = tagName.toUpperCase(); - - currentElement = currentElement.parentNode; - while (currentElement - && currentElement.tagName != tagName) { - currentElement = currentElement.parentNode; - } - - return currentElement; - }, - - cascadeLeftOffset: function(element) { - element = $(element); - var currentElement = element; + (function(c) { + for (var i in c) + window["HTML" + i + "Element"] = document.createElement(c[ i ]).constructor; + })({ + Html: "html", Head: "head", Link: "link", Title: "title", Meta: "meta", + Base: "base", IsIndex: "isindex", Style: "style", Body: "body", Form: "form", + Select: "select", OptGroup: "optgroup", Option: "option", Input: "input", + TextArea: "textarea", Button: "button", Label: "label", FieldSet: "fieldset", + Legend: "legend", UList: "ul", OList: "ol", DList: "dl", Directory: "dir", + Menu: "menu", LI: "li", Div: "div", Paragraph: "p", Heading: "h1", Quote: "q", + Pre: "pre", BR: "br", BaseFont: "basefont", Font: "font", HR: "hr", Mod: "ins", + Anchor: "a", Image: "img", Object: "object", Param: "param", Applet: "applet", + Map: "map", Area: "area", Script: "script", Table: "table", TableCaption: "caption", + TableCol: "col", TableSection: "tbody", TableRow: "tr", TableCell: "td", + FrameSet: "frameset", Frame: "frame", IFrame: "iframe" + }); - var offset = 0; - while (currentElement) { - offset += currentElement.offsetLeft; - currentElement = currentElement.getParentWithTagName("div"); - } - - return offset; - }, - - cascadeTopOffset: function(element) { - element = $(element); - var currentElement = element; - var offset = 0; - - var i = 0; - while (currentElement - && currentElement instanceof HTMLElement) { - offset += currentElement.offsetTop; - currentElement = currentElement.parentNode; - i++; - } - - return offset; - }, - - dump: function(element, additionalInfo, additionalKeys) { - element = $(element); - var id = element.getAttribute("id"); - var nclass = element.getAttribute("class"); + function HTMLElement() {} + //HTMLElement.prototype = HTMLHtmlElement.__proto__.__proto__; + var HTMLDocument = document.constructor; + var HTMLCollection = document.links.constructor; + var HTMLOptionsCollection = document.createElement("select").options.constructor; + var Text = document.createTextNode("").constructor; + //var Node = Text; - var str = element.tagName; - if (id) - str += "; id = " + id; - if (nclass) - str += "; class = " + nclass; - - if (additionalInfo) - str += "; " + additionalInfo; - - if (additionalKeys) - for (var i = 0; i < additionalKeys.length; i++) { - var value = element.getAttribute(additionalKeys[i]); - if (value) - str += "; " + additionalKeys[i] + " = " + value; - } - - log (str); - }, + // More efficient for Safari 2 + function Document() {} + function Event() {} + function HTMLCollection() {} + function HTMLElement() {} + function Node() {} + Document.prototype = window["[[DOMDocument]]"]; + Event.prototype = window["[[DOMEvent]]"]; + HTMLCollection.prototype = window["[[HTMLCollection.prototype]]"]; + HTMLElement.prototype = window["[[DOMElement.prototype]]"]; + Node.prototype = window["[[DOMNode.prototype]]"]; +} - getSelectedNodes: function(element) { - element = $(element); - var selArray = new Array(); +/* custom extensions to the DOM api */ +HTMLElement.prototype.addInterface = function(objectInterface) { + Object.extend(this, objectInterface); + if (this.bind) + this.bind(); +} - for (var i = 0; i < element.childNodes.length; i++) { - node = element.childNodes.item(i); - if (node.nodeType == 1 - && isNodeSelected(node)) - selArray.push(node); - } - - return selArray; - }, - - getSelectedNodesId: function(element) { - element = $(element); - var selArray = new Array(); - - for (var i = 0; i < element.childNodes.length; i++) { - node = element.childNodes.item(i); - if (node.nodeType == 1 - && isNodeSelected(node)) - selArray.push(node.getAttribute("id")); - } - - return selArray; - }, +HTMLElement.prototype.childNodesWithTag = function(tagName) { + var matchingNodes = new Array(); + var tagName = tagName.toUpperCase(); - onContextMenu: function(element, event) { - element = $(element); - var popup = element.sogoContextMenu; - - if (document.currentPopupMenu) - hideMenu(event, document.currentPopupMenu); - - var menuTop = event.pageY; - var menuLeft = event.pageX; - var heightDiff = (window.innerHeight - - (menuTop + popup.offsetHeight)); - if (heightDiff < 0) - menuTop += heightDiff; - - var leftDiff = (window.innerWidth - - (menuLeft + popup.offsetWidth)); - if (leftDiff < 0) - menuLeft -= popup.offsetWidth; - - popup.style.top = menuTop + "px;"; - popup.style.left = menuLeft + "px;"; - popup.style.visibility = "visible;"; - - bodyOnClick = "" + document.body.getAttribute("onclick"); - document.body.setAttribute("onclick", "onBodyClick(event);"); - document.currentPopupMenu = popup; - }, - - attachMenu: function(element, menuName) { - element = $(element); - element.sogoContextMenu = $(menuName); - element.addEventListener("contextmenu", element.onContextMenu, true); - }, - - select: function(element) { - element = $(element); - element.addClassName('_selected'); - }, - - deselect: function(element) { - element = $(element); - element.removeClassName('_selected'); - }, - - deselectAll: function(element) { - element = $(element); - var nodes; - if (element.tagName == 'TABLE') - nodes = element.getSelectedRows(); - else - nodes = element.childNodes; - for (var i = 0; i < nodes.length; i++) { - var node = nodes.item(i); - if (node.nodeType == 1) - node.deselect(); - } + for (var i = 0; i < this.childNodes.length; i++) { + if (typeof(this.childNodes[i]) == "object" + && this.childNodes[i].tagName + && this.childNodes[i].tagName.toUpperCase() == tagName) + matchingNodes.push(this.childNodes[i]); } -}); // Element.addMethods + return matchingNodes; +} + +HTMLElement.prototype.addClassName = function(className) { + var classStr = '' + this.getAttribute("class"); + + position = classStr.indexOf(className, 0); + if (position < 0) { + classStr = classStr + ' ' + className; + this.setAttribute('class', classStr); + } +} + +HTMLElement.prototype.removeClassName = function(className) { + var classStr = '' + this.getAttribute('class'); + + position = classStr.indexOf(className, 0); + while (position > -1) { + classStr1 = classStr.substring(0, position); + classStr2 = classStr.substring(position + 10, classStr.length); + classStr = classStr1 + classStr2; + position = classStr.indexOf(className, 0); + } + + this.setAttribute('class', classStr); +} + +HTMLElement.prototype.hasClassName = function(className) { + var classStr = '' + this.getAttribute('class'); + position = classStr.indexOf(className, 0); + return (position > -1); +} + +HTMLElement.prototype.getParentWithTagName = function(tagName) { + var currentElement = this; + tagName = tagName.toUpperCase(); + + currentElement = currentElement.parentNode; + while (currentElement + && currentElement.tagName != tagName) { + currentElement = currentElement.parentNode; + } + + return currentElement; +} + +HTMLElement.prototype.cascadeLeftOffset = function() { + var currentElement = this; + + var offset = 0; + while (currentElement) { + offset += currentElement.offsetLeft; + currentElement = currentElement.getParentWithTagName("div"); + } + + return offset; +} + +HTMLElement.prototype.cascadeTopOffset = function() { + var currentElement = this; + var offset = 0; + + var i = 0; + + while (currentElement + && currentElement instanceof HTMLElement) { + offset += currentElement.offsetTop; + currentElement = currentElement.parentNode; + i++; + } + + return offset; +} + +HTMLElement.prototype.dump = function(additionalInfo, additionalKeys) { + var id = this.getAttribute("id"); + var nclass = this.getAttribute("class"); + + var str = this.tagName; + if (id) + str += "; id = " + id; + if (nclass) + str += "; class = " + nclass; + + if (additionalInfo) + str += "; " + additionalInfo; + + if (additionalKeys) + for (var i = 0; i < additionalKeys.length; i++) { + var value = this.getAttribute(additionalKeys[i]); + if (value) + str += "; " + additionalKeys[i] + " = " + value; + } + + log (str); +} + +HTMLElement.prototype.getSelectedNodes = function() { + var selArray = new Array(); + + for (var i = 0; i < this.childNodes.length; i++) { + node = this.childNodes.item(i); + if (node.nodeType == 1 + && isNodeSelected(node)) + selArray.push(node); + } + + return selArray; +} + +HTMLElement.prototype.getSelectedNodesId = function() { + var selArray = new Array(); + + for (var i = 0; i < this.childNodes.length; i++) { + node = this.childNodes.item(i); + if (node.nodeType == 1 + && isNodeSelected(node)) + selArray.push(node.getAttribute("id")); + } + + return selArray; +} + +HTMLElement.prototype.onContextMenu = function(event) { + var popup = this.sogoContextMenu; + + if (document.currentPopupMenu) + hideMenu(event, document.currentPopupMenu); + + var menuTop = event.pageY; + var menuLeft = event.pageX; + var heightDiff = (window.innerHeight + - (menuTop + popup.offsetHeight)); + if (heightDiff < 0) + menuTop += heightDiff; + + var leftDiff = (window.innerWidth + - (menuLeft + popup.offsetWidth)); + if (leftDiff < 0) + menuLeft -= popup.offsetWidth; + + popup.style.top = menuTop + "px;"; + popup.style.left = menuLeft + "px;"; + popup.style.visibility = "visible;"; + + bodyOnClick = "" + document.body.getAttribute("onclick"); + document.body.setAttribute("onclick", "onBodyClick(event);"); + document.currentPopupMenu = popup; +} + +HTMLElement.prototype.attachMenu = function(menuName) { + this.sogoContextMenu = $(menuName); + Event.observe(this, "contextmenu", this.onContextMenu); +} + +HTMLElement.prototype.select = function() { + this.addClassName('_selected'); +} + +HTMLElement.prototype.deselect = function() { + this.removeClassName('_selected'); +} + +HTMLElement.prototype.deselectAll = function () { + for (var i = 0; i < this.childNodes.length; i++) { + var node = this.childNodes.item(i); + if (node.nodeType == 1) + node.deselect(); + } +} diff --git a/UI/WebServerResources/JavascriptAPIExtensions.js b/UI/WebServerResources/JavascriptAPIExtensions.js index fc7649ab8..088a7f10a 100644 --- a/UI/WebServerResources/JavascriptAPIExtensions.js +++ b/UI/WebServerResources/JavascriptAPIExtensions.js @@ -2,6 +2,15 @@ String.prototype.trim = function() { return this.replace(/(^\s+|\s+$)/g, ''); } +String.prototype.repeat = function(count) { + var newString = ""; + for (var i = 0; i < count; i++) { + newString += this; + } + + return newString; +} + String.prototype.capitalize = function() { return this.replace(/\w+/g, function(a) { diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index d64e78e1f..075d020ce 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -4,6 +4,10 @@ var currentMessages = new Array(); var maxCachedMessages = 20; var cachedMessages = new Array(); var currentMailbox = ''; + +var usersRightsWindowHeight = 320; +var usersRightsWindowWidth = 400; + /* mail list */ function openMessageWindow(msguid, url) { @@ -113,6 +117,14 @@ function openAddressbook(sender) { return false; } +function onMenuSharing(event) { + var folderID = document.menuTarget.getAttribute("dataname"); + var urlstr = URLForFolderID(folderID) + "/acls"; + event.preventDefault(); + + openAclWindow(urlstr); +} + /* mail list DOM changes */ function markMailInWindow(win, msguid, markread) { @@ -1059,13 +1071,14 @@ function initializeMenus() { "messageContentMenu", "label-menu", "mark-menu"); menus["accountIconMenu"] = new Array(null, null, null, null, null, null, - null, null, null, null); + null, null, null, onMenuSharing); menus["inboxIconMenu"] = new Array(null, null, null, "-", null, null, - null, "-", null, null); + null, "-", null, onMenuSharing); menus["trashIconMenu"] = new Array(null, null, null, "-", null, null, null, - null, "-", null, null); + null, "-", null, onMenuSharing); menus["mailboxIconMenu"] = new Array(null, null, null, "-", null, null, - null, null, null, "-", null, null); + null, null, null, "-", null, + onMenuSharing); menus["addressMenu"] = new Array(newContactFromEmail, newEmailTo, null); menus["messageListMenu"] = new Array(onMenuOpenMessage, "-", onMenuReplyToSender, diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 698e6c7a0..1265ba520 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -23,28 +23,36 @@ var usersRightsWindowHeight = 250; var usersRightsWindowWidth = 502; function newEvent(sender, type) { - var day = sender.getAttribute("day"); - if (!day) - day = currentDay; + var day = sender.getAttribute("day"); + if (!day) + day = currentDay; - var user = UserLogin; - if (sender.parentNode.getAttribute("id") != "toolbar" - && currentView == "multicolumndayview" && type == "event") - user = sender.parentNode.parentNode.getAttribute("user"); + var user = UserLogin; + if (sender.parentNode.getAttribute("id") != "toolbar" + && currentView == "multicolumndayview" && type == "event") + user = sender.parentNode.parentNode.getAttribute("user"); - var hour = sender.getAttribute("hour"); - var urlstr = UserFolderURL + "../" + user + "/Calendar/new" + type; - var params = new Array(); - if (day) - params.push("day=" + day); - if (hour) - params.push("hm=" + hour); - if (params.length > 0) - urlstr += "?" + params.join("&"); + var hour = sender.getAttribute("hour"); + var urlstr = UserFolderURL + "../" + user + "/Calendar/new" + type; + var params = new Array(); + if (day) + params.push("day=" + day); + if (hour) + params.push("hm=" + hour); + if (params.length > 0) + urlstr += "?" + params.join("&"); + + window.open(urlstr, "", "width=490,height=470,resizable=0"); + + return false; /* stop following the link */ +} - window.open(urlstr, "", "width=490,height=470,resizable=0"); +function onMenuNewEventClick(event) { + newEvent(this, "event"); +} - return false; /* stop following the link */ +function onMenuNewTaskClick(event) { + newEvent(this, "task"); } function _editEventId(id, owner) { @@ -549,7 +557,7 @@ function onAppointmentContextMenu(event, element) { var menu = $("appointmentsListMenu"); Event.observe(menu, "hideMenu", onAppointmentContextMenuHide); - onMenuClick(event, "appointmentsListMenu"); + popupMenu(event, "appointmentsListMenu", element); var topNode = $("appointmentsList"); var selectedNodes = topNode.getSelectedRows(); @@ -714,22 +722,20 @@ function popupMonthMenu(event, menuId) { } } -function onMonthMenuItemClick(node) { - var month = '' + node.getAttribute("month"); +function onMonthMenuItemClick(event) { + var month = '' + this.getAttribute("month"); var year = '' + $("yearLabel").innerHTML; - - changeDateSelectorDisplay(year+month+"01", true); - return false; + changeDateSelectorDisplay(year + month + "01", true); + +// event.cancelBubble(); } -function onYearMenuItemClick(node) { +function onYearMenuItemClick(event) { var month = '' + $("monthLabel").getAttribute("month");; - var year = '' + node.innerHTML; + var year = '' + this.innerHTML; - changeDateSelectorDisplay(year+month+"01", true); - - return false; + changeDateSelectorDisplay(year + month + "01", true); } function onSearchFormSubmit() { @@ -977,22 +983,46 @@ function browseURL(anchor, event) { } function initializeMenus() { - var menus = new Array("monthListMenu", "yearListMenu", - "appointmentsListMenu", "calendarsMenu", "searchMenu"); + menus["menuIds"] = new Array("monthListMenu", "yearListMenu", + "appointmentsListMenu", + "calendarsMenu", + "searchMenu"); + var dateMenu = new Array(); + for (var i = 0; i < 12; i++) + dateMenu.push(onMonthMenuItemClick); + menus["monthListMenu"] = dateMenu; - $("calendarSelector").attachMenu("calendarsMenu"); + dateMenu = new Array(); + for (var i = 0; i < 11; i++) + dateMenu.push(onYearMenuItemClick); + menus["yearListMenu"] = dateMenu; - var accessRightsMenuEntry = $("accessRightsMenuEntry"); - Event.observe(accessRightsMenuEntry, "mouseup", onAccessRightsMenuEntryMouseUp); + menus["appointmentsListMenu"] = new Array(onMenuNewEventClick, "-", + onMenuNewTaskClick, + editEvent, deleteEvent, "-", + onSelectAll, "-", + null, null); + menus["calendarsMenu"] = new Array(null, null, "-", null, null, "-", + null, "-", onMenuSharing); + menus["searchMenu"] = new Array(setSearchCriteria); + + initMenus(); + var selector = $("calendarSelector"); + if (selector) + selector.attachMenu("calendarsMenu"); } -function onAccessRightsMenuEntryMouseUp(event) { +function onMenuSharing(event) { var folders = $("calendarList"); var selected = folders.getSelectedNodes()[0]; - var folderID = selected.getAttribute("id"); - var urlstr = URLForFolderID(folderID) + "/acls"; + /* FIXME: activation of the context menu should preferable select the entry + above which the event has occured */ + if (selected) { + var folderID = selected.getAttribute("id"); + var urlstr = URLForFolderID(folderID) + "/acls"; - openAclWindow(urlstr); + openAclWindow(urlstr); + } } function configureDragHandles() { diff --git a/UI/WebServerResources/UIxAclEditor.js b/UI/WebServerResources/UIxAclEditor.js index 74845b325..5354d9998 100644 --- a/UI/WebServerResources/UIxAclEditor.js +++ b/UI/WebServerResources/UIxAclEditor.js @@ -119,15 +119,20 @@ function onOpenUserRights(event) { function onAclLoadHandler() { defaultUserID = $("defaultUserID").value; - Event.observe($("defaultRolesBtn"), "click", openRightsForDefaultUser); + var defaultRolesBtn = $("defaultRolesBtn"); + if (defaultRolesBtn) + Event.observe(defaultRolesBtn, "click", openRightsForDefaultUser); var ul = $("userList"); var lis = ul.childNodesWithTag("li"); for (var i = 0; i < lis.length; i++) setEventsOnUserNode(lis[i]); - var buttons = $("userSelectorButtons").childNodesWithTag("a"); - Event.observe(buttons[0], "click", onUserAdd); - Event.observe(buttons[1], "click", onUserRemove); + var buttonArea = $("userSelectorButtons"); + if (buttonArea) { + var buttons = buttonArea.childNodesWithTag("a"); + Event.observe(buttons[0], "click", onUserAdd); + Event.observe(buttons[1], "click", onUserRemove); + } this.userRightsHeight = window.opener.getUsersRightsWindowHeight(); this.userRightsWidth = window.opener.getUsersRightsWindowWidth(); diff --git a/UI/WebServerResources/UIxMailUserRightsEditor.css b/UI/WebServerResources/UIxMailUserRightsEditor.css new file mode 100644 index 000000000..eaea5734b --- /dev/null +++ b/UI/WebServerResources/UIxMailUserRightsEditor.css @@ -0,0 +1,49 @@ +DIV.title +{ color: #000; + vertical-align: bottom; + padding-top: 15px; + padding-left: 1em; + height: 33px; + background-color: #fff; + border-bottom: 1px solid #555; } + +DIV.title SPAN.value +{ margin-left: 1em; + font-size: 18px; + font-weight: bold; } + +DIV.calendarUserRights +{ margin: 1em;} + +DIV.calendarUserRights > TABLE +{ background-color: #fff; + width: 45em; + color: #999; + border-collapse: collapse; + border-bottom: 1px solid #fff; + border-right: 1px solid #fff; + border-top: 2px solid #222; + border-left: 2px solid #222; + -moz-border-top-colors: #9c9a94 #000 transparent; + -moz-border-left-colors: #9c9a94 #000 transparent; } + +DIV.calendarUserRights > TABLE TR.permissions TH +{ color: #00f; +/* background-color: #ddd; + */ border-bottom: 1px solid #999; } + +DIV.calendarUserRights > TABLE TH +{ width: 15em; } + +DIV.calendarUserRights > TABLE TD.eventType +{ width: 5em; + text-align: right; + border-right: 1px solid #999; } + +DIV.calendarUserRights > TABLE TD +{ text-align: center; + border-top: 1px solid #cecbff; } + +DIV.buttons +{ text-align: right; + margin: 1em; } diff --git a/UI/WebServerResources/UIxMailUserRightsEditor.js b/UI/WebServerResources/UIxMailUserRightsEditor.js new file mode 100644 index 000000000..71fe311f7 --- /dev/null +++ b/UI/WebServerResources/UIxMailUserRightsEditor.js @@ -0,0 +1,9 @@ +function onCancelClick(event) { + window.close(); +} + +function initACLButtons() { + $("cancelButton").addEventListener("click", onCancelClick, false); +} + +window.addEventListener("load", initACLButtons, false); diff --git a/UI/WebServerResources/generic.css b/UI/WebServerResources/generic.css index a15911de1..19c19b1af 100644 --- a/UI/WebServerResources/generic.css +++ b/UI/WebServerResources/generic.css @@ -218,8 +218,6 @@ DIV#toolbar white-space: nowrap; overflow: auto; } -BODY.popup { min-width: 400px; } - BODY.popup DIV#toolbar { border-top: 0px; } diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index f162736ea..5a36bda9e 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -573,8 +573,14 @@ function log(message) { logWindow = logWindow.opener; } var logConsole = logWindow.document.getElementById("logConsole"); - if (logConsole) - logConsole.innerHTML += message.replace("<", "<", "g") + '
    ' + "\n"; + if (logConsole) { + var logMessage = message.replace("<", "<", "g"); + logMessage = logMessage.replace("\r\n", "
    \n", "g"); + logMessage = logMessage.replace("\n", "
    \n", "g"); + logMessage = logMessage.replace(" ", " ", "g"); + logMessage += '
    ' + "\n"; + logConsole.innerHTML += logMessage; + } } function backtrace() { @@ -684,10 +690,9 @@ function popupSearchMenu(event) { function setSearchCriteria(event) { searchValue = $("searchValue"); searchCriteria = $("searchCriteria"); - - var node = event.target; - searchValue.setAttribute("ghost-phrase", node.innerHTML); - searchCriteria = node.getAttribute('id'); + + searchValue.setAttribute("ghost-phrase", this.innerHTML); +// searchCriteria = this.getAttribute('id'); } function checkSearchValue(event) { @@ -910,7 +915,8 @@ function initMenus() { var menuId = menus["menuIds"][i]; var callbacks = menus[menuId]; var menuDIV = $(menuId); - initMenu(menuDIV, callbacks); + if (menuDIV) + initMenu(menuDIV, callbacks); } } @@ -1077,11 +1083,11 @@ function indexColor(number) { var onLoadHandler = function (event) { queryParameters = parseQueryParameters('' + window.location); - if (!$(document.body).hasClassName("popup")) { + if (!document.body.hasClassName("popup")) { initLogConsole(); - initializeMenus(); initCriteria(); } + initializeMenus(); initTabs(); configureDragHandles(); configureSortableTableHeaders(); diff --git a/UI/WebServerResources/submenu-disabled.gif b/UI/WebServerResources/submenu-disabled.gif new file mode 100644 index 000000000..f24a802f0 Binary files /dev/null and b/UI/WebServerResources/submenu-disabled.gif differ