From 1ed3955bd0b01b5cb1419c07596c457bb7f3a684 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Wed, 12 Sep 2007 13:01:17 +0000 Subject: [PATCH 1/6] Monotone-Parent: 9ef1fb2c66953b8ada0d55d0eec183621a71ebab Monotone-Revision: dc5f7b2c31d9e41fc7a1cb9e62c39060dca4d576 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-09-12T13:01:17 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 8 ++++ UI/MainUI/SOGoRootPage.m | 96 +++++++--------------------------------- 2 files changed, 24 insertions(+), 80 deletions(-) diff --git a/ChangeLog b/ChangeLog index 53a2270d6..3556ea464 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-09-12 Wolfgang Sourdeau + + * UI/MainUI/SOGoRootPage.m ([SOGoRootPage -defaultAction]): test + whether the user is logged in and if so, redirect to his/her + homepage. + ([SOGoRootPage -appendToResponse:inContext:]): removed useless + method. + 2007-09-11 Wolfgang Sourdeau * SoObjects/SOGo/SOGoFolder.m ([SOGoFolder diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index d4bdc2070..f0323e638 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -83,88 +83,24 @@ return response; } -// - (id ) defaultAction -// { -// WOResponse *r; -// NSString *login, *rhk; -// SOGoWebAuthenticator *auth; -// SOGoUser *user; -// SOGoUserFolder *home; -// WOApplication *base; +- (id ) defaultAction +{ + id response; + NSString *login, *oldLocation; -// /* -// Note: ctx.activeUser is NOT set here. Don't know why, so we retrieve -// the user from the authenticator. -// */ - -// auth = [[self clientObject] authenticatorInContext: context]; -// user = [auth userInContext: context]; -// login = [user login]; + login = [[context activeUser] login]; + if ([login isEqualToString: @"anonymous"]) + response = self; + else + { + oldLocation = [[self clientObject] baseURLInContext: context]; + response + = [self redirectToLocation: [NSString stringWithFormat: @"%@/%@", + oldLocation, login]]; + } -// if ([login isEqualToString:@"anonymous"]) { -// /* use root page for unauthenticated users */ -// return self; -// } - -// /* check base */ - -// base = [self application]; -// rhk = [[context request] requestHandlerKey]; -// if (([rhk length] == 0) || ([base requestHandlerForKey:rhk] == nil)) { -// base = [base lookupName: @"so" inContext: context acquire: NO]; - -// if (![base isNotNull] || [base isKindOfClass:[NSException class]]) { -// /* use root page if home could not be found */ -// [self errorWithFormat:@"Did not find 'so' request handler!"]; -// return self; -// } -// } - -// /* lookup home-page */ - -// home = [base lookupName: login inContext: context acquire: NO]; -// if (![home isNotNull] || [home isKindOfClass:[NSException class]]) { -// /* use root page if home could not be found */ -// return self; -// } - -// /* redirect to home-page */ - -// r = [context response]; -// [r setStatus: 302 /* moved */]; -// [r setHeader: [home baseURLInContext: context] -// forKey: @"location"]; - -// return r; -// } - -/* response generation */ - -// - (void) appendToResponse: (WOResponse *) response -// inContext: (WOContext *) ctx -// { -// NSString *rhk; - -// // TODO: we might also want to look into the HTTP basic-auth to redirect to -// // the login URL! - -// rhk = [[ctx request] requestHandlerKey]; -// if ([rhk length] == 0 -// || [[self application] requestHandlerForKey: rhk] == nil) -// { -// /* a small hack to redirect to a valid URL */ -// NSString *url; - -// url = [ctx urlWithRequestHandlerKey: @"so" path: @"/" queryString: nil]; -// [response setStatus: 302 /* moved */]; -// [response setHeader: url forKey: @"location"]; -// [self logWithFormat: @"URL: %@", url]; -// return; -// } - -// [response setHeader: @"text/html" forKey: @"content-type"]; -// [super appendToResponse: response inContext: ctx]; -// } + return response; +} - (BOOL) isPublicInContext: (WOContext *) localContext { From 0c2dbaa0ec6c9954bcce53d0b974db2e5831bbdd Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Thu, 13 Sep 2007 14:57:55 +0000 Subject: [PATCH 2/6] Monotone-Parent: dc5f7b2c31d9e41fc7a1cb9e62c39060dca4d576 Monotone-Revision: a9a496d4716bb30eac90c8ad8d7e50c38bef62c8 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-09-13T14:57:55 Monotone-Branch: ca.inverse.sogo --- UI/WebServerResources/SOGoRootPage.css | 10 +++++----- UI/WebServerResources/lori-login.jpg | Bin 11089 -> 7861 bytes 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/UI/WebServerResources/SOGoRootPage.css b/UI/WebServerResources/SOGoRootPage.css index fa534ef43..15d0c1f47 100644 --- a/UI/WebServerResources/SOGoRootPage.css +++ b/UI/WebServerResources/SOGoRootPage.css @@ -12,10 +12,10 @@ DIV#loginScreen background-color: #d4d0c8; margin: 0px auto; margin-top: 5em; - padding: 10px; + padding: 5px; border: 2px solid transparent; - width: 197px; - height: 300px; + width: 200px; + height: 315px; -moz-border-top-colors: #efebe7 #fff; -moz-border-left-colors: #efebe7 #fff; -moz-border-right-colors: #000 #9c9a94 transparent; @@ -26,8 +26,8 @@ DIV#loginScreen IMG { border: 0px; margin: 0px; padding: 0px; - height: 192px; - width: 192px; } + height: 200px; + width: 200px; } DIV#loginScreen INPUT.textField { width: 187px; } diff --git a/UI/WebServerResources/lori-login.jpg b/UI/WebServerResources/lori-login.jpg index a8947edb4f8a3cf9c76ed99f2effec29f4af838c..7ab42d121e19921b798c31fad3efe3ccee1cb29b 100644 GIT binary patch literal 7861 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 Date: Fri, 14 Sep 2007 21:54:19 +0000 Subject: [PATCH 3/6] Monotone-Parent: d3bbadcce7472714c99e523e6d397a87aa65bf5b Monotone-Revision: 17441bc6502df80d7fa89d2f1beee98ac6e2c5d9 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-09-14T21:54:19 Monotone-Branch: ca.inverse.sogo --- UI/WebServerResources/MailerUI.js | 18 +++++++++--------- UI/WebServerResources/UIxAclEditor.js | 3 +-- UI/WebServerResources/UIxAppointmentEditor.js | 16 ++++++++-------- UI/WebServerResources/UIxComponentEditor.js | 2 +- UI/WebServerResources/UIxContactEditor.js | 4 ++-- UI/WebServerResources/UIxMailEditor.js | 3 +-- UI/WebServerResources/UIxTaskEditor.js | 10 +++++----- 7 files changed, 27 insertions(+), 29 deletions(-) diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 6fca56d53..6b626482b 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -207,7 +207,7 @@ function ctxFolderAdd(sender) { } function ctxFolderDelete(sender) { - if (!confirm("Delete current folder?").decodeEntities()) + if (!confirm("Delete current folder?")) return false; // TODO: should use a form-POST or AJAX @@ -306,10 +306,10 @@ function onMenuDeleteMessage(event) { function onPrintCurrentMessage(event) { var rowIds = $("messageList").getSelectedRowsId(); if (rowIds.length == 0) { - window.alert(labels["Please select a message to print."].decodeEntities()); + window.alert(labels["Please select a message to print."]); } else if (rowIds.length > 1) { - window.alert(labels["Please select only one message to print."].decodeEntities()); + window.alert(labels["Please select only one message to print."]); } else window.print(); @@ -489,7 +489,7 @@ function quotasCallback(http) { var used = mbQuotas["usedSpace"]; var max = mbQuotas["maxQuota"]; var percents = (Math.round(used * 10000 / max) / 100); - var format = labels["quotasFormat"].decodeEntities(); + var format = labels["quotasFormat"]; var text = format.formatted(used, max, percents); window.status = text; } @@ -1263,7 +1263,7 @@ function buildMailboxes(accountName, encoded) { } function onMenuCreateFolder(event) { - var name = window.prompt(labels["Name :"].decodeEntities(), ""); + var name = window.prompt(labels["Name :"], ""); if (name && name.length > 0) { var folderID = document.menuTarget.getAttribute("dataname"); var urlstr = URLForFolderID(folderID) + "/createFolder?name=" + name; @@ -1273,7 +1273,7 @@ function onMenuCreateFolder(event) { function onMenuRenameFolder(event) { var name = window.prompt(labels["Enter the new name of your folder :"] - .decodeEntities(), + , ""); if (name && name.length > 0) { var folderID = document.menuTarget.getAttribute("dataname"); @@ -1283,7 +1283,7 @@ function onMenuRenameFolder(event) { } function onMenuDeleteFolder(event) { - var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"].decodeEntities()); + var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"]); if (answer) { var folderID = document.menuTarget.getAttribute("dataname"); var urlstr = URLForFolderID(folderID) + "/deleteFolder"; @@ -1318,7 +1318,7 @@ function folderOperationCallback(http) { && http.status == 204) initMailboxTree(); else - window.alert(labels["Operation failed"].decodeEntities()); + window.alert(labels["Operation failed"]); } function folderRefreshCallback(http) { @@ -1329,7 +1329,7 @@ function folderRefreshCallback(http) { refreshCurrentFolder(); } else - window.alert(labels["Operation failed"].decodeEntities()); + window.alert(labels["Operation failed"]); } function getMenus() { diff --git a/UI/WebServerResources/UIxAclEditor.js b/UI/WebServerResources/UIxAclEditor.js index 91c249ab9..2bef5e1d3 100644 --- a/UI/WebServerResources/UIxAclEditor.js +++ b/UI/WebServerResources/UIxAclEditor.js @@ -88,8 +88,7 @@ function subscribeToFolder(refreshCallback, refreshCallbackData) { refreshCallbackData["folder"]); } else - refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"] - .decodeEntities()); + refreshCallbackData["window"].alert(clabels["You cannot subscribe to a folder that you own!"]); } function openRightsForUserID(userID) { diff --git a/UI/WebServerResources/UIxAppointmentEditor.js b/UI/WebServerResources/UIxAppointmentEditor.js index 91c58ecab..9f89c798f 100644 --- a/UI/WebServerResources/UIxAppointmentEditor.js +++ b/UI/WebServerResources/UIxAppointmentEditor.js @@ -43,36 +43,36 @@ function validateAptEditor() { e = $('summary'); if (e.value.length == 0) { - if (!confirm(labels.validate_notitle.decodeEntities())) + if (!confirm(labels.validate_notitle)) return false; } e = $('startTime_date'); if (e.value.length != 10) { - alert(labels.validate_invalid_startdate.decodeEntities()); + alert(labels.validate_invalid_startdate); return false; } startdate = e.calendar.prs_date(e.value); if (startdate == null) { - alert(labels.validate_invalid_startdate.decodeEntities()); + alert(labels.validate_invalid_startdate); return false; } e = $('endTime_date'); if (e.value.length != 10) { - alert(labels.validate_invalid_enddate.decodeEntities()); + alert(labels.validate_invalid_enddate); return false; } enddate = e.calendar.prs_date(e.value); if (enddate == null) { - alert(labels.validate_invalid_enddate.decodeEntities()); + alert(labels.validate_invalid_enddate); return false; } // cuicui = ''; tmpdate = uixEarlierDate(startdate, enddate); if (tmpdate == enddate) { // window.alert(cuicui); - alert(labels.validate_endbeforestart.decodeEntities()); + alert(labels.validate_endbeforestart); return false; } else if (tmpdate == null /* means: same date */) { @@ -83,14 +83,14 @@ function validateAptEditor() { end = parseInt(document.forms[0]['endTime_time_hour'].value); if (start > end) { - alert(labels.validate_endbeforestart.decodeEntities()); + alert(labels.validate_endbeforestart); return false; } else if (start == end) { start = parseInt(document.forms[0]['startTime_time_minute'].value); end = parseInt(document.forms[0]['endTime_time_minute'].value); if (start > end) { - alert(labels.validate_endbeforestart.decodeEntities()); + alert(labels.validate_endbeforestart); return false; } } diff --git a/UI/WebServerResources/UIxComponentEditor.js b/UI/WebServerResources/UIxComponentEditor.js index 82213035d..af61b807e 100644 --- a/UI/WebServerResources/UIxComponentEditor.js +++ b/UI/WebServerResources/UIxComponentEditor.js @@ -24,7 +24,7 @@ function onPopupUrlWindow(event) { preventDefault(event); var urlInput = document.getElementById("url"); - var newUrl = window.prompt(labels["Target:"].decodeEntities(), urlInput.value); + var newUrl = window.prompt(labels["Target:"], urlInput.value); if (newUrl != null) { var documentHref = $("documentHref"); var documentLabel = $("documentLabel"); diff --git a/UI/WebServerResources/UIxContactEditor.js b/UI/WebServerResources/UIxContactEditor.js index 32670f0bf..b17720dad 100644 --- a/UI/WebServerResources/UIxContactEditor.js +++ b/UI/WebServerResources/UIxContactEditor.js @@ -84,13 +84,13 @@ function validateContactEditor() { if (e.value.length == 0) return true; if (uixEmailRegex.test(e.value) != true) - return confirm(labels.invalidemailwarn.decodeEntities()); + return confirm(labels.invalidemailwarn); e = $('homeMail'); if (e.value.length == 0) return true; if (uixEmailRegex.test(e.value) != true) - return confirm(labels.invalidemailwarn.decodeEntities()); + return confirm(labels.invalidemailwarn); return true; } diff --git a/UI/WebServerResources/UIxMailEditor.js b/UI/WebServerResources/UIxMailEditor.js index d84345b71..bddc2b238 100644 --- a/UI/WebServerResources/UIxMailEditor.js +++ b/UI/WebServerResources/UIxMailEditor.js @@ -133,8 +133,7 @@ function validateEditorInput(sender) { errortext = errortext + labels.error_missingrecipients + "\n"; if (errortext.length > 0) { - alert(labels.error_validationfailed.decodeEntities() + ":\n" - + errortext.decodeEntities()); + alert(labels.error_validationfailed + ":\n" + errortext); return false; } return true; diff --git a/UI/WebServerResources/UIxTaskEditor.js b/UI/WebServerResources/UIxTaskEditor.js index b68d3dac9..5207d57e7 100644 --- a/UI/WebServerResources/UIxTaskEditor.js +++ b/UI/WebServerResources/UIxTaskEditor.js @@ -24,7 +24,7 @@ function validateDate(date, label) { dateValue = date.calendar.prs_date(date.value); if (date.value.length != 10 || !dateValue) { - alert(label.decodeEntities()); + alert(label); result = false; } else result = dateValue; @@ -37,7 +37,7 @@ function validateTaskEditor() { e = document.getElementById('summary'); if (e.value.length == 0 - && !confirm(labels.validate_notitle.decodeEntities())) + && !confirm(labels.validate_notitle)) return false; e = document.getElementById('startTime_date'); @@ -58,7 +58,7 @@ function validateTaskEditor() { tmpdate = uixEarlierDate(startdate, enddate); if (tmpdate == enddate) { // window.alert(cuicui); - alert(labels.validate_endbeforestart.decodeEntities()); + alert(labels.validate_endbeforestart); return false; } else if (tmpdate == null /* means: same date */) { @@ -69,14 +69,14 @@ function validateTaskEditor() { end = parseInt(document.forms[0]['dueTime_time_hour'].value); if (start > end) { - alert(labels.validate_endbeforestart.decodeEntities()); + alert(labels.validate_endbeforestart); return false; } else if (start == end) { start = parseInt(document.forms[0]['startTime_time_minute'].value); end = parseInt(document.forms[0]['dueTime_time_minute'].value); if (start > end) { - alert(labels.validate_endbeforestart.decodeEntities()); + alert(labels.validate_endbeforestart); return false; } } From beac7e7aeab0c37a8844e6853a2e3edf98d64700 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Fri, 14 Sep 2007 21:59:00 +0000 Subject: [PATCH 4/6] Monotone-Parent: 17441bc6502df80d7fa89d2f1beee98ac6e2c5d9 Monotone-Revision: c4c95e670daa9c22e838239469a51f3d23b84ab0 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-09-14T21:59:00 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 11 +++++ SoObjects/SOGo/SOGoObject.h | 9 +++- SoObjects/SOGo/SOGoObject.m | 92 ++++++++++++++++++++++++++++++++++++- 3 files changed, 109 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3556ea464..8ce905a88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2007-09-14 Wolfgang Sourdeau + + * SoObjects/SOGo/SOGoObject.m ([SOGoObject -labelForKey:key]): new + method that returns translated strings for controller bundles + (same as what UIxComponent does for view bundles). + ([SOGoObject -pathArrayToSOGoObject]): new method that returns + the real path to a subscribed folder (if subscribed). + ([SOGoObject +globallyUniqueObjectId]): move method from SOGoFolder. + ([SOGoObject -globallyUniqueObjectId]): new instance method + calling its class equivalent. + 2007-09-12 Wolfgang Sourdeau * UI/MainUI/SOGoRootPage.m ([SOGoRootPage -defaultAction]): test diff --git a/SoObjects/SOGo/SOGoObject.h b/SoObjects/SOGo/SOGoObject.h index 67142bfef..5404508a0 100644 --- a/SoObjects/SOGo/SOGoObject.h +++ b/SoObjects/SOGo/SOGoObject.h @@ -61,6 +61,9 @@ id container; } ++ (NSString *) globallyUniqueObjectId; +- (NSString *) globallyUniqueObjectId; + + (id) objectWithName: (NSString *)_name inContainer:(id)_container; - (id) initWithName: (NSString *) _name inContainer:(id)_container; @@ -70,11 +73,15 @@ - (NSString *) nameInContainer; - (id) container; +- (NSArray *) pathArrayToSOGoObject; + - (NSURL *) davURL; - (NSURL *) soURL; - (NSURL *) soURLToBaseContainerForUser: (NSString *) uid; - (NSURL *) soURLToBaseContainerForCurrentUser; +- (NSString *) labelForKey: (NSString *) key; + /* ownership */ - (void) setOwner: (NSString *) newOwner; @@ -100,7 +107,7 @@ /* etag support */ -- (NSException *)matchesRequestConditionInContext:(id)_ctx; +- (NSException *) matchesRequestConditionInContext:(id)_ctx; /* acls */ diff --git a/SoObjects/SOGo/SOGoObject.m b/SoObjects/SOGo/SOGoObject.m index 280211e53..31a6b6ce6 100644 --- a/SoObjects/SOGo/SOGoObject.m +++ b/SoObjects/SOGo/SOGoObject.m @@ -24,6 +24,9 @@ Please use gnustep-base instead. #endif +#import + +#import #import #import #import @@ -35,6 +38,7 @@ #import #import #import +#import #import #import #import @@ -52,6 +56,7 @@ #import "SOGoDAVRendererTypes.h" #import "NSArray+Utilities.h" +#import "NSDictionary+Utilities.h" #import "NSString+Utilities.h" #import "SOGoObject.h" @@ -179,6 +184,35 @@ static BOOL kontactGroupDAV = YES; // asDefaultForPermission: SoPerm_WebDAVAccess]; } ++ (NSString *) globallyUniqueObjectId +{ + /* + 4C08AE1A-A808-11D8-AC5A-000393BBAFF6 + SOGo-Web-28273-18283-288182 + printf( "%x", *(int *) &f); + */ + static int pid = 0; + static int sequence = 0; + static float rndm = 0; + float f; + + if (pid == 0) + { /* break if we fork ;-) */ + pid = getpid(); + rndm = random(); + } + sequence++; + f = [[NSDate date] timeIntervalSince1970]; + + return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X", + pid, (int) f, sequence++, random]; +} + +- (NSString *) globallyUniqueObjectId +{ + return [[self class] globallyUniqueObjectId]; +} + + (void) _fillDictionary: (NSMutableDictionary *) dictionary withDAVMethods: (NSString *) firstMethod, ... { @@ -447,6 +481,30 @@ static BOOL kontactGroupDAV = YES; return container; } +- (NSArray *) pathArrayToSOGoObject +{ + NSMutableArray *realPathArray; + NSString *objectName; + NSArray *objectDescription; + + realPathArray + = [NSMutableArray arrayWithArray: [self pathArrayToSoObject]]; + if ([realPathArray count] > 2) + { + objectName = [realPathArray objectAtIndex: 2]; + objectDescription = [objectName componentsSeparatedByString: @"_"]; + if ([objectDescription count] > 1) + { + [realPathArray replaceObjectAtIndex: 0 + withObject: [objectDescription objectAtIndex: 0]]; + [realPathArray replaceObjectAtIndex: 2 + withObject: [objectDescription objectAtIndex: 1]]; + } + } + + return realPathArray; +} + /* ownership */ - (void) setOwner: (NSString *) newOwner @@ -493,14 +551,16 @@ static BOOL kontactGroupDAV = YES; /* looking up shared objects */ -- (SOGoUserFolder *)lookupUserFolder { +- (SOGoUserFolder *) lookupUserFolder +{ if (![container respondsToSelector:_cmd]) return nil; return [container lookupUserFolder]; } -- (SOGoGroupsFolder *)lookupGroupsFolder { +- (SOGoGroupsFolder *) lookupGroupsFolder +{ return [[self lookupUserFolder] lookupGroupsFolder]; } @@ -905,6 +965,34 @@ static BOOL kontactGroupDAV = YES; return nil; } +- (NSString *) labelForKey: (NSString *) key +{ + NSString *userLanguage, *label; + NSArray *paths; + NSBundle *bundle; + NSDictionary *strings; + + bundle = [NSBundle bundleForClass: [self class]]; + if (!bundle) + bundle = [NSBundle mainBundle]; + + userLanguage = [[context activeUser] language]; + paths = [bundle pathsForResourcesOfType: @"strings" + inDirectory: [NSString stringWithFormat: @"%@.lproj", userLanguage] + forLocalization: userLanguage]; + if ([paths count] > 0) + { + strings = [NSDictionary dictionaryFromStringsFile: [paths objectAtIndex: 0]]; + label = [strings objectForKey: key]; + if (!label) + label = key; + } + else + label = key; + + return label; +} + /* description */ - (void)appendAttributesToDescription:(NSMutableString *)_ms { From e2340b4c9f592586b978272c3fddfdbb39a99940 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Fri, 14 Sep 2007 22:01:02 +0000 Subject: [PATCH 5/6] UI/Scheduler/Toolbars/SOGoAppointmentFolders.toolbar Monotone-Parent: c4c95e670daa9c22e838239469a51f3d23b84ab0 Monotone-Revision: 92e93f3527a76deed69fa61275517490d57f9a4f Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-09-14T22:01:02 Monotone-Branch: ca.inverse.sogo --- .../English.lproj/Localizable.strings | 1 + .../French.lproj/Localizable.strings | 1 + SoObjects/Appointments/GNUmakefile | 5 +- .../German.lproj/Localizable.strings | 1 + .../Appointments/SOGoAppointmentFolder.h | 4 +- .../Appointments/SOGoAppointmentFolder.m | 190 +++++------- .../Appointments/SOGoAppointmentObject.h | 7 - .../Appointments/SOGoAppointmentObject.m | 20 +- SoObjects/Appointments/SOGoTaskObject.h | 7 - SoObjects/Appointments/SOGoTaskObject.m | 16 +- SoObjects/Appointments/product.plist | 3 + .../English.lproj/Localizable.strings | 1 + .../Contacts/French.lproj/Localizable.strings | 1 + .../Contacts/German.lproj/Localizable.strings | 1 + SoObjects/Contacts/SOGoContactFolders.m | 19 +- SoObjects/Contacts/SOGoContactGCSFolder.m | 6 +- SoObjects/Contacts/SOGoContactLDAPFolder.m | 5 + SoObjects/Contacts/product.plist | 7 +- SoObjects/SOGo/NSDictionary+Utilities.h | 2 + SoObjects/SOGo/NSDictionary+Utilities.m | 20 ++ SoObjects/SOGo/SOGoContentObject.m | 6 +- SoObjects/SOGo/SOGoFolder.h | 16 +- SoObjects/SOGo/SOGoFolder.m | 180 +++++++---- SoObjects/SOGo/SOGoParentFolder.h | 3 +- SoObjects/SOGo/SOGoParentFolder.m | 71 ++++- SoObjects/SOGo/SOGoUserFolder.m | 18 +- UI/Common/English.lproj/Localizable.strings | 1 + UI/Common/French.lproj/Localizable.strings | 1 + UI/Common/GNUmakefile | 1 + UI/Common/German.lproj/Localizable.strings | 1 + UI/Common/UIxFolderActions.h | 2 +- UI/Common/UIxFolderActions.m | 109 ++++--- UI/Common/product.plist | 199 ++++++------ UI/Contacts/English.lproj/Localizable.strings | 2 + UI/Contacts/French.lproj/Localizable.strings | 2 + UI/Contacts/German.lproj/Localizable.strings | 2 + UI/Contacts/UIxContactEditor.m | 4 +- UI/Contacts/UIxContactFoldersView.m | 146 ++++----- UI/Contacts/UIxContactsListView.m | 19 -- UI/Contacts/UIxContactsListViewContainer.h | 12 +- UI/Contacts/UIxContactsListViewContainer.m | 65 +--- UI/Contacts/product.plist | 10 - UI/MainUI/SOGoRootPage.m | 2 +- UI/MainUI/product.plist | 8 + UI/PreferencesUI/UIxPreferences.m | 3 +- .../English.lproj/Localizable.strings | 7 +- UI/Scheduler/French.lproj/Localizable.strings | 7 +- UI/Scheduler/GNUmakefile | 2 +- UI/Scheduler/German.lproj/Localizable.strings | 7 +- ...toolbar => SOGoAppointmentFolders.toolbar} | 0 UI/Scheduler/UIxAppointmentEditor.m | 10 +- UI/Scheduler/UIxCalListingActions.m | 82 ++--- UI/Scheduler/UIxCalMainView.m | 10 + UI/Scheduler/UIxCalendarSelector.h | 20 +- UI/Scheduler/UIxCalendarSelector.m | 133 ++++---- UI/Scheduler/UIxComponentEditor.m | 12 +- UI/Scheduler/UIxTaskEditor.m | 10 +- UI/Scheduler/product.plist | 53 +++- .../UIxContactsListViewContainer.wox | 9 +- UI/Templates/SchedulerUI/UIxCalMainView.wox | 3 + .../SchedulerUI/UIxCalendarSelector.wox | 22 +- UI/Templates/UIxPageFrame.wox | 2 +- UI/WebServerResources/ContactsUI.js | 142 +++++---- UI/WebServerResources/SchedulerUI.js | 286 +++++++++++------- .../UIxContactsUserFolders.js | 2 +- UI/WebServerResources/add-user-calendar.png | Bin 0 -> 1168 bytes UI/WebServerResources/generic.js | 103 +++++-- 67 files changed, 1130 insertions(+), 992 deletions(-) create mode 100644 SoObjects/Appointments/English.lproj/Localizable.strings create mode 100644 SoObjects/Appointments/French.lproj/Localizable.strings create mode 100644 SoObjects/Appointments/German.lproj/Localizable.strings create mode 100644 SoObjects/Contacts/English.lproj/Localizable.strings create mode 100644 SoObjects/Contacts/French.lproj/Localizable.strings create mode 100644 SoObjects/Contacts/German.lproj/Localizable.strings rename UI/Scheduler/Toolbars/{SOGoAppointmentFolder.toolbar => SOGoAppointmentFolders.toolbar} (100%) create mode 100644 UI/WebServerResources/add-user-calendar.png diff --git a/SoObjects/Appointments/English.lproj/Localizable.strings b/SoObjects/Appointments/English.lproj/Localizable.strings new file mode 100644 index 000000000..95feda9fd --- /dev/null +++ b/SoObjects/Appointments/English.lproj/Localizable.strings @@ -0,0 +1 @@ +"Personal Calendar" = "Personal Calendar"; diff --git a/SoObjects/Appointments/French.lproj/Localizable.strings b/SoObjects/Appointments/French.lproj/Localizable.strings new file mode 100644 index 000000000..11b333c2a --- /dev/null +++ b/SoObjects/Appointments/French.lproj/Localizable.strings @@ -0,0 +1 @@ +"Personal Calendar" = "Agenda personnel"; diff --git a/SoObjects/Appointments/GNUmakefile b/SoObjects/Appointments/GNUmakefile index 789501a3d..0ae0a98f1 100644 --- a/SoObjects/Appointments/GNUmakefile +++ b/SoObjects/Appointments/GNUmakefile @@ -6,7 +6,9 @@ WOBUNDLE_NAME = Appointments Appointments_PRINCIPAL_CLASS = SOGoAppointmentsProduct -# Appointments_LANGUAGES = English French +Appointments_LANGUAGES = English French German + +Appointments_LOCALIZED_RESOURCE_FILES=Localizable.strings Appointments_OBJC_FILES = \ Product.m \ @@ -17,6 +19,7 @@ Appointments_OBJC_FILES = \ SOGoAppointmentObject.m \ SOGoTaskObject.m \ SOGoAppointmentFolder.m \ + SOGoAppointmentFolders.m \ SOGoGroupAppointmentFolder.m \ SOGoFreeBusyObject.m \ \ diff --git a/SoObjects/Appointments/German.lproj/Localizable.strings b/SoObjects/Appointments/German.lproj/Localizable.strings new file mode 100644 index 000000000..95feda9fd --- /dev/null +++ b/SoObjects/Appointments/German.lproj/Localizable.strings @@ -0,0 +1 @@ +"Personal Calendar" = "Personal Calendar"; diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.h b/SoObjects/Appointments/SOGoAppointmentFolder.h index f3e71cd8d..06edea0e6 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.h +++ b/SoObjects/Appointments/SOGoAppointmentFolder.h @@ -53,6 +53,8 @@ NSMutableDictionary *uidToFilename; } +- (BOOL) isActive; + /* selection */ - (NSArray *) calendarUIDs; @@ -113,8 +115,6 @@ - (NSArray *) fetchAllSOGoAppointments; -- (NSArray *) calendarFolders; - - (NSString *) roleForComponentsWithAccessClass: (iCalAccessClass) accessClass forUser: (NSString *) uid; diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 9fa1695fc..38c34a943 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -125,11 +125,6 @@ static NSNumber *sharedYes = nil; return logger; } -- (BOOL) folderIsMandatory -{ - return YES; -} - /* selection */ - (NSArray *) calendarUIDs @@ -746,7 +741,7 @@ static NSNumber *sharedYes = nil; privacySqlString = @"and (c_isopaque = 1)"; else { -#warning we do not manage all the user's possible emails +#warning we do not manage all the possible user emails email = [[activeUser primaryIdentity] objectForKey: @"email"]; privacySqlString @@ -905,7 +900,6 @@ static NSNumber *sharedYes = nil; component: _component]; } - - (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate to: (NSCalendarDate *) _endDate { @@ -1041,21 +1035,28 @@ static NSNumber *sharedYes = nil; /* Note: can return NSNull objects in the array! */ NSMutableArray *folders; NSEnumerator *e; - NSString *uid; - + NSString *uid, *ownerLogin; + id folder; + + ownerLogin = [self ownerInContext: context]; + if ([_uids count] == 0) return nil; folders = [NSMutableArray arrayWithCapacity:16]; e = [_uids objectEnumerator]; - while ((uid = [e nextObject])) { - id folder; + while ((uid = [e nextObject])) + { + if ([uid isEqualToString: ownerLogin]) + folder = self; + else + { + folder = [self lookupCalendarFolderForUID: uid]; + if (![folder isNotNull]) + [self logWithFormat:@"Note: did not find folder for uid: '%@'", uid]; + } - folder = [self lookupCalendarFolderForUID: uid]; - if (![folder isNotNull]) - [self logWithFormat:@"Note: did not find folder for uid: '%@'", uid]; - - /* Note: intentionally add 'null' folders to allow a mapping */ - [folders addObject:folder ? folder : [NSNull null]]; - } + [folders addObject: folder]; + } + return folders; } @@ -1196,67 +1197,67 @@ static NSNumber *sharedYes = nil; return events; } -#warning We only support ONE calendar per user at this time -- (BOOL) _appendSubscribedFolders: (NSDictionary *) subscribedFolders - toFolderList: (NSMutableArray *) calendarFolders -{ - NSEnumerator *keys; - NSString *currentKey; - NSMutableDictionary *currentCalendar; - BOOL firstShouldBeActive; - unsigned int count; +// #warning We only support ONE calendar per user at this time +// - (BOOL) _appendSubscribedFolders: (NSDictionary *) subscribedFolders +// toFolderList: (NSMutableArray *) calendarFolders +// { +// NSEnumerator *keys; +// NSString *currentKey; +// NSMutableDictionary *currentCalendar; +// BOOL firstShouldBeActive; +// unsigned int count; - firstShouldBeActive = YES; +// firstShouldBeActive = YES; - keys = [[subscribedFolders allKeys] objectEnumerator]; - currentKey = [keys nextObject]; - count = 1; - while (currentKey) - { - currentCalendar = [NSMutableDictionary new]; - [currentCalendar autorelease]; - [currentCalendar - setDictionary: [subscribedFolders objectForKey: currentKey]]; - [currentCalendar setObject: currentKey forKey: @"folder"]; - [calendarFolders addObject: currentCalendar]; - if ([[currentCalendar objectForKey: @"active"] boolValue]) - firstShouldBeActive = NO; - count++; - currentKey = [keys nextObject]; - } +// keys = [[subscribedFolders allKeys] objectEnumerator]; +// currentKey = [keys nextObject]; +// count = 1; +// while (currentKey) +// { +// currentCalendar = [NSMutableDictionary new]; +// [currentCalendar autorelease]; +// [currentCalendar +// setDictionary: [subscribedFolders objectForKey: currentKey]]; +// [currentCalendar setObject: currentKey forKey: @"folder"]; +// [calendarFolders addObject: currentCalendar]; +// if ([[currentCalendar objectForKey: @"active"] boolValue]) +// firstShouldBeActive = NO; +// count++; +// currentKey = [keys nextObject]; +// } - return firstShouldBeActive; -} +// return firstShouldBeActive; +// } -- (NSArray *) calendarFolders -{ - NSMutableDictionary *userCalendar, *calendarDict; - NSMutableArray *calendarFolders; - SOGoUser *calendarUser; - BOOL firstActive; +// - (NSArray *) calendarFolders +// { +// NSMutableDictionary *userCalendar, *calendarDict; +// NSMutableArray *calendarFolders; +// SOGoUser *calendarUser; +// BOOL firstActive; - calendarFolders = [NSMutableArray new]; - [calendarFolders autorelease]; +// calendarFolders = [NSMutableArray new]; +// [calendarFolders autorelease]; - calendarUser = [SOGoUser userWithLogin: [self ownerInContext: context] - roles: nil]; - userCalendar = [NSMutableDictionary new]; - [userCalendar autorelease]; - [userCalendar setObject: @"/" forKey: @"folder"]; - [userCalendar setObject: @"Calendar" forKey: @"displayName"]; - [calendarFolders addObject: userCalendar]; +// calendarUser = [SOGoUser userWithLogin: [self ownerInContext: context] +// roles: nil]; +// userCalendar = [NSMutableDictionary new]; +// [userCalendar autorelease]; +// [userCalendar setObject: @"/" forKey: @"folder"]; +// [userCalendar setObject: @"Calendar" forKey: @"displayName"]; +// [calendarFolders addObject: userCalendar]; - calendarDict = [[calendarUser userSettings] objectForKey: @"Calendar"]; - firstActive = [[calendarDict objectForKey: @"activateUserFolder"] boolValue]; - firstActive = ([self _appendSubscribedFolders: - [calendarDict objectForKey: @"SubscribedFolders"] - toFolderList: calendarFolders] - || firstActive); - [userCalendar setObject: [NSNumber numberWithBool: firstActive] - forKey: @"active"]; +// calendarDict = [[calendarUser userSettings] objectForKey: @"Calendar"]; +// firstActive = [[calendarDict objectForKey: @"activateUserFolder"] boolValue]; +// firstActive = ([self _appendSubscribedFolders: +// [calendarDict objectForKey: @"SubscribedFolders"] +// toFolderList: calendarFolders] +// || firstActive); +// [userCalendar setObject: [NSNumber numberWithBool: firstActive] +// forKey: @"active"]; - return calendarFolders; -} +// return calendarFolders; +// } // - (NSArray *) fetchContentObjectNames // { @@ -1297,49 +1298,16 @@ static NSNumber *sharedYes = nil; return @"IPF.Appointment"; } -/* hack until we permit more than 1 cal per user */ -- (NSArray *) _fixedPath: (NSArray *) objectPath +- (BOOL) isActive { - NSMutableArray *newPath; + NSUserDefaults *settings; + NSArray *activeFolders; - newPath = [NSMutableArray arrayWithArray: objectPath]; - if ([newPath count] > 2) - { - if (![[newPath objectAtIndex: 2] isEqualToString: @"personal"]) - [newPath insertObject: @"personal" atIndex: 2]; - } - else - [newPath addObject: @"personal"]; + settings = [[context activeUser] userSettings]; + activeFolders + = [[settings objectForKey: @"Calendar"] objectForKey: @"ActiveFolders"]; - return newPath; -} - -- (NSArray *) aclUsersForObjectAtPath: (NSArray *) objectPathArray -{ - return [super aclUsersForObjectAtPath: [self _fixedPath: objectPathArray]]; -} - -- (NSArray *) aclsForUser: (NSString *) uid - forObjectAtPath: (NSArray *) objectPathArray -{ - return [super aclsForUser: uid - forObjectAtPath: [self _fixedPath: objectPathArray]]; -} - -- (void) setRoles: (NSArray *) roles - forUser: (NSString *) uid - forObjectAtPath: (NSArray *) objectPathArray -{ - [super setRoles: roles - forUser: uid - forObjectAtPath: [self _fixedPath: objectPathArray]]; -} - -- (void) removeAclsForUsers: (NSArray *) users - forObjectAtPath: (NSArray *) objectPathArray -{ - [super removeAclsForUsers: users - forObjectAtPath: [self _fixedPath: objectPathArray]]; + return [activeFolders containsObject: nameInContainer]; } @end /* SOGoAppointmentFolder */ diff --git a/SoObjects/Appointments/SOGoAppointmentObject.h b/SoObjects/Appointments/SOGoAppointmentObject.h index d6fe91e86..8262970f2 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.h +++ b/SoObjects/Appointments/SOGoAppointmentObject.h @@ -46,13 +46,6 @@ @interface SOGoAppointmentObject : SOGoCalendarComponent -/* folder management */ - -- (id) lookupHomeFolderForUID: (NSString *) _uid - inContext: (id) _ctx; -- (NSArray *) lookupCalendarFoldersForUIDs: (NSArray *) _uids - inContext: (id) _ctx; - /* "iCal multifolder saves" */ - (NSException *) saveContentString: (NSString *) _iCal diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index 33e140282..404428ea7 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -34,6 +34,8 @@ #import #import "NSArray+Appointments.h" +#import "SOGoAppointmentFolder.h" + #import "SOGoAppointmentObject.h" @implementation SOGoAppointmentObject @@ -96,16 +98,6 @@ return uids; } -/* folder management */ - -- (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx { - // TODO: what does this do? lookup the home of the organizer? - return [[self container] lookupHomeFolderForUID:_uid inContext:_ctx]; -} -- (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx { - return [[self container] lookupCalendarFoldersForUIDs:_uids inContext:_ctx]; -} - /* store in all the other folders */ - (NSException *) saveContentString: (NSString *) _iCal @@ -115,8 +107,8 @@ id folder; NSException *allErrors = nil; - e = [[self lookupCalendarFoldersForUIDs:_uids inContext: context] - objectEnumerator]; + e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context] + objectEnumerator]; while ((folder = [e nextObject]) != nil) { NSException *error; SOGoAppointmentObject *apt; @@ -160,8 +152,8 @@ id folder; NSException *allErrors = nil; - e = [[self lookupCalendarFoldersForUIDs:_uids inContext: context] - objectEnumerator]; + e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context] + objectEnumerator]; while ((folder = [e nextObject])) { NSException *error; SOGoAppointmentObject *apt; diff --git a/SoObjects/Appointments/SOGoTaskObject.h b/SoObjects/Appointments/SOGoTaskObject.h index 9f57bf588..da442022b 100644 --- a/SoObjects/Appointments/SOGoTaskObject.h +++ b/SoObjects/Appointments/SOGoTaskObject.h @@ -44,13 +44,6 @@ @interface SOGoTaskObject : SOGoCalendarComponent -/* folder management */ - -- (id) lookupHomeFolderForUID: (NSString *) _uid - inContext: (id) _ctx; -- (NSArray *) lookupCalendarFoldersForUIDs: (NSArray *) _uids - inContext: (id) _ctx; - /* "iCal multifolder saves" */ - (NSException *) saveContentString: (NSString *) _iCal diff --git a/SoObjects/Appointments/SOGoTaskObject.m b/SoObjects/Appointments/SOGoTaskObject.m index 547d19e04..2357ac8b2 100644 --- a/SoObjects/Appointments/SOGoTaskObject.m +++ b/SoObjects/Appointments/SOGoTaskObject.m @@ -34,6 +34,7 @@ #import "NSArray+Appointments.h" #import "SOGoAptMailNotification.h" +#import "SOGoAppointmentFolder.h" #import "SOGoTaskObject.h" @@ -118,17 +119,6 @@ static NSString *mailTemplateDefaultLanguage = nil; return uids; } -/* folder management */ - -- (id)lookupHomeFolderForUID:(NSString *)_uid inContext:(id)_ctx { - // TODO: what does this do? lookup the home of the organizer? - return [[self container] lookupHomeFolderForUID:_uid inContext:_ctx]; -} - -- (NSArray *)lookupCalendarFoldersForUIDs:(NSArray *)_uids inContext:(id)_ctx { - return [[self container] lookupCalendarFoldersForUIDs:_uids inContext:_ctx]; -} - /* store in all the other folders */ - (NSException *)saveContentString:(NSString *)_iCal inUIDs:(NSArray *)_uids { @@ -136,7 +126,7 @@ static NSString *mailTemplateDefaultLanguage = nil; id folder; NSException *allErrors = nil; - e = [[self lookupCalendarFoldersForUIDs: _uids inContext: context] + e = [[container lookupCalendarFoldersForUIDs: _uids inContext: context] objectEnumerator]; while ((folder = [e nextObject]) != nil) { NSException *error; @@ -175,7 +165,7 @@ static NSString *mailTemplateDefaultLanguage = nil; id folder; NSException *allErrors = nil; - e = [[self lookupCalendarFoldersForUIDs: _uids inContext: context] + e = [[container lookupCalendarFoldersForUIDs: _uids inContext: context] objectEnumerator]; while ((folder = [e nextObject])) { NSException *error; diff --git a/SoObjects/Appointments/product.plist b/SoObjects/Appointments/product.plist index d70b2faad..1fdd67e88 100644 --- a/SoObjects/Appointments/product.plist +++ b/SoObjects/Appointments/product.plist @@ -8,6 +8,9 @@ }; classes = { + SOGoAppointmentFolder = { + superclass = "SOGoParentFolder"; + }; SOGoAppointmentFolder = { superclass = "SOGoFolder"; defaultRoles = { diff --git a/SoObjects/Contacts/English.lproj/Localizable.strings b/SoObjects/Contacts/English.lproj/Localizable.strings new file mode 100644 index 000000000..56404b013 --- /dev/null +++ b/SoObjects/Contacts/English.lproj/Localizable.strings @@ -0,0 +1 @@ +"Personal Address Book" = "Personal Address Book"; diff --git a/SoObjects/Contacts/French.lproj/Localizable.strings b/SoObjects/Contacts/French.lproj/Localizable.strings new file mode 100644 index 000000000..af4d87c3a --- /dev/null +++ b/SoObjects/Contacts/French.lproj/Localizable.strings @@ -0,0 +1 @@ +"Personal Address Book" = "Carnet d'adresses personnel"; diff --git a/SoObjects/Contacts/German.lproj/Localizable.strings b/SoObjects/Contacts/German.lproj/Localizable.strings new file mode 100644 index 000000000..95feda9fd --- /dev/null +++ b/SoObjects/Contacts/German.lproj/Localizable.strings @@ -0,0 +1 @@ +"Personal Calendar" = "Personal Calendar"; diff --git a/SoObjects/Contacts/SOGoContactFolders.m b/SoObjects/Contacts/SOGoContactFolders.m index dc3ffe256..2d75c8f0c 100644 --- a/SoObjects/Contacts/SOGoContactFolders.m +++ b/SoObjects/Contacts/SOGoContactFolders.m @@ -27,25 +27,11 @@ TaskItems IPF.Task JournalItems IPF.Journal */ -// #import #import #import #import -// #import -// #import -// #import -// #import -// #import -// #import - -// #import -// #import -// #import -// #import - #import -// #import #import "SOGoContactGCSFolder.h" #import "SOGoContactLDAPFolder.h" @@ -85,4 +71,9 @@ } } +- (NSString *) defaultFolderName +{ + return @"Personal Address Book"; +} + @end diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.m b/SoObjects/Contacts/SOGoContactGCSFolder.m index a3f603185..e00e96749 100644 --- a/SoObjects/Contacts/SOGoContactGCSFolder.m +++ b/SoObjects/Contacts/SOGoContactGCSFolder.m @@ -21,6 +21,7 @@ #import #import + #import #import #import @@ -41,11 +42,6 @@ @implementation SOGoContactGCSFolder -- (BOOL) folderIsMandatory -{ - return [nameInContainer isEqualToString: @"personal"]; -} - /* name lookup */ - (id ) lookupContactWithId: (NSString *) recordId diff --git a/SoObjects/Contacts/SOGoContactLDAPFolder.m b/SoObjects/Contacts/SOGoContactLDAPFolder.m index 841a79a00..459f2998e 100644 --- a/SoObjects/Contacts/SOGoContactLDAPFolder.m +++ b/SoObjects/Contacts/SOGoContactLDAPFolder.m @@ -257,6 +257,11 @@ } /* acls */ +- (NSString *) ownerInContext: (WOContext *) noContext +{ + return @"nobody"; +} + /* TODO: this might change one day when we support LDAP acls */ - (NSArray *) aclsForUser: (NSString *) uid { diff --git a/SoObjects/Contacts/product.plist b/SoObjects/Contacts/product.plist index cb6b5124d..e1557d613 100644 --- a/SoObjects/Contacts/product.plist +++ b/SoObjects/Contacts/product.plist @@ -9,12 +9,7 @@ classes = { SOGoContactFolders = { - superclass = "SOGoFolder"; - protectedBy = "Access Contents Information"; - defaultRoles = { - "Access Contents Information" = ( "Authenticated" ); - "WebDAV Access" = ( "Authenticated" ); - }; + superclass = "SOGoParentFolder"; }; SOGoContactGCSFolder = { superclass = "SOGoFolder"; diff --git a/SoObjects/SOGo/NSDictionary+Utilities.h b/SoObjects/SOGo/NSDictionary+Utilities.h index bc054c813..1c5622f13 100644 --- a/SoObjects/SOGo/NSDictionary+Utilities.h +++ b/SoObjects/SOGo/NSDictionary+Utilities.h @@ -29,6 +29,8 @@ @interface NSDictionary (SOGoDictionaryUtilities) ++ (NSDictionary *) dictionaryFromStringsFile: (NSString *) file; + - (NSString *) jsonRepresentation; - (NSString *) keysWithFormat: (NSString *) keyFormat; diff --git a/SoObjects/SOGo/NSDictionary+Utilities.m b/SoObjects/SOGo/NSDictionary+Utilities.m index 6caaeaa67..666aef023 100644 --- a/SoObjects/SOGo/NSDictionary+Utilities.m +++ b/SoObjects/SOGo/NSDictionary+Utilities.m @@ -21,6 +21,7 @@ */ #import +#import #import #import "NSArray+Utilities.h" @@ -29,6 +30,25 @@ @implementation NSDictionary (SOGoDictionaryUtilities) ++ (NSDictionary *) dictionaryFromStringsFile: (NSString *) file +{ + NSString *serialized; + NSMutableData *content; + NSDictionary *newDictionary; + + content = [NSMutableData new]; + [content appendBytes: "{" length: 1]; + [content appendData: [NSData dataWithContentsOfFile: file]]; + [content appendBytes: "}" length: 1]; + serialized = [[NSString alloc] initWithData: content + encoding: NSUTF8StringEncoding]; + [content release]; + newDictionary = [serialized propertyList]; + [serialized release]; + + return newDictionary; +} + - (NSString *) jsonRepresentation { NSMutableArray *values; diff --git a/SoObjects/SOGo/SOGoContentObject.m b/SoObjects/SOGo/SOGoContentObject.m index 945382da5..255db3b65 100644 --- a/SoObjects/SOGo/SOGoContentObject.m +++ b/SoObjects/SOGo/SOGoContentObject.m @@ -231,7 +231,7 @@ needsLocation = NO; tmp = [[self nameInContainer] stringByDeletingPathExtension]; if ([tmp isEqualToString:@"new"]) { - tmp = [[[self container] class] globallyUniqueObjectId]; + tmp = [self globallyUniqueObjectId]; needsLocation = YES; [self debugWithFormat: @@ -359,7 +359,7 @@ - (NSArray *) aclUsers { - return [container aclUsersForObjectAtPath: [self pathArrayToSoObject]]; + return [container aclUsersForObjectAtPath: [self pathArrayToSOGoObject]]; } - (NSArray *) aclsForUser: (NSString *) uid @@ -369,7 +369,7 @@ acls = [NSMutableArray array]; ownAcls = [container aclsForUser: uid - forObjectAtPath: [self pathArrayToSoObject]]; + forObjectAtPath: [self pathArrayToSOGoObject]]; [acls addObjectsFromArray: ownAcls]; containerAcls = [container aclsForUser: uid]; if ([containerAcls count] > 0) diff --git a/SoObjects/SOGo/SOGoFolder.h b/SoObjects/SOGo/SOGoFolder.h index dad4629ad..ed57b8059 100644 --- a/SoObjects/SOGo/SOGoFolder.h +++ b/SoObjects/SOGo/SOGoFolder.h @@ -43,23 +43,18 @@ @interface SOGoFolder : SOGoObject { - NSString *displayName; + NSMutableString *displayName; NSString *ocsPath; GCSFolder *ocsFolder; NSMutableDictionary *aclCache; } -+ (NSString *) globallyUniqueObjectId; ++ (id) folderWithSubscriptionReference: (NSString *) reference + inContainer: (id) aContainer; /* accessors */ -+ (id) folderWithName: (NSString *) aName - andDisplayName: (NSString *) aDisplayName - inContainer: (id) aContainer; -- (id) initWithName: (NSString *) aName - andDisplayName: (NSString *) aDisplayName - inContainer: (id) aContainer; - +- (void) setDisplayName: (NSString *) newDisplayName; - (NSString *) displayName; - (void) setOCSPath: (NSString *)_Path; @@ -79,10 +74,11 @@ - (NSString *) outlookFolderClass; - (BOOL) folderIsMandatory; +- (NSString *) folderType; - (BOOL) create; - (NSException *) delete; - +- (void) renameTo: (NSString *) newName; /* dav */ - (NSArray *) davNamespaces; diff --git a/SoObjects/SOGo/SOGoFolder.m b/SoObjects/SOGo/SOGoFolder.m index 18d2d4856..a78d50740 100644 --- a/SoObjects/SOGo/SOGoFolder.m +++ b/SoObjects/SOGo/SOGoFolder.m @@ -19,9 +19,6 @@ 02111-1307, USA. */ -#import -#import - #import #import #import @@ -38,9 +35,11 @@ #import #import #import +#import #import #import #import +#import #import #import "NSArray+Utilities.h" @@ -67,40 +66,29 @@ static NSString *defaultUserID = @""; NSStringFromClass([self superclass]), [super version]); } -+ (NSString *) globallyUniqueObjectId -{ - /* - 4C08AE1A-A808-11D8-AC5A-000393BBAFF6 - SOGo-Web-28273-18283-288182 - printf( "%x", *(int *) &f); - */ - static int pid = 0; - static int sequence = 0; - static float rndm = 0; - float f; - - if (pid == 0) - { /* break if we fork ;-) */ - pid = getpid(); - rndm = random(); - } - sequence++; - f = [[NSDate date] timeIntervalSince1970]; - - return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X", - pid, (int) f, sequence++, random]; -} - -+ (id) folderWithName: (NSString *) aName - andDisplayName: (NSString *) aDisplayName - inContainer: (id) aContainer ++ (id) folderWithSubscriptionReference: (NSString *) reference + inContainer: (id) aContainer { id newFolder; + NSArray *elements, *pathElements; + NSString *ocsPath, *objectPath, *owner, *ocsName, *folderName; - newFolder = [[self alloc] initWithName: aName - andDisplayName: aDisplayName + elements = [reference componentsSeparatedByString: @":"]; + owner = [elements objectAtIndex: 0]; + objectPath = [elements objectAtIndex: 1]; + pathElements = [objectPath componentsSeparatedByString: @"/"]; + if ([pathElements count] > 1) + ocsName = [pathElements objectAtIndex: 1]; + else + ocsName = @"personal"; + + ocsPath = [NSString stringWithFormat: @"/Users/%@/%@/%@", + owner, [pathElements objectAtIndex: 0], ocsName]; + folderName = [NSString stringWithFormat: @"%@_%@", owner, ocsName]; + newFolder = [[self alloc] initWithName: folderName inContainer: aContainer]; - [newFolder autorelease]; + [newFolder setOCSPath: ocsPath]; + [newFolder setOwner: owner]; return newFolder; } @@ -118,17 +106,6 @@ static NSString *defaultUserID = @""; return self; } -- (id) initWithName: (NSString *) aName - andDisplayName: (NSString *) aDisplayName - inContainer: (id) aContainer -{ - if ((self = [self initWithName: aName - inContainer: aContainer])) - ASSIGN (displayName, aDisplayName); - - return self; -} - - (void) dealloc { [ocsFolder release]; @@ -147,13 +124,12 @@ static NSString *defaultUserID = @""; - (void) setOCSPath: (NSString *) _path { - if ([ocsPath isEqualToString:_path]) - return; - - if (ocsPath) - [self warnWithFormat:@"GCS path is already set! '%@'", _path]; - - ASSIGNCOPY(ocsPath, _path); + if (![ocsPath isEqualToString:_path]) + { + if (ocsPath) + [self warnWithFormat: @"GCS path is already set! '%@'", _path]; + ASSIGN (ocsPath, _path); + } } - (NSString *) ocsPath @@ -178,16 +154,75 @@ static NSString *defaultUserID = @""; - (BOOL) folderIsMandatory { - [self subclassResponsibility: _cmd]; + return [nameInContainer isEqualToString: @"personal"]; +} - return NO; +- (void) _setDisplayNameFromRow: (NSDictionary *) row +{ + NSString *currentLogin, *ownerLogin; + NSDictionary *ownerIdentity; + + displayName + = [NSMutableString stringWithString: [row objectForKey: @"c_foldername"]]; + currentLogin = [[context activeUser] login]; + ownerLogin = [self ownerInContext: context]; + if (![currentLogin isEqualToString: ownerLogin]) + { + ownerIdentity = [[SOGoUser userWithLogin: ownerLogin roles: nil] + primaryIdentity]; + [displayName appendFormat: @" (%@ <%@>)", + [ownerIdentity objectForKey: @"fullName"], + [ownerIdentity objectForKey: @"email"]]; + } +} + +- (void) _fetchDisplayName +{ + GCSChannelManager *cm; + EOAdaptorChannel *fc; + NSURL *folderLocation; + NSString *sql; + NSArray *attrs; + NSDictionary *row; + + cm = [GCSChannelManager defaultChannelManager]; + folderLocation + = [[GCSFolderManager defaultFolderManager] folderInfoLocation]; + fc = [cm acquireOpenChannelForURL: folderLocation]; + if (fc) + { + sql + = [NSString stringWithFormat: (@"SELECT c_foldername FROM %@" + @" WHERE c_path = '%@'"), + [folderLocation gcsTableName], ocsPath]; + [fc evaluateExpressionX: sql]; + attrs = [fc describeResults: NO]; + row = [fc fetchAttributes: attrs withZone: NULL]; + if (row) + [self _setDisplayNameFromRow: row]; + [fc cancelFetch]; + [cm releaseChannel: fc]; + } +} + +- (void) setDisplayName: (NSString *) newDisplayName +{ + ASSIGN (displayName, newDisplayName); } - (NSString *) displayName { + if (!displayName) + [self _fetchDisplayName]; + return displayName; } +- (NSString *) davDisplayName +{ + return [self displayName]; +} + - (GCSFolder *) ocsFolder { GCSFolder *folder; @@ -222,7 +257,9 @@ static NSString *defaultUserID = @""; { NSException *result; +// [self dieHard]; result = [[self folderManager] createFolderOfType: [self folderType] + withName: displayName atPath: ocsPath]; return (result == nil); @@ -234,13 +271,40 @@ static NSString *defaultUserID = @""; if ([nameInContainer isEqualToString: @"personal"]) error = [NSException exceptionWithHTTPStatus: 403 - reason: @"the 'personal' folder cannot be deleted"]; + reason: @"folder 'personal' cannot be deleted"]; else error = [[self folderManager] deleteFolderAtPath: ocsPath]; return error; } +- (void) renameTo: (NSString *) newName +{ + GCSChannelManager *cm; + EOAdaptorChannel *fc; + NSURL *folderLocation; + NSString *sql; + + [displayName release]; + displayName = nil; + + cm = [GCSChannelManager defaultChannelManager]; + folderLocation + = [[GCSFolderManager defaultFolderManager] folderInfoLocation]; + fc = [cm acquireOpenChannelForURL: folderLocation]; + if (fc) + { + sql + = [NSString stringWithFormat: (@"UPDATE %@ SET c_foldername = '%@'" + @" WHERE c_path = '%@'"), + [folderLocation gcsTableName], newName, ocsPath]; + [fc evaluateExpressionX: sql]; + [cm releaseChannel: fc]; +// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'", +// uidColumnName, [self uid]]; + } +} + - (NSArray *) fetchContentObjectNames { NSArray *fields, *records; @@ -512,7 +576,7 @@ static NSString *defaultUserID = @""; /* acls */ - (NSArray *) aclUsers { - return [self aclUsersForObjectAtPath: [self pathArrayToSoObject]]; + return [self aclUsersForObjectAtPath: [self pathArrayToSOGoObject]]; } - (NSArray *) aclsForUser: (NSString *) uid @@ -522,7 +586,7 @@ static NSString *defaultUserID = @""; acls = [NSMutableArray array]; ownAcls = [self aclsForUser: uid - forObjectAtPath: [self pathArrayToSoObject]]; + forObjectAtPath: [self pathArrayToSOGoObject]]; [acls addObjectsFromArray: ownAcls]; if ([container respondsToSelector: @selector (aclsForUser:)]) { @@ -545,13 +609,13 @@ static NSString *defaultUserID = @""; { return [self setRoles: roles forUser: uid - forObjectAtPath: [self pathArrayToSoObject]]; + forObjectAtPath: [self pathArrayToSOGoObject]]; } - (void) removeAclsForUsers: (NSArray *) users { return [self removeAclsForUsers: users - forObjectAtPath: [self pathArrayToSoObject]]; + forObjectAtPath: [self pathArrayToSOGoObject]]; } - (NSString *) defaultUserID diff --git a/SoObjects/SOGo/SOGoParentFolder.h b/SoObjects/SOGo/SOGoParentFolder.h index 5bbde0bc6..c54d08f87 100644 --- a/SoObjects/SOGo/SOGoParentFolder.h +++ b/SoObjects/SOGo/SOGoParentFolder.h @@ -43,7 +43,8 @@ - (NSArray *) subFolders; -- (NSException *) newFolderWithName: (NSString *) name; +- (NSException *) newFolderWithName: (NSString *) name + nameInContainer: (NSString **) newNameInContainer; @end diff --git a/SoObjects/SOGo/SOGoParentFolder.m b/SoObjects/SOGo/SOGoParentFolder.m index 2bd1f6963..6bdf0f783 100644 --- a/SoObjects/SOGo/SOGoParentFolder.m +++ b/SoObjects/SOGo/SOGoParentFolder.m @@ -22,14 +22,17 @@ #import #import +#import #import +#import #import #import #import #import #import "SOGoFolder.h" +#import "SOGoUser.h" #import "SOGoParentFolder.h" @@ -73,6 +76,11 @@ ASSIGN (OCSPath, newOCSPath); } +- (NSString *) defaultFolderName +{ + return @"Personal"; +} + - (void) _fetchPersonalFolders: (NSString *) sql withChannel: (EOAdaptorChannel *) fc { @@ -80,7 +88,7 @@ NSDictionary *row; SOGoFolder *folder; BOOL hasPersonal; - NSString *key, *path; + NSString *key, *path, *personalName; if (!subFolderClass) subFolderClass = [[self class] subFolderClass]; @@ -92,8 +100,7 @@ while (row) { folder - = [subFolderClass folderWithName: [row objectForKey: @"c_path4"] - andDisplayName: [row objectForKey: @"c_foldername"] + = [subFolderClass objectWithName: [row objectForKey: @"c_path4"] inContainer: self]; key = [row objectForKey: @"c_path4"]; hasPersonal = (hasPersonal || [key isEqualToString: @"personal"]); @@ -105,9 +112,9 @@ if (!hasPersonal) { - folder = [subFolderClass folderWithName: @"personal" - andDisplayName: @"personal" - inContainer: self]; + folder = [subFolderClass objectWithName: @"personal" inContainer: self]; + personalName = [self labelForKey: [self defaultFolderName]]; + [folder setDisplayName: personalName]; path = [NSString stringWithFormat: @"/Users/%@/%@/personal", [self ownerInContext: context], nameInContainer]; @@ -132,7 +139,7 @@ gcsFolderType = [[self class] gcsFolderType]; sql - = [NSString stringWithFormat: (@"SELECT c_path4, c_foldername FROM %@" + = [NSString stringWithFormat: (@"SELECT c_path4 FROM %@" @" WHERE c_path2 = '%@'" @" AND c_folder_type = '%@'"), [folderLocation gcsTableName], @@ -149,25 +156,58 @@ { } -- (NSException *) newFolderWithName: (NSString *) name +- (void) appendSubscribedSources { + NSArray *subscribedReferences; + NSUserDefaults *settings; + NSEnumerator *allKeys; + NSString *currentKey; + SOGoFolder *subscribedFolder; + + settings = [[context activeUser] userSettings]; + subscribedReferences = [[settings objectForKey: nameInContainer] + objectForKey: @"SubscribedFolders"]; + if ([subscribedReferences isKindOfClass: [NSArray class]]) + { + allKeys = [subscribedReferences objectEnumerator]; + currentKey = [allKeys nextObject]; + while (currentKey) + { + subscribedFolder + = [subFolderClass folderWithSubscriptionReference: currentKey + inContainer: self]; + [subFolders setObject: subscribedFolder + forKey: [subscribedFolder nameInContainer]]; + currentKey = [allKeys nextObject]; + } + } +} + +- (NSException *) newFolderWithName: (NSString *) name + nameInContainer: (NSString **) newNameInContainer +{ + NSString *newFolderID; SOGoFolder *newFolder; NSException *error; if (!subFolderClass) subFolderClass = [[self class] subFolderClass]; - newFolder = [subFolderClass folderWithName: name - andDisplayName: name - inContainer: self]; + *newNameInContainer = nil; + newFolderID = [self globallyUniqueObjectId]; + newFolder = [subFolderClass objectWithName: newFolderID inContainer: self]; if ([newFolder isKindOfClass: [NSException class]]) error = (NSException *) newFolder; else { + [newFolder setDisplayName: name]; [newFolder setOCSPath: [NSString stringWithFormat: @"%@/%@", - OCSPath, name]]; + OCSPath, newFolderID]]; if ([newFolder create]) - error = nil; + { + error = nil; + *newNameInContainer = newFolderID; + } else error = [NSException exceptionWithHTTPStatus: 400 reason: @"The new folder could not be created"]; @@ -178,11 +218,16 @@ - (void) initSubFolders { + NSString *login; + if (!subFolders) { subFolders = [NSMutableDictionary new]; [self appendPersonalSources]; [self appendSystemSources]; + login = [[context activeUser] login]; + if ([login isEqualToString: owner]) + [self appendSubscribedSources]; } } diff --git a/SoObjects/SOGo/SOGoUserFolder.m b/SoObjects/SOGo/SOGoUserFolder.m index 10194d27a..84297af23 100644 --- a/SoObjects/SOGo/SOGoUserFolder.m +++ b/SoObjects/SOGo/SOGoUserFolder.m @@ -26,7 +26,7 @@ #import #import -#import +#import #import #import #import @@ -117,7 +117,7 @@ - (NSString *) ocsPrivateCalendarPath { - return [[self ocsUserPath] stringByAppendingString:@"/Calendar/personal"]; + return [[self ocsUserPath] stringByAppendingString:@"/Calendar"]; } - (NSString *) ocsPrivateContactsPath @@ -134,15 +134,15 @@ // : [super permissionForKey: key]); // } -- (SOGoAppointmentFolder *) privateCalendar: (NSString *) _key - inContext: (WOContext *) _ctx +- (SOGoAppointmentFolders *) privateCalendars: (NSString *) _key + inContext: (WOContext *) _ctx { - SOGoAppointmentFolder *calendar; + SOGoAppointmentFolders *calendars; - calendar = [$(@"SOGoAppointmentFolder") objectWithName: _key inContainer: self]; - [calendar setOCSPath: [self ocsPrivateCalendarPath]]; + calendars = [$(@"SOGoAppointmentFolders") objectWithName: _key inContainer: self]; + [calendars setBaseOCSPath: [self ocsPrivateCalendarPath]]; - return calendar; + return calendars; } - (SOGoContactFolders *) privateContacts: (NSString *) _key @@ -185,7 +185,7 @@ if (!obj) { if ([_key isEqualToString: @"Calendar"]) - obj = [self privateCalendar: @"Calendar" inContext: _ctx]; + obj = [self privateCalendars: @"Calendar" inContext: _ctx]; // if (![_key isEqualToString: @"Calendar"]) // obj = [obj lookupName: [_key pathExtension] // inContext: _ctx acquire: NO]; diff --git a/UI/Common/English.lproj/Localizable.strings b/UI/Common/English.lproj/Localizable.strings index 9af10007e..9f20244c8 100644 --- a/UI/Common/English.lproj/Localizable.strings +++ b/UI/Common/English.lproj/Localizable.strings @@ -32,3 +32,4 @@ "You cannot subscribe to a folder that you own!" = "You cannot subscribe to a folder that you own!"; "Unable to unsubscribe from that folder!" = "Unable to unsubscribe from that folder!"; "You cannot unsubscribe from a folder that you own!" = "You cannot unsubscribe from a folder that you own!"; +"Unable to rename that folder!" = "Unable to rename that folder!"; diff --git a/UI/Common/French.lproj/Localizable.strings b/UI/Common/French.lproj/Localizable.strings index 18a984d3b..e77de6d77 100644 --- a/UI/Common/French.lproj/Localizable.strings +++ b/UI/Common/French.lproj/Localizable.strings @@ -33,3 +33,4 @@ "You cannot subscribe to a folder that you own!" = "Impossible de vous abonner à un dossier qui vous appartient."; "Unable to unsubscribe from that folder!" = "Impossible de se désabonner de ce dossier."; "You cannot unsubscribe from a folder that you own!" = "Impossible de vous désabonner d'un dossier qui vous appartient."; +"Unable to rename that folder!" = "Impossible de renommer ce dossier."; diff --git a/UI/Common/GNUmakefile b/UI/Common/GNUmakefile index ebdc4fea9..80a1a5943 100644 --- a/UI/Common/GNUmakefile +++ b/UI/Common/GNUmakefile @@ -17,6 +17,7 @@ CommonUI_OBJC_FILES += \ UIxAclEditor.m \ UIxObjectActions.m \ UIxFolderActions.m \ + UIxParentFolderActions.m \ UIxElemBuilder.m \ UIxTabView.m \ UIxTabItem.m \ diff --git a/UI/Common/German.lproj/Localizable.strings b/UI/Common/German.lproj/Localizable.strings index d1b779ba6..9a0bb6969 100644 --- a/UI/Common/German.lproj/Localizable.strings +++ b/UI/Common/German.lproj/Localizable.strings @@ -35,3 +35,4 @@ "You cannot subscribe to a folder that you own!" = "Unmöglich sich an einem Ordner zu abonnieren, der Ihnen selbst gehört."; "Unable to unsubscribe from that folder!" = "Unmöglich sich von diesem Ordner zu des-abonnieren."; "You cannot unsubscribe from a folder that you own!" = "Unmöglich sich von einem Ordner zu des-abonnieren, der Ihnen selbst gehört."; +"Unable to rename that folder!" = "Unable to rename that folder!"; diff --git a/UI/Common/UIxFolderActions.h b/UI/Common/UIxFolderActions.h index b74a20a30..8794bbeab 100644 --- a/UI/Common/UIxFolderActions.h +++ b/UI/Common/UIxFolderActions.h @@ -41,7 +41,7 @@ NSString *owner; NSString *login; NSString *baseFolder; - NSMutableString *subscriptionPointer; + NSString *subscriptionPointer; NSMutableDictionary *moduleSettings; BOOL isMailInvitation; } diff --git a/UI/Common/UIxFolderActions.m b/UI/Common/UIxFolderActions.m index b7a469a00..e152ed335 100644 --- a/UI/Common/UIxFolderActions.m +++ b/UI/Common/UIxFolderActions.m @@ -33,8 +33,9 @@ #import #import +#import #import -#import +#import #import #import "WODirectAction+SOGo.h" @@ -74,21 +75,19 @@ } [ud setObject: moduleSettings forKey: baseFolder]; - subscriptionPointer = [NSMutableString stringWithFormat: @"%@:%@", - owner, baseFolder]; - if ([baseFolder isEqualToString: @"Contacts"]) - [subscriptionPointer appendFormat: @"/%@", - [clientObject nameInContainer]]; + subscriptionPointer = [NSString stringWithFormat: @"%@:%@/%@", + owner, baseFolder, + [clientObject nameInContainer]]; mailInvitationParam = [[context request] formValueForKey: @"mail-invitation"]; isMailInvitation = [mailInvitationParam boolValue]; } -- (WOResponse *) _realActionWithFolderName: (NSDictionary *) folderDict +- (WOResponse *) _realSubscribe: (BOOL) reallyDo { WOResponse *response; - NSMutableDictionary *folderSubscription; + NSMutableArray *folderSubscription; NSString *mailInvitationURL; if ([owner isEqualToString: login]) @@ -101,17 +100,17 @@ { folderSubscription = [moduleSettings objectForKey: @"SubscribedFolders"]; - if (!folderSubscription) + if (!(folderSubscription + && [folderSubscription isKindOfClass: [NSMutableArray class]])) { - folderSubscription = [NSMutableDictionary dictionary]; + folderSubscription = [NSMutableArray array]; [moduleSettings setObject: folderSubscription forKey: @"SubscribedFolders"]; } - if (folderDict) - [folderSubscription setObject: folderDict - forKey: subscriptionPointer]; + if (reallyDo) + [folderSubscription addObjectUniquely: subscriptionPointer]; else - [folderSubscription removeObjectForKey: subscriptionPointer]; + [folderSubscription removeObject: subscriptionPointer]; [ud synchronize]; @@ -133,32 +132,16 @@ - (WOResponse *) subscribeAction { - NSString *email; - NSMutableDictionary *folderDict; - NSString *folderName; - [self _setupContext]; - email = [NSString stringWithFormat: @"%@ <%@>", - [um getCNForUID: owner], - [um getEmailForUID: owner]]; - if ([baseFolder isEqualToString: @"Contacts"]) - folderName = [NSString stringWithFormat: @"%@ (%@)", - [clientObject nameInContainer], email]; - else - folderName = email; - folderDict = [NSMutableDictionary dictionary]; - [folderDict setObject: folderName forKey: @"displayName"]; - [folderDict setObject: [NSNumber numberWithBool: NO] forKey: @"active"]; - - return [self _realActionWithFolderName: folderDict]; + return [self _realSubscribe: YES]; } - (WOResponse *) unsubscribeAction { [self _setupContext]; - return [self _realActionWithFolderName: nil]; + return [self _realSubscribe: NO]; } - (WOResponse *) canAccessContentAction @@ -168,26 +151,24 @@ - (WOResponse *) _realFolderActivation: (BOOL) makeActive { - NSMutableDictionary *folderSubscription, *folderDict; - NSNumber *active; - + NSMutableArray *folderSubscription; + NSString *folderName; + [self _setupContext]; - active = [NSNumber numberWithBool: makeActive]; - if ([owner isEqualToString: login]) - [moduleSettings setObject: active forKey: @"activateUserFolder"]; - else + folderSubscription + = [moduleSettings objectForKey: @"ActiveFolders"]; + if (!folderSubscription) { - folderSubscription - = [moduleSettings objectForKey: @"SubscribedFolders"]; - if (folderSubscription) - { - folderDict = [folderSubscription objectForKey: subscriptionPointer]; - if (folderDict) - [folderDict setObject: active - forKey: @"active"]; - } + folderSubscription = [NSMutableArray array]; + [moduleSettings setObject: folderSubscription forKey: @"ActiveFolders"]; } + folderName = [clientObject nameInContainer]; + if (makeActive) + [folderSubscription addObjectUniquely: folderName]; + else + [folderSubscription removeObject: folderName]; + [ud synchronize]; return [self responseWith204]; @@ -203,4 +184,36 @@ return [self _realFolderActivation: NO]; } +- (WOResponse *) deleteFolderAction +{ + WOResponse *response; + + response = (WOResponse *) [[self clientObject] delete]; + if (!response) + response = [self responseWith204]; + + return response; +} + +- (WOResponse *) renameFolderAction +{ + WOResponse *response; + NSString *folderName; + + folderName = [[context request] formValueForKey: @"name"]; + if ([folderName length] > 0) + { + clientObject = [self clientObject]; + [clientObject renameTo: folderName]; + response = [self responseWith204]; + } + else + { + response = [self responseWithStatus: 500]; + [response appendContentString: @"Missing 'name' parameter."]; + } + + return response; +} + @end diff --git a/UI/Common/product.plist b/UI/Common/product.plist index 9e014e8e9..704880c10 100644 --- a/UI/Common/product.plist +++ b/UI/Common/product.plist @@ -1,95 +1,114 @@ -{ /* -*-javascript-*- */ - requires = ( MAIN, Mailer ); +{ /* -*-java-*- */ + 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.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 + ); - 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.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 = { + }; - factories = { - }; - - categories = { - SOGoObject = { - methods = { - addUserInAcls = { - protectedBy = "SaveAcls"; - actionClass = "UIxObjectActions"; - actionName = "addUserInAcls"; - }; - removeUserFromAcls = { - protectedBy = "SaveAcls"; - actionClass = "UIxObjectActions"; - actionName = "removeUserFromAcls"; - }; - acls = { - protectedBy = "ReadAcls"; - pageName = "UIxAclEditor"; - }; - saveAcls = { - protectedBy = "SaveAcls"; - pageName = "UIxAclEditor"; - actionName = "saveAcls"; - }; - userRights = { - protectedBy = "ReadAcls"; - pageName = "UIxUserRightsEditor"; - }; - saveUserRights = { - protectedBy = "ReadAcls"; - pageName = "UIxUserRightsEditor"; - actionName = "saveUserRights"; - }; - }; + categories = { + SOGoObject = { + methods = { + addUserInAcls = { + protectedBy = "SaveAcls"; + actionClass = "UIxObjectActions"; + actionName = "addUserInAcls"; + }; + removeUserFromAcls = { + protectedBy = "SaveAcls"; + actionClass = "UIxObjectActions"; + actionName = "removeUserFromAcls"; + }; + acls = { + protectedBy = "ReadAcls"; + pageName = "UIxAclEditor"; + }; + saveAcls = { + protectedBy = "SaveAcls"; + pageName = "UIxAclEditor"; + actionName = "saveAcls"; + }; + userRights = { + protectedBy = "ReadAcls"; + pageName = "UIxUserRightsEditor"; + }; + saveUserRights = { + protectedBy = "ReadAcls"; + pageName = "UIxUserRightsEditor"; + actionName = "saveUserRights"; + }; }; - SOGoFolder = { - methods = { - subscribe = { - protectedBy = ""; - actionClass = "UIxFolderActions"; - actionName = "subscribe"; - }; - unsubscribe = { - protectedBy = ""; - actionClass = "UIxFolderActions"; - actionName = "unsubscribe"; - }; - canAccessContent = { - protectedBy = ""; - actionClass = "UIxFolderActions"; - actionName = "canAccessContent"; - }; - activateFolder = { - protectedBy = ""; - actionClass = "UIxFolderActions"; - actionName = "activateFolder"; - }; - deactivateFolder = { - protectedBy = ""; - actionClass = "UIxFolderActions"; - actionName = "deactivateFolder"; - }; - }; + }; + SOGoParentFolder = { + methods = { + createFolder = { + protectedBy = "View"; + actionClass = "UIxParentFolderActions"; + actionName = "createFolder"; + }; }; - }; + }; + SOGoFolder = { + methods = { + subscribe = { + protectedBy = ""; + actionClass = "UIxFolderActions"; + actionName = "subscribe"; + }; + unsubscribe = { + protectedBy = ""; + actionClass = "UIxFolderActions"; + actionName = "unsubscribe"; + }; + canAccessContent = { + protectedBy = ""; + actionClass = "UIxFolderActions"; + actionName = "canAccessContent"; + }; + activateFolder = { + protectedBy = ""; + actionClass = "UIxFolderActions"; + actionName = "activateFolder"; + }; + deactivateFolder = { + protectedBy = ""; + actionClass = "UIxFolderActions"; + actionName = "deactivateFolder"; + }; + deleteFolder = { + protectedBy = "SaveAcls"; /* a hack to force "owner" */ + actionClass = "UIxFolderActions"; + actionName = "deleteFolder"; + }; + renameFolder = { + protectedBy = "SaveAcls"; + actionClass = "UIxFolderActions"; + actionName = "renameFolder"; + }; + }; + }; + }; } diff --git a/UI/Contacts/English.lproj/Localizable.strings b/UI/Contacts/English.lproj/Localizable.strings index 9f8a0ac23..f7d9db028 100644 --- a/UI/Contacts/English.lproj/Localizable.strings +++ b/UI/Contacts/English.lproj/Localizable.strings @@ -97,6 +97,8 @@ "Are you sure you want to delete the selected address book?" = "Are you sure you want to delete the selected address book?"; +"Address Book Name" = "Address Book Name"; + "You cannot subscribe to a folder that you own!" = "You cannot subscribe to a folder that you own!"; "Unable to subscribe to that folder!" diff --git a/UI/Contacts/French.lproj/Localizable.strings b/UI/Contacts/French.lproj/Localizable.strings index f0ee23b30..757494068 100644 --- a/UI/Contacts/French.lproj/Localizable.strings +++ b/UI/Contacts/French.lproj/Localizable.strings @@ -110,6 +110,8 @@ "Are you sure you want to delete the selected address book?" = "Voulez-vous vraiment supprimer le carnet d'adresses sélectionné ?"; +"Address Book Name" = "Nom du carnet d'adresses"; + "You cannot subscribe to a folder that you own!" = "Vous ne pouvez pas vous inscrire à un dossier qui vous appartient!"; "Unable to subscribe to that folder!" diff --git a/UI/Contacts/German.lproj/Localizable.strings b/UI/Contacts/German.lproj/Localizable.strings index 9f4500abb..19bd4387e 100644 --- a/UI/Contacts/German.lproj/Localizable.strings +++ b/UI/Contacts/German.lproj/Localizable.strings @@ -109,6 +109,8 @@ "Are you sure you want to delete the selected address book?" = "Voulez-vous vraiment supprimer le carnet d'adresses sélectionné ?"; +"Address Book Name" = "Address Book Name"; + "You cannot subscribe to a folder that you own!" = "Vous ne pouvez pas vous inscrire à un dossier qui vous appartient!"; "Unable to subscribe to that folder!" diff --git a/UI/Contacts/UIxContactEditor.m b/UI/Contacts/UIxContactEditor.m index 578c65ce3..6f3954112 100644 --- a/UI/Contacts/UIxContactEditor.m +++ b/UI/Contacts/UIxContactEditor.m @@ -584,8 +584,8 @@ id co; co = [self clientObject]; - if ([[co class] respondsToSelector: @selector (globallyUniqueObjectId)]) - objectId = [[[self clientObject] class] globallyUniqueObjectId]; + if ([co respondsToSelector: @selector (globallyUniqueObjectId)]) + objectId = [co globallyUniqueObjectId]; else objectId = nil; diff --git a/UI/Contacts/UIxContactFoldersView.m b/UI/Contacts/UIxContactFoldersView.m index fa47cb91e..fa43d8109 100644 --- a/UI/Contacts/UIxContactFoldersView.m +++ b/UI/Contacts/UIxContactFoldersView.m @@ -52,8 +52,7 @@ WORequest *request; folders = [self clientObject]; - action = [NSString stringWithFormat: @"../personal/%@", - actionName]; + action = [NSString stringWithFormat: @"../personal/%@", actionName]; request = [[self context] request]; @@ -74,25 +73,6 @@ return [self _selectActionForApplication: @"new"]; } -- (id ) newAbAction -{ - id response; - NSString *name; - - name = [self queryParameterForKey: @"name"]; - if ([name length] > 0) - { - response = [[self clientObject] newFolderWithName: name]; - if (!response) - response = [self responseWith204]; - } - else - response = [NSException exceptionWithHTTPStatus: 400 - reason: @"The name is missing"]; - - return response; -} - - (id) selectForMailerAction { return [self _selectActionForApplication: @"mailer-contacts"]; @@ -193,50 +173,55 @@ return result; } -- (NSArray *) _gcsFoldersFromFolder: (SOGoContactFolders *) contactFolders +- (NSArray *) _subFoldersFromFolder: (SOGoParentFolder *) parentFolder { - NSMutableArray *gcsFolders; - NSEnumerator *contactSubfolders; - SOGoContactGCSFolder *currentContactFolder; - NSString *folderName, *displayName; + NSMutableArray *folders; + NSEnumerator *subfolders; + SOGoFolder *currentFolder; + NSString *folderName; NSMutableDictionary *currentDictionary; + SoSecurityManager *securityManager; - gcsFolders = [NSMutableArray new]; - [gcsFolders autorelease]; + securityManager = [SoSecurityManager sharedSecurityManager]; + +// return (([securityManager validatePermission: SoPerm_AccessContentsInformation +// onObject: contactFolder +// inContext: context] == nil) - contactSubfolders = [[contactFolders subFolders] objectEnumerator]; - currentContactFolder = [contactSubfolders nextObject]; - while (currentContactFolder) + folders = [NSMutableArray new]; + [folders autorelease]; + + subfolders = [[parentFolder subFolders] objectEnumerator]; + currentFolder = [subfolders nextObject]; + while (currentFolder) { - if ([currentContactFolder - isKindOfClass: [SOGoContactGCSFolder class]]) + if (![securityManager validatePermission: SOGoPerm_AccessObject + onObject: currentFolder inContext: context]) { - displayName = [[currentContactFolder ocsFolder] folderName]; - if (displayName) - { - folderName = [NSString stringWithFormat: @"/Contacts/%@", - [currentContactFolder nameInContainer]]; - currentDictionary - = [NSMutableDictionary dictionaryWithCapacity: 3]; - [currentDictionary setObject: displayName forKey: @"displayName"]; - [currentDictionary setObject: folderName forKey: @"name"]; - [currentDictionary setObject: @"contact" forKey: @"type"]; - [gcsFolders addObject: currentDictionary]; - } + folderName = [NSString stringWithFormat: @"/%@/%@", + [parentFolder nameInContainer], + [currentFolder nameInContainer]]; + currentDictionary + = [NSMutableDictionary dictionaryWithCapacity: 3]; + [currentDictionary setObject: [currentFolder displayName] + forKey: @"displayName"]; + [currentDictionary setObject: folderName forKey: @"name"]; + [currentDictionary setObject: [currentFolder folderType] + forKey: @"type"]; + [folders addObject: currentDictionary]; } - currentContactFolder = [contactSubfolders nextObject]; + currentFolder = [subfolders nextObject]; } - return gcsFolders; + return folders; } - (NSArray *) _foldersForUID: (NSString *) uid ofType: (NSString *) folderType { NSObject *topFolder, *userFolder; - SOGoContactFolders *contactFolders; + SOGoParentFolder *parentFolder; NSMutableArray *folders; - NSMutableDictionary *currentDictionary; folders = [NSMutableArray new]; [folders autorelease]; @@ -245,23 +230,19 @@ userFolder = [topFolder lookupName: uid inContext: context acquire: NO]; /* FIXME: should be moved in the SOGo* classes. Maybe by having a SOGoFolderManager. */ -#warning this might need adjustments whenever we permit multiple calendar folders per-user if ([folderType length] == 0 || [folderType isEqualToString: @"calendar"]) { - currentDictionary = [NSMutableDictionary new]; - [currentDictionary autorelease]; - [currentDictionary setObject: [self labelForKey: @"Calendar"] - forKey: @"displayName"]; - [currentDictionary setObject: @"/Calendar" forKey: @"name"]; - [currentDictionary setObject: @"calendar" forKey: @"type"]; - [folders addObject: currentDictionary]; + parentFolder = [userFolder lookupName: @"Calendar" + inContext: context acquire: NO]; + [folders + addObjectsFromArray: [self _subFoldersFromFolder: parentFolder]]; } if ([folderType length] == 0 || [folderType isEqualToString: @"contact"]) { - contactFolders = [userFolder lookupName: @"Contacts" - inContext: context acquire: NO]; + parentFolder = [userFolder lookupName: @"Contacts" + inContext: context acquire: NO]; [folders - addObjectsFromArray: [self _gcsFoldersFromFolder: contactFolders]]; + addObjectsFromArray: [self _subFoldersFromFolder: parentFolder]]; } return folders; @@ -352,31 +333,30 @@ return result; } -- (SOGoContactGCSFolder *) contactFolderForUID: (NSString *) uid -{ - SOGoFolder *upperContainer; - SOGoUserFolder *userFolder; - SOGoContactFolders *contactFolders; - SOGoContactGCSFolder *contactFolder; - SoSecurityManager *securityManager; +// - (SOGoContactGCSFolder *) contactFolderForUID: (NSString *) uid +// { +// SOGoFolder *upperContainer; +// SOGoUserFolder *userFolder; +// SOGoContactFolders *contactFolders; +// SOGoContactGCSFolder *contactFolder; +// SoSecurityManager *securityManager; - upperContainer = [[[self clientObject] container] container]; - userFolder = [SOGoUserFolder objectWithName: uid - inContainer: upperContainer]; - contactFolders = [SOGoContactFolders objectWithName: @"Contacts" - inContainer: userFolder]; - contactFolder = [SOGoContactGCSFolder objectWithName: @"personal" - inContainer: contactFolders]; - [contactFolder - setOCSPath: [NSString stringWithFormat: @"/Users/%@/Contacts/personal", uid]]; - [contactFolder setOwner: uid]; +// upperContainer = [[[self clientObject] container] container]; +// userFolder = [SOGoUserFolder objectWithName: uid +// inContainer: upperContainer]; +// contactFolders = [SOGoUserFolder lookupName: @"Contacts" +// inContext: context +// acquire: NO]; +// contactFolder = [contactFolders lookupName: @"personal" +// inContext: context +// acquire: NO]; - securityManager = [SoSecurityManager sharedSecurityManager]; +// securityManager = [SoSecurityManager sharedSecurityManager]; - return (([securityManager validatePermission: SoPerm_AccessContentsInformation - onObject: contactFolder - inContext: context] == nil) - ? contactFolder : nil); -} +// return (([securityManager validatePermission: SoPerm_AccessContentsInformation +// onObject: contactFolder +// inContext: context] == nil) +// ? contactFolder : nil); +// } @end diff --git a/UI/Contacts/UIxContactsListView.m b/UI/Contacts/UIxContactsListView.m index 45dadfa62..e6b2e2ad1 100644 --- a/UI/Contacts/UIxContactsListView.m +++ b/UI/Contacts/UIxContactsListView.m @@ -81,25 +81,6 @@ return selectorComponentClass; } -- (id ) deleteAction -{ - id result; - NSException *ex; - WOResponse *response; - - ex = [[self clientObject] delete]; - if (ex) - result = ex; - else - { - response = [context response]; - [response setStatus: 200]; - result = response; - } - - return result; -} - - (NSString *) defaultSortKey { return @"displayName"; diff --git a/UI/Contacts/UIxContactsListViewContainer.h b/UI/Contacts/UIxContactsListViewContainer.h index 5be9899fd..eb0d72d87 100644 --- a/UI/Contacts/UIxContactsListViewContainer.h +++ b/UI/Contacts/UIxContactsListViewContainer.h @@ -31,28 +31,18 @@ @interface UIxContactsListViewContainer : UIxComponent { - NSString *foldersPrefix; NSString *selectorComponentClass; - NSString *currentAdditionalFolder; - NSDictionary *additionalFolders; id currentFolder; } - (void) setCurrentFolder: (id) folder; -- (NSString *) foldersPrefix; - - (NSArray *) contactFolders; - (NSString *) currentContactFolderId; +- (NSString *) currentContactFolderOwner; - (NSString *) currentContactFolderName; -- (NSArray *) additionalFolders; - -- (void) setCurrentAdditionalFolder: (NSString *) newCurrentAdditionalFolder; -- (NSString *) currentAdditionalFolder; -- (NSString *) currentAdditionalFolderName; - @end #endif /* UIXCONTACTSLISTVIEWCONTAINERBASE_H */ diff --git a/UI/Contacts/UIxContactsListViewContainer.m b/UI/Contacts/UIxContactsListViewContainer.m index 5aab0c6d7..f472b1560 100644 --- a/UI/Contacts/UIxContactsListViewContainer.m +++ b/UI/Contacts/UIxContactsListViewContainer.m @@ -41,20 +41,12 @@ { if ((self = [super init])) { - foldersPrefix = nil; selectorComponentClass = nil; - additionalFolders = nil; } return self; } -- (void) dealloc -{ - [additionalFolders release]; - [super dealloc]; -} - - (void) setSelectorComponentClass: (NSString *) aComponentClass { selectorComponentClass = aComponentClass; @@ -86,30 +78,6 @@ currentFolder = folder; } -- (NSString *) foldersPrefix -{ - NSMutableArray *folders; - SOGoObject *currentObject; - - if (!foldersPrefix) - { - folders = [NSMutableArray new]; - [folders autorelease]; - - currentObject = [[self clientObject] container]; - while (![currentObject isKindOfClass: [SOGoContactFolders class]]) - { - [folders insertObject: [currentObject nameInContainer] atIndex: 0]; - currentObject = [currentObject container]; - } - - foldersPrefix = [folders componentsJoinedByString: @"/"]; - [foldersPrefix retain]; - } - - return foldersPrefix; -} - - (NSArray *) contactFolders { SOGoContactFolders *folderContainer; @@ -121,8 +89,7 @@ - (NSString *) currentContactFolderId { - return [NSString stringWithFormat: @"%@/%@", - [self foldersPrefix], + return [NSString stringWithFormat: @"/%@", [currentFolder nameInContainer]]; } @@ -131,35 +98,9 @@ return [currentFolder displayName]; } -- (NSArray *) additionalFolders +- (NSString *) currentContactFolderOwner { - NSUserDefaults *ud; - - if (!additionalFolders) - { - ud = [[context activeUser] userSettings]; - additionalFolders - = [[ud objectForKey: @"Contacts"] objectForKey: @"SubscribedFolders"]; - [additionalFolders retain]; - } - - return [additionalFolders allKeys]; -} - -- (void) setCurrentAdditionalFolder: (NSString *) newCurrentAdditionalFolder -{ - currentAdditionalFolder = newCurrentAdditionalFolder; -} - -- (NSString *) currentAdditionalFolder -{ - return currentAdditionalFolder; -} - -- (NSString *) currentAdditionalFolderName -{ - return [[additionalFolders objectForKey: currentAdditionalFolder] - objectForKey: @"displayName"]; + return [currentFolder ownerInContext: context]; } - (BOOL) hasContactSelectionButtons diff --git a/UI/Contacts/product.plist b/UI/Contacts/product.plist index cff8e800d..3602be7ae 100644 --- a/UI/Contacts/product.plist +++ b/UI/Contacts/product.plist @@ -17,11 +17,6 @@ pageName = "UIxContactFoldersView"; actionName = "new"; }; - newAb = { - protectedBy = "View"; - pageName = "UIxContactFoldersView"; - actionName = "newAb"; - }; mailer-contacts = { protectedBy = "View"; pageName = "UIxContactFoldersView"; @@ -87,11 +82,6 @@ pageName = "UIxContactsListView"; actionName = "mailerContacts"; }; - delete = { - protectedBy = "SaveAcls"; /* a hack to force "owner" */ - pageName = "UIxContactsListView"; - actionName = "delete"; - }; userRights = { protectedBy = "ReadAcls"; pageName = "UIxContactsUserRightsEditor"; diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index f0323e638..9749d13b5 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -73,7 +73,7 @@ cookieString = [NSString stringWithFormat: @"%@:%@", [self queryParameterForKey: @"userName"], [self queryParameterForKey: @"password"]]; - cookieValue = [NSString stringWithFormat: @"basic%@", + cookieValue = [NSString stringWithFormat: @"basic %@", [cookieString stringByEncodingBase64]]; authCookie = [WOCookie cookieWithName: [auth cookieNameInContext: context] value: cookieValue]; diff --git a/UI/MainUI/product.plist b/UI/MainUI/product.plist index c3ebb0993..11e282820 100644 --- a/UI/MainUI/product.plist +++ b/UI/MainUI/product.plist @@ -46,6 +46,14 @@ "Access Contents Information" = ( "Owner", "ObjectViewer" ); }; }; + SOGoParentFolder = { + superclass = "SOGoObject"; + protectedBy = "Access Contents Information"; + defaultRoles = { + "Access Contents Information" = ( "Authenticated" ); + "WebDAV Access" = ( "Authenticated" ); + }; + }; SOGoUserFolder = { superclass = "SOGoFolder"; protectedBy = "Access Contents Information"; diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m index 4131db0a5..7259f60d2 100644 --- a/UI/PreferencesUI/UIxPreferences.m +++ b/UI/PreferencesUI/UIxPreferences.m @@ -125,7 +125,8 @@ static BOOL shouldDisplayPasswordChange = NO; - (NSArray *) timeZonesList { - return [NSTimeZone knownTimeZoneNames]; + return [[NSTimeZone knownTimeZoneNames] + sortedArrayUsingSelector: @selector (localizedCaseInsensitiveCompare:)]; } - (NSString *) userTimeZone diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index f49a55a92..5e7ee587b 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -99,8 +99,11 @@ /* Button Titles */ -"Add..." = "Add..."; -"Remove" = "Remove"; +"New Calendar..." = "New Calendar..."; +"Subscribe to a Calendar..." = "Subscribe to a Calendar..."; +"Remove the selected Calendar" = "Remove the selected Calendar"; + +"Name of the Calendar" = "Name of the Calendar"; "new" = "New"; "printview" = "Print View"; diff --git a/UI/Scheduler/French.lproj/Localizable.strings b/UI/Scheduler/French.lproj/Localizable.strings index 9fb1d9fcc..1d8f083eb 100644 --- a/UI/Scheduler/French.lproj/Localizable.strings +++ b/UI/Scheduler/French.lproj/Localizable.strings @@ -100,8 +100,11 @@ /* Button Titles */ -"Add..." = "Ajouter..."; -"Remove" = "Enlever"; +"New Calendar..." = "Nouvel agenda..."; +"Subscribe to a Calendar..." = "S'inscrire à un agenda..."; +"Remove the selected Calendar" = "Enlever l'agenda sélectionné"; + +"Name of the Calendar" = "Nom de l'agenda"; "new" = "Nouveau"; "printview" = "Version imprimable"; diff --git a/UI/Scheduler/GNUmakefile b/UI/Scheduler/GNUmakefile index 0089f139a..8c65e344b 100644 --- a/UI/Scheduler/GNUmakefile +++ b/UI/Scheduler/GNUmakefile @@ -48,7 +48,7 @@ SchedulerUI_RESOURCE_FILES += \ product.plist SchedulerUI_RESOURCE_FILES += \ - Toolbars/SOGoAppointmentFolder.toolbar \ + Toolbars/SOGoAppointmentFolders.toolbar \ Toolbars/SOGoAppointmentObject.toolbar \ Toolbars/SOGoAppointmentObjectAccept.toolbar \ Toolbars/SOGoAppointmentObjectDecline.toolbar \ diff --git a/UI/Scheduler/German.lproj/Localizable.strings b/UI/Scheduler/German.lproj/Localizable.strings index 9a52d23d9..b05adbc75 100644 --- a/UI/Scheduler/German.lproj/Localizable.strings +++ b/UI/Scheduler/German.lproj/Localizable.strings @@ -100,8 +100,11 @@ /* Button Titles */ -"Add..." = "Hinzufügen..."; -"Remove" = "Löschen"; +"New Calendar..." = "New Calendar..."; +"Subscribe to a Calendar..." = "Subscribe to a Calendar..."; +"Remove the selected Calendar" = "Remove the selected Calendar"; + +"Name of the Calendar" = "Name of the Calendar"; "new" = "Neu"; "printview" = "Version imprimable"; diff --git a/UI/Scheduler/Toolbars/SOGoAppointmentFolder.toolbar b/UI/Scheduler/Toolbars/SOGoAppointmentFolders.toolbar similarity index 100% rename from UI/Scheduler/Toolbars/SOGoAppointmentFolder.toolbar rename to UI/Scheduler/Toolbars/SOGoAppointmentFolders.toolbar diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index f4f041979..a88b3f382 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -286,14 +286,14 @@ { NSString *objectId, *method, *uri; id result; - Class clientKlazz; + SOGoAppointmentFolder *co; - clientKlazz = [[self clientObject] class]; - objectId = [clientKlazz globallyUniqueObjectId]; + co = [self clientObject]; + objectId = [co globallyUniqueObjectId]; if ([objectId length] > 0) { - method = [NSString stringWithFormat:@"%@/Calendar/%@/editAsAppointment", - [self userFolderPath], objectId]; + method = [NSString stringWithFormat:@"%@/%@/editAsAppointment", + [co soURL], objectId]; uri = [self completeHrefForMethod: method]; result = [self redirectToLocation: uri]; } diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m index 34a1ec92d..b036060f9 100644 --- a/UI/Scheduler/UIxCalListingActions.m +++ b/UI/Scheduler/UIxCalListingActions.m @@ -25,6 +25,7 @@ #import #import #import +#import #import #import @@ -38,6 +39,7 @@ #import #import #import +#import #import @@ -214,36 +216,6 @@ return aptFolder; } -- (NSArray *) _activeCalendarFolders -{ - NSMutableArray *activeFolders; - NSEnumerator *folders; - NSDictionary *currentFolderDict; - SOGoAppointmentFolder *currentFolder, *clientObject; - - activeFolders = [NSMutableArray new]; - [activeFolders autorelease]; - - clientObject = [self clientObject]; - - folders = [[clientObject calendarFolders] objectEnumerator]; - currentFolderDict = [folders nextObject]; - while (currentFolderDict) - { - if ([[currentFolderDict objectForKey: @"active"] boolValue]) - { - currentFolder - = [self _aptFolder: [currentFolderDict objectForKey: @"folder"] - withClientObject: clientObject]; - [activeFolders addObject: currentFolder]; - } - - currentFolderDict = [folders nextObject]; - } - - return activeFolders; -} - - (NSArray *) _fetchFields: (NSArray *) fields forComponentOfType: (NSString *) component { @@ -252,34 +224,42 @@ NSMutableDictionary *infos, *currentInfo, *newInfo; NSString *owner, *uid; NSNull *marker; + SOGoAppointmentFolders *clientObject; marker = [NSNull null]; infos = [NSMutableDictionary dictionary]; - folders = [[self _activeCalendarFolders] objectEnumerator]; + clientObject = [self clientObject]; + + folders = [[clientObject subFolders] objectEnumerator]; currentFolder = [folders nextObject]; while (currentFolder) { - owner = [currentFolder ownerInContext: context]; - currentInfos = [[currentFolder fetchCoreInfosFrom: startDate - to: endDate - component: component] objectEnumerator]; - newInfo = [currentInfos nextObject]; - while (newInfo) + if ([currentFolder isActive]) { - uid = [newInfo objectForKey: @"c_uid"]; - currentInfo = [infos objectForKey: uid]; - if (!currentInfo - || [owner isEqualToString: userLogin]) - { - [self _updatePrivacyInComponent: newInfo - fromFolder: currentFolder]; - [newInfo setObject: owner forKey: @"c_owner"]; - [infos setObject: [newInfo objectsForKeys: fields - notFoundMarker: marker] - forKey: uid]; - } + owner = [currentFolder ownerInContext: context]; + currentInfos = [[currentFolder fetchCoreInfosFrom: startDate + to: endDate + component: component] objectEnumerator]; newInfo = [currentInfos nextObject]; + while (newInfo) + { + uid = [newInfo objectForKey: @"c_uid"]; + currentInfo = [infos objectForKey: uid]; + if (!currentInfo + || [owner isEqualToString: userLogin]) + { + [self _updatePrivacyInComponent: newInfo + fromFolder: currentFolder]; + [newInfo setObject: [currentFolder nameInContainer] + forKey: @"c_folder"]; + // [newInfo setObject: owner forKey: @"c_owner"]; + [infos setObject: [newInfo objectsForKeys: fields + notFoundMarker: marker] + forKey: uid]; + } + newInfo = [currentInfos nextObject]; + } } currentFolder = [folders nextObject]; } @@ -326,7 +306,7 @@ [self _setupContext]; newEvents = [NSMutableArray array]; - fields = [NSArray arrayWithObjects: @"c_name", @"c_owner", @"c_status", + fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status", @"c_title", @"c_startdate", @"c_enddate", @"c_location", @"c_isallday", nil]; events = [[self _fetchFields: fields @@ -397,7 +377,7 @@ [self _setupContext]; - fields = [NSArray arrayWithObjects: @"c_name", @"c_owner", @"c_status", + fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status", @"c_title", @"c_enddate", nil]; tasks = [[self _fetchFields: fields diff --git a/UI/Scheduler/UIxCalMainView.m b/UI/Scheduler/UIxCalMainView.m index 80b66f66d..ca3933a0c 100644 --- a/UI/Scheduler/UIxCalMainView.m +++ b/UI/Scheduler/UIxCalMainView.m @@ -23,6 +23,7 @@ #import #import #import +#import #import #import @@ -41,6 +42,15 @@ static NSMutableArray *yearMenuItems = nil; @implementation UIxCalMainView +- (NSString *) userUTCOffset +{ + NSTimeZone *userTZ; + + userTZ = [[context activeUser] timeZone]; + + return [NSString stringWithFormat: @"%d", [userTZ secondsFromGMT]]; +} + - (NSArray *) monthMenuItems { unsigned int count; diff --git a/UI/Scheduler/UIxCalendarSelector.h b/UI/Scheduler/UIxCalendarSelector.h index 410ce6dbb..21feda2f8 100644 --- a/UI/Scheduler/UIxCalendarSelector.h +++ b/UI/Scheduler/UIxCalendarSelector.h @@ -23,29 +23,23 @@ #ifndef UIXCALENDARSELECTOR_H #define UIXCALENDARSELECTOR_H +#import + @class NSArray; @class NSMutableArray; @class NSDictionary; -@class NSMutableDictionary; @class NSString; -@class iCalPerson; @interface UIxCalendarSelector : UIxComponent { - NSMutableDictionary *colors; - - NSDictionary *currentCalendarFolder; - NSString *currentCalendarLogin; + NSMutableArray *calendars; + NSDictionary *currentCalendar; } -- (NSArray *) calendarFolders; +- (NSArray *) calendars; -- (void) setCurrentCalendarFolder: (NSDictionary *) newCurrentCalendarFolder; -- (NSDictionary *) currentCalendarFolder; - -- (NSString *) currentCalendarSpanBG; -- (NSString *) currentCalendarLogin; -- (NSString *) currentCalendarStyle; +- (void) setCurrentCalendar: (NSDictionary *) newCalendar; +- (NSDictionary *) currentCalendar; @end diff --git a/UI/Scheduler/UIxCalendarSelector.m b/UI/Scheduler/UIxCalendarSelector.m index 1beef4b43..b411f6b44 100644 --- a/UI/Scheduler/UIxCalendarSelector.m +++ b/UI/Scheduler/UIxCalendarSelector.m @@ -22,34 +22,30 @@ #import #import -#import -#import +#import -#import -#import - -#import -#import +#import #import +#import #import "UIxCalendarSelector.h" -static inline char -darkenedColor (const char value) -{ - char newValue; +// static inline char +// darkenedColor (const char value) +// { +// char newValue; - if (value >= '0' && value <= '9') - newValue = ((value - '0') / 2) + '0'; - else if (value >= 'a' && value <= 'f') - newValue = ((value + 10 - 'a') / 2) + '0'; - else if (value >= 'A' && value <= 'F') - newValue = ((value + 10 - 'A') / 2) + '0'; - else - newValue = value; +// if (value >= '0' && value <= '9') +// newValue = ((value - '0') / 2) + '0'; +// else if (value >= 'a' && value <= 'f') +// newValue = ((value + 10 - 'a') / 2) + '0'; +// else if (value >= 'A' && value <= 'F') +// newValue = ((value + 10 - 'A') / 2) + '0'; +// else +// newValue = value; - return newValue; -} +// return newValue; +// } static inline NSString * colorForNumber (unsigned int number) @@ -90,8 +86,8 @@ colorForNumber (unsigned int number) { if ((self = [super init])) { - colors = nil; - currentCalendarFolder = nil; + calendars = nil; + currentCalendar = nil; } return self; @@ -99,82 +95,61 @@ colorForNumber (unsigned int number) - (void) dealloc { - [currentCalendarFolder release]; - [colors release]; + [calendars release]; + [currentCalendar release]; [super dealloc]; } -- (NSArray *) calendarFolders +- (NSArray *) calendars { - NSArray *calendarFolders; - NSEnumerator *newFolders; - NSDictionary *currentFolder; - unsigned int count; + NSArray *folders; + SOGoAppointmentFolder *folder; + NSMutableDictionary *calendar; + unsigned int count, max; + NSString *folderId, *folderName; + NSNumber *isActive; - calendarFolders = [[self clientObject] calendarFolders]; - if (!colors) + if (!calendars) { - colors = [NSMutableDictionary new]; - count = 0; - newFolders = [calendarFolders objectEnumerator]; - currentFolder = [newFolders nextObject]; - while (currentFolder) + folders = [[self clientObject] subFolders]; + max = [folders count]; + calendars = [[NSMutableArray alloc] initWithCapacity: max]; + for (count = 0; count < max; count++) { - [colors setObject: colorForNumber (count) - forKey: [currentFolder objectForKey: @"folder"]]; - count++; - currentFolder = [newFolders nextObject]; + folder = [folders objectAtIndex: count]; + calendar = [NSMutableDictionary dictionary]; + folderName = [folder nameInContainer]; + [calendar setObject: + [NSString stringWithFormat: @"/%@", folderName] + forKey: @"id"]; + [calendar setObject: [folder displayName] + forKey: @"displayName"]; + [calendar setObject: folderName forKey: @"folder"]; + [calendar setObject: colorForNumber (count) + forKey: @"color"]; + isActive = [NSNumber numberWithBool: [folder isActive]]; + [calendar setObject: isActive forKey: @"active"]; + [calendars addObject: calendar]; } } - return calendarFolders; + return calendars; } -- (void) setCurrentCalendarFolder: (NSDictionary *) newCurrentCalendarFolder +- (void) setCurrentCalendar: (NSDictionary *) newCalendar { - ASSIGN (currentCalendarFolder, newCurrentCalendarFolder); + ASSIGN (currentCalendar, newCalendar); } -- (NSDictionary *) currentCalendarFolder +- (NSDictionary *) currentCalendar { - return currentCalendarFolder; -} - -- (NSString *) currentCalendarSpanBG -{ - NSString *colorKey; - - colorKey = [currentCalendarFolder objectForKey: @"folder"]; - - return [colors objectForKey: colorKey]; -} - -- (NSString *) currentCalendarLogin -{ - NSArray *parts; - NSMutableString *login; - - login = [NSMutableString string]; - parts = [[currentCalendarFolder objectForKey: @"folder"] - componentsSeparatedByString: @":"]; - [login appendString: (([parts count] > 1) - ? [parts objectAtIndex: 0] - : [[context activeUser] login])]; - [login replaceString: @"." withString: @"_"]; - [login replaceString: @"#" withString: @"_"]; - [login replaceString: @"@" withString: @"_"]; - - return login; + return currentCalendar; } - (NSString *) currentCalendarStyle { - NSString *color; - - color = [self currentCalendarSpanBG]; - - return [NSString stringWithFormat: @"color: %@; background-color: %@;", - color, color]; + return [currentCalendar + keysWithFormat: @"color: %{color}; background-color: %{color};"]; } @end /* UIxCalendarSelector */ diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index 7937e8fa7..5cfeecaf4 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -42,6 +42,7 @@ #import #import +#import #import #import #import @@ -331,19 +332,20 @@ - (NSArray *) calendarList { - SOGoAppointmentFolder *folder; + SOGoAppointmentFolder *calendar, *currentCalendar; + SOGoAppointmentFolders *calendarParent; NSEnumerator *allCalendars; - NSDictionary *currentCalendar; if (!calendarList) { calendarList = [NSMutableArray new]; - folder = [[self clientObject] container]; - allCalendars = [[folder calendarFolders] objectEnumerator]; + calendar = [[self clientObject] container]; + calendarParent = [calendar container]; + allCalendars = [[calendarParent subFolders] objectEnumerator]; currentCalendar = [allCalendars nextObject]; while (currentCalendar) { - if ([[currentCalendar objectForKey: @"active"] boolValue]) + if ([currentCalendar isActive]) [calendarList addObject: currentCalendar]; currentCalendar = [allCalendars nextObject]; } diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index 0258ae2d2..bc7e1bed1 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -324,14 +324,14 @@ { NSString *objectId, *method, *uri; id result; - Class clientKlazz; + SOGoAppointmentFolder *co; - clientKlazz = [[self clientObject] class]; - objectId = [clientKlazz globallyUniqueObjectId]; + co = [self clientObject]; + objectId = [co globallyUniqueObjectId]; if ([objectId length] > 0) { - method = [NSString stringWithFormat:@"%@/Calendar/%@/editAsTask", - [self userFolderPath], objectId]; + method = [NSString stringWithFormat:@"%@/%@/editAsTask", + [co soURL], objectId]; uri = [self completeHrefForMethod: method]; result = [self redirectToLocation: uri]; } diff --git a/UI/Scheduler/product.plist b/UI/Scheduler/product.plist index 2041d7570..c5afd5cc6 100644 --- a/UI/Scheduler/product.plist +++ b/UI/Scheduler/product.plist @@ -28,11 +28,11 @@ }; categories = { - SOGoAppointmentFolder = { + SOGoAppointmentFolders = { slots = { toolbar = { protectedBy = "View"; - value = "SOGoAppointmentFolder.toolbar"; + value = "SOGoAppointmentFolders.toolbar"; }; }; methods = { @@ -70,16 +70,6 @@ protectedBy = "View"; pageName = "UIxCalMonthView"; }; - newevent = { - protectedBy = "Add Documents, Images, and Files"; - pageName = "UIxAppointmentEditor"; - actionName = "new"; - }; - newtask = { - protectedBy = "Add Documents, Images, and Files"; - pageName = "UIxTaskEditor"; - actionName = "new"; - }; show = { protectedBy = "View"; pageName = "UIxCalView"; @@ -94,15 +84,45 @@ pageName = "UIxAppointmentProposal"; actionName = "proposalSearch"; }; + userRights = { + protectedBy = "ReadAcls"; + pageName = "UIxCalUserRightsEditor"; + }; + saveUserRights = { + protectedBy = "SaveAcls"; + pageName = "UIxCalUserRightsEditor"; + actionName = "saveUserRights"; + }; + }; + }; + + SOGoAppointmentFolder = { + methods = { + newevent = { + protectedBy = "Add Documents, Images, and Files"; + pageName = "UIxAppointmentEditor"; + actionName = "new"; + }; + newtask = { + protectedBy = "Add Documents, Images, and Files"; + pageName = "UIxTaskEditor"; + actionName = "new"; + }; batchDelete = { protectedBy = "Delete Objects"; pageName = "UIxCalMainView"; actionName = "batchDelete"; }; - updateCalendars = { + + show = { protectedBy = "View"; + pageName = "UIxCalView"; + actionName = "redirectForUIDs"; + }; + batchDelete = { + protectedBy = "Delete Objects"; pageName = "UIxCalMainView"; - actionName = "updateCalendars"; + actionName = "batchDelete"; }; editAttendees = { protectedBy = "View"; @@ -119,6 +139,7 @@ }; }; }; + SOGoCalendarComponent = { }; @@ -158,6 +179,10 @@ pageName = "UIxAppointmentEditor"; actionName = "decline"; }; + editAttendees = { + protectedBy = "View"; + pageName = "UIxAttendeesEditor"; + }; }; }; diff --git a/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox b/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox index 8a2d86556..1733b8969 100644 --- a/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox +++ b/UI/Templates/ContactsUI/UIxContactsListViewContainer.wox @@ -62,13 +62,10 @@
  • + >
diff --git a/UI/Templates/SchedulerUI/UIxCalMainView.wox b/UI/Templates/SchedulerUI/UIxCalMainView.wox index 863be2ff4..9ab3d56d5 100644 --- a/UI/Templates/SchedulerUI/UIxCalMainView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMainView.wox @@ -9,6 +9,9 @@ className="UIxPageFrame" title="title" > + diff --git a/UI/Templates/SchedulerUI/UIxCalendarSelector.wox b/UI/Templates/SchedulerUI/UIxCalendarSelector.wox index bee2ff03c..a54fcfb6b 100644 --- a/UI/Templates/SchedulerUI/UIxCalendarSelector.wox +++ b/UI/Templates/SchedulerUI/UIxCalendarSelector.wox @@ -7,30 +7,34 @@ xmlns:rsrc="OGo:url" xmlns:label="OGo:label">
+
    -
  • +
  • + var:checked="currentCalendar.active" />
    OO
    -
diff --git a/UI/Templates/UIxPageFrame.wox b/UI/Templates/UIxPageFrame.wox index 6bad635bb..59244aed2 100644 --- a/UI/Templates/UIxPageFrame.wox +++ b/UI/Templates/UIxPageFrame.wox @@ -5,7 +5,7 @@ xmlns:var="http://www.skyrix.com/od/binding" xmlns:const="http://www.skyrix.com/od/constant" xmlns:rsrc="OGo:url" - xmlns:label="OGo:label" + xmlns:label="OGo:label" > diff --git a/UI/WebServerResources/ContactsUI.js b/UI/WebServerResources/ContactsUI.js index f38c9d05b..e5b841468 100644 --- a/UI/WebServerResources/ContactsUI.js +++ b/UI/WebServerResources/ContactsUI.js @@ -18,8 +18,8 @@ function validateEditorInput(sender) { errortext = errortext + labels.error_missingrecipients + "\n"; if (errortext.length > 0) { - alert(labels.error_validationfailed.decodeEntities() + ":\n" - + errortext.decodeEntities()); + alert(labels.error_validationfailed + ":\n" + + errortext); return false; } return true; @@ -468,28 +468,24 @@ function refreshContacts(contactId) { } function onAddressBookNew(event) { - var name = window.prompt(labels["Name of the Address Book"].decodeEntities()); - if (name) { - if (document.newAbAjaxRequest) { - document.newAbAjaxRequest.aborted = true; - document.newAbAjaxRequest.abort(); - } - var url = ApplicationBaseURL + "/newAb?name=" + name; - document.newAbAjaxRequest - = triggerAjaxRequest(url, newAbCallback, name); - } + createFolder(window.prompt(labels["Name of the Address Book"]), + appendAddressBook); preventDefault(event); } function appendAddressBook(name, folder) { - var li = document.createElement("li"); - $("contactFolders").appendChild(li); - li.setAttribute("id", folder); - li.appendChild(document.createTextNode(name)); - setEventsOnContactFolder(li); + if (folder) + folder = accessToSubscribedFolder(folder); + else + folder = "/" + name; + var li = document.createElement("li"); + $("contactFolders").appendChild(li); + li.setAttribute("id", folder); + li.appendChild(document.createTextNode(name)); + setEventsOnContactFolder(li); } -function newAbCallback(http) { +function newFolderCallback(http) { if (http.readyState == 4 && http.status == 201) { var name = http.callbackData; @@ -523,60 +519,60 @@ function onAddressBookRemove(event) { var selector = $("contactFolders"); var nodes = selector.getSelectedNodes(); if (nodes.length > 0) { - nodes[0].deselect(); - var folderId = nodes[0].getAttribute("id"); - var folderIdElements = folderId.split(":"); - if (folderIdElements.length > 1) - unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId); - else { - var abId = folderIdElements[0].substr(1); - deletePersonalAddressBook(abId); - var personal = $("/personal"); - personal.select(); - onFolderSelectionChange(); - } + nodes[0].deselect(); + var folderId = nodes[0].getAttribute("id"); + var folderIdElements = folderId.split("_"); + if (folderIdElements.length > 1) + unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId); + else { + var abId = folderIdElements[0].substr(1); + deletePersonalAddressBook(abId); + var personal = $("/personal"); + personal.select(); + onFolderSelectionChange(); + } } preventDefault(event); } function deletePersonalAddressBook(folderId) { - var label - = labels["Are you sure you want to delete the selected address book?"]; - if (window.confirm(label.decodeEntities())) { - if (document.deletePersonalABAjaxRequest) { - document.deletePersonalABAjaxRequest.aborted = true; - document.deletePersonalABAjaxRequest.abort(); - } - var url = ApplicationBaseURL + "/" + folderId + "/delete"; - document.deletePersonalABAjaxRequest - = triggerAjaxRequest(url, deletePersonalAddressBookCallback, - folderId); - } + var label + = labels["Are you sure you want to delete the selected address book?"]; + if (window.confirm(label)) { + if (document.deletePersonalABAjaxRequest) { + document.deletePersonalABAjaxRequest.aborted = true; + document.deletePersonalABAjaxRequest.abort(); + } + var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder"; + document.deletePersonalABAjaxRequest + = triggerAjaxRequest(url, deletePersonalAddressBookCallback, + folderId); + } } function deletePersonalAddressBookCallback(http) { if (http.readyState == 4) { - if (http.status == 200) { - var ul = $("contactFolders"); + if (isHttpStatus204(http.status)) { + var ul = $("contactFolders"); - var children = ul.childNodesWithTag("li"); - var i = 0; - var done = false; - while (!done && i < children.length) { - var currentFolderId = children[i].getAttribute("id").substr(1); - if (currentFolderId == http.callbackData) { - ul.removeChild(children[i]); - done = true; - } - else - i++; + var children = ul.childNodesWithTag("li"); + var i = 0; + var done = false; + while (!done && i < children.length) { + var currentFolderId = children[i].getAttribute("id").substr(1); + if (currentFolderId == http.callbackData) { + ul.removeChild(children[i]); + done = true; } - } - document.deletePersonalABAjaxRequest = null; + else + i++; + } + } + document.deletePersonalABAjaxRequest = null; } else - log ("ajax problem 5: " + http.status); + log ("ajax problem 5: " + http.status); } function configureDragHandles() { @@ -648,6 +644,34 @@ function setEventsOnContactFolder(node) { onContactFoldersContextMenu.bindAsEventListener(node), false); } +function onMenuModify(event) { + var folders = $("contactFolders"); + var selected = folders.getSelectedNodes()[0]; + + if (UserLogin == selected.getAttribute("owner")) { + var currentName = selected.innerHTML; + var newName = window.prompt(labels["Address Book Name"], + currentName); + if (newName && newName.length > 0 + && newName != currentName) { + var url = (URLForFolderID(selected.getAttribute("id")) + + "/renameFolder?name=" + escape(newName.utf8encode())); + triggerAjaxRequest(url, folderRenameCallback, + {node: selected, name: newName}); + } + } else + window.alert(clabels["Unable to rename that folder!"]); +} + +function folderRenameCallback(http) { + if (http.readyState == 4) { + if (isHttpStatus204(http.status)) { + var dict = http.callbackData; + dict["node"].innerHTML = dict["name"]; + } + } +} + function onMenuSharing(event) { var folders = $("contactFolders"); var selected = folders.getSelectedNodes()[0]; @@ -659,7 +683,7 @@ function onMenuSharing(event) { function getMenus() { var menus = {}; - menus["contactFoldersMenu"] = new Array(null, "-", null, + menus["contactFoldersMenu"] = new Array(onMenuModify, "-", null, null, "-", null, "-", onMenuSharing); menus["contactMenu"] = new Array(onMenuEditContact, "-", diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index fc864847b..7c992039a 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -17,7 +17,7 @@ var cachedDateSelectors = new Array(); var contactSelectorAction = 'calendars-contacts'; var eventsToDelete = new Array(); -var ownersOfEventsToDelete = new Array(); +var calendarsOfEventsToDelete = new Array(); var usersRightsWindowHeight = 250; var usersRightsWindowWidth = 502; @@ -27,15 +27,11 @@ function newEvent(sender, type) { if (!day) day = currentDay; - var user = UserLogin; - if (sender.parentNode.getAttribute("id") != "toolbar" - && currentView == "multicolumndayview" && type == "event") - user = sender.parentNode.parentNode.getAttribute("user"); - var hour = sender.hour; if (!hour) hour = sender.getAttribute("hour"); - var urlstr = UserFolderURL + "../" + user + "/Calendar/new" + type; + var folderID = getSelectedFolder(); + var urlstr = ApplicationBaseURL + folderID + "/new" + type; var params = new Array(); if (day) params.push("day=" + day); @@ -49,6 +45,18 @@ function newEvent(sender, type) { return false; /* stop following the link */ } +function getSelectedFolder() { + var folder; + + var nodes = $("calendarList").getSelectedRows(); + if (nodes.length > 0) + folder = nodes[0].getAttribute("id"); + else + folder = "/personal"; + + return folder; +} + function onMenuNewEventClick(event) { newEvent(this, "event"); } @@ -57,13 +65,8 @@ function onMenuNewTaskClick(event) { newEvent(this, "task"); } -function _editEventId(id, owner) { - var urlBase; - if (owner) - urlBase = UserFolderURL + "../" + owner + "/"; - urlBase += "Calendar/" - - var urlstr = urlBase + id + "/edit"; +function _editEventId(id, calendar) { + var urlstr = ApplicationBaseURL + "/" + calendar + "/" + id + "/edit"; var targetname = "SOGo_edit_" + id; var win = window.open(urlstr, "_blank", "width=490,height=470,resizable=0"); @@ -76,10 +79,10 @@ function editEvent() { for (var i = 0; i < nodes.length; i++) _editEventId(nodes[i].getAttribute("id"), - nodes[i].owner); + nodes[i].calendar); } else if (selectedCalendarCell) { _editEventId(selectedCalendarCell[0].cname, - selectedCalendarCell[0].owner); + selectedCalendarCell[0].calendar); } return false; /* stop following the link */ @@ -87,9 +90,9 @@ function editEvent() { function _batchDeleteEvents() { var events = eventsToDelete.shift(); - var owner = ownersOfEventsToDelete.shift(); - var urlstr = (UserFolderURL + "../" + owner + "/Calendar/batchDelete?ids=" - + events.join('/')); + var calendar = calendarsOfEventsToDelete.shift(); + var urlstr = (ApplicationBaseURL + "/" + calendar + + "/batchDelete?ids=" + events.join('/')); document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr, deleteEventCallback, events); @@ -102,9 +105,9 @@ function deleteEvent() { if (nodes.length > 0) { var label = ""; if (listOfSelection == $("tasksList")) - label = labels["taskDeleteConfirmation"].decodeEntities(); + label = labels["taskDeleteConfirmation"]; else - label = labels["eventDeleteConfirmation"].decodeEntities(); + label = labels["eventDeleteConfirmation"]; if (confirm(label)) { if (document.deleteEventAjaxRequest) { @@ -112,33 +115,33 @@ function deleteEvent() { document.deleteEventAjaxRequest.abort(); } var sortedNodes = new Array(); - var owners = new Array(); + var calendars = new Array(); for (var i = 0; i < nodes.length; i++) { - var owner = nodes[i].owner; - if (!sortedNodes[owner]) { - sortedNodes[owner] = new Array(); - owners.push(owner); + var calendar = nodes[i].calendar; + if (!sortedNodes[calendar]) { + sortedNodes[calendar] = new Array(); + calendars.push(calendar); } - sortedNodes[owner].push(nodes[i].cname); + sortedNodes[calendar].push(nodes[i].cname); } - for (var i = 0; i < owners.length; i++) { - ownersOfEventsToDelete.push(owners[i]); - eventsToDelete.push(sortedNodes[owners[i]]); + for (var i = 0; i < calendars.length; i++) { + calendarsOfEventsToDelete.push(calendars[i]); + eventsToDelete.push(sortedNodes[calendars[i]]); } _batchDeleteEvents(); } } } else if (selectedCalendarCell) { - var label = labels["eventDeleteConfirmation"].decodeEntities(); + var label = labels["eventDeleteConfirmation"]; if (confirm(label)) { if (document.deleteEventAjaxRequest) { document.deleteEventAjaxRequest.aborted = true; document.deleteEventAjaxRequest.abort(); } eventsToDelete.push([selectedCalendarCell[0].cname]); - ownersOfEventsToDelete.push(selectedCalendarCell[0].owner); + calendarsOfEventsToDelete.push(selectedCalendarCell[0].calendar); _batchDeleteEvents(); } } @@ -168,7 +171,7 @@ function closeInvitationWindow() { closePseudoWin.style.top = "0px;"; closePseudoWin.style.left = "0px;"; closePseudoWin.style.right = "0px;"; - closePseudoWin.appendChild(document.createTextNode(labels["closeThisWindowMessage"].decodeEntities())); + closePseudoWin.appendChild(document.createTextNode(labels["closeThisWindowMessage"])); document.body.appendChild(closeDiv); document.body.appendChild(closePseudoWin); } @@ -215,7 +218,7 @@ function deleteEventCallback(http) { } function editDoubleClickedEvent(event) { - _editEventId(this.cname, this.owner); + _editEventId(this.cname, this.calendar); preventDefault(event); event.cancelBubble = true; @@ -316,7 +319,7 @@ function eventsListCallback(http) { $(row).addClassName("eventRow"); row.setAttribute("id", escape(data[i][0])); row.cname = escape(data[i][0]); - row.owner = data[i][1]; + row.calendar = data[i][1]; var startDate = new Date(); startDate.setTime(data[i][4] * 1000); @@ -372,9 +375,8 @@ function tasksListCallback(http) { Event.observe(listItem, "dblclick", editDoubleClickedEvent.bindAsEventListener(listItem)); listItem.setAttribute("id", data[i][0]); $(listItem).addClassName(data[i][5]); - var owner = data[i][1]; - listItem.owner = owner; - $(listItem).addClassName("ownerIs" + owner.cssSafeString()); + listItem.calendar = data[i][1]; + $(listItem).addClassName("calendarFolder" + data[i][1]); listItem.cname = escape(data[i][0]); var input = document.createElement("input"); input.setAttribute("type", "checkbox"); @@ -429,7 +431,7 @@ function restoreCurrentDaySelection(div) { } function changeDateSelectorDisplay(day, keepCurrentDay) { - var url = ApplicationBaseURL + "dateselector"; + var url = ApplicationBaseURL + "/dateselector"; if (day) url += "?day=" + day; @@ -457,7 +459,7 @@ function changeDateSelectorDisplay(day, keepCurrentDay) { } function changeCalendarDisplay(time, newView) { - var url = ApplicationBaseURL + ((newView) ? newView : currentView); + var url = ApplicationBaseURL + "/" + ((newView) ? newView : currentView); selectedCalendarCell = null; @@ -583,7 +585,7 @@ function refreshCalendarEvents() { document.refreshCalendarEventsAjaxRequest.aborted = true; document.refreshCalendarEventsAjaxRequest.abort(); } - var url = ApplicationBaseURL + "eventslist?sd=" + sd + "&ed=" + ed; + var url = ApplicationBaseURL + "/eventslist?sd=" + sd + "&ed=" + ed; document.refreshCalendarEventsAjaxRequest = triggerAjaxRequest(url, refreshCalendarEventsCallback, {"startDate": sd, "endDate": ed}); @@ -608,9 +610,9 @@ function drawCalendarEvent(eventData, sd, ed) { var viewEndDate = ed.asDate(); var startDate = new Date(); - startDate.setTime(eventData[4] * 1000); + startDate.setTime(eventData[4] * 1000 + (1000 * UTCOffset)); var endDate = new Date(); - endDate.setTime(eventData[5] * 1000); + endDate.setTime(eventData[5] * 1000 + (1000 * UTCOffset)); var days = startDate.daysUpTo(endDate); @@ -636,8 +638,8 @@ function drawCalendarEvent(eventData, sd, ed) { // log("day: " + days[i]); if (i == 0) { - var quarters = (startDate.getHours() * 4 - + Math.floor(startDate.getMinutes() / 15)); + var quarters = (startDate.getUTCHours() * 4 + + Math.floor(startDate.getUTCMinutes() / 15)); starts = quarters; startHour = startDate.getDisplayHoursString(); endHour = endDate.getDisplayHoursString(); @@ -648,8 +650,8 @@ function drawCalendarEvent(eventData, sd, ed) { var ends; var lasts; if (i == days.length - 1) { - var quarters = (endDate.getHours() * 4 - + Math.ceil(endDate.getMinutes() / 15)); + var quarters = (endDate.getUTCHours() * 4 + + Math.ceil(endDate.getUTCMinutes() / 15)); ends = quarters; } else @@ -706,11 +708,11 @@ function drawCalendarEvent(eventData, sd, ed) { } } -function newEventDIV(cname, owner, starts, lasts, +function newEventDIV(cname, calendar, starts, lasts, startHour, endHour, title) { var eventDiv = document.createElement("div"); eventDiv.cname = escape(cname); - eventDiv.owner = owner; + eventDiv.calendar = calendar; $(eventDiv).addClassName("event"); $(eventDiv).addClassName("starts" + starts); $(eventDiv).addClassName("lasts" + lasts); @@ -723,7 +725,7 @@ function newEventDIV(cname, owner, starts, lasts, var innerDiv = document.createElement("div"); eventDiv.appendChild(innerDiv); $(innerDiv).addClassName("eventInside"); - $(innerDiv).addClassName("ownerIs" + owner.cssSafeString()); + $(innerDiv).addClassName("calendarFolder" + calendar); var gradientDiv = document.createElement("div"); innerDiv.appendChild(gradientDiv); @@ -881,7 +883,7 @@ function _loadEventHref(href) { document.eventsListAjaxRequest.aborted = true; document.eventsListAjaxRequest.abort(); } - var url = ApplicationBaseURL + href; + var url = ApplicationBaseURL + "/" + href; document.eventsListAjaxRequest = triggerAjaxRequest(url, eventsListCallback, href); @@ -897,7 +899,7 @@ function _loadTasksHref(href) { document.tasksListAjaxRequest.aborted = true; document.tasksListAjaxRequest.abort(); } - url = ApplicationBaseURL + href; + url = ApplicationBaseURL + "/" + href; var tasksList = $("tasksList"); var selectedIds; @@ -1119,7 +1121,6 @@ function onShowCompletedTasks(event) { function updateTaskStatus(event) { var taskId = this.parentNode.getAttribute("id"); - var taskOwner = this.parentNode.owner; var newStatus = (this.checked ? 1 : 0); var http = createHTTPClient(); @@ -1128,9 +1129,8 @@ function updateTaskStatus(event) { //log("update task status: " + taskId + " to " + this.checked); event.cancelBubble = true; - url = (UserFolderURL + "../" + taskOwner - + "/Calendar/" + taskId - + "/changeStatus?status=" + newStatus); + url = (ApplicationBaseURL + "/" + this.parentNode.calendar + + "/" + taskId + "/changeStatus?status=" + newStatus); if (http) { // log ("url: " + url); @@ -1162,10 +1162,11 @@ function updateCalendarStatus(event) { } } - if (!list.length) { - list.push(UserLogin); - nodes[0].childNodesWithTag("input")[0].checked = true; - } +// if (!list.length) { +// list.push(UserLogin); +// nodes[0].childNodesWithTag("input")[0].checked = true; +// } + // ApplicationBaseURL = (UserFolderURL + "Groups/_custom_" // + list.join(",") + "/Calendar/"); @@ -1207,7 +1208,7 @@ function calendarStatusCallback(http) { } function calendarEntryCallback(http) { - if (http.readyState == 4) { + if (http.readyState == 4) { var denied = !isHttpStatus204(http.status); var entry = $(http.callbackData); if (denied) @@ -1339,79 +1340,94 @@ function initCalendarSelector() { } var links = $("calendarSelectorButtons").childNodesWithTag("a"); - Event.observe(links[0], "click", onCalendarAdd); - Event.observe(links[1], "click", onCalendarRemove); + Event.observe(links[0], "click", onCalendarNew); + Event.observe(links[1], "click", onCalendarAdd); + Event.observe(links[2], "click", onCalendarRemove); +} + +function onCalendarNew(event) { + createFolder(window.prompt(labels["Name of the Calendar"]), + appendCalendar); + preventDefault(event); } function onCalendarAdd(event) { - openUserFolderSelector(onFolderSubscribeCB, "calendar"); - - preventDefault(event); + openUserFolderSelector(onFolderSubscribeCB, "calendar"); + preventDefault(event); } function appendCalendar(folderName, folder) { - var calendarList = $("calendarList"); - var lis = calendarList.childNodesWithTag("li"); - var color = indexColor(lis.length); - //log ("color: " + color); + if (folder) + folder = accessToSubscribedFolder(folder); + else + folder = "/" + folderName; - var li = document.createElement("li"); - calendarList.appendChild(li); +// log ("append: " + folderName + "; folder: " + folder); - var checkBox = document.createElement("input"); - checkBox.setAttribute("type", "checkbox"); - li.appendChild(checkBox); + var calendarList = $("calendarList"); + var lis = calendarList.childNodesWithTag("li"); + var color = indexColor(lis.length + 100); + //log ("color: " + color); + + var li = document.createElement("li"); + calendarList.appendChild(li); + + var checkBox = document.createElement("input"); + checkBox.setAttribute("type", "checkbox"); + li.appendChild(checkBox); - li.appendChild(document.createTextNode(" ")); + li.appendChild(document.createTextNode(" ")); - var colorBox = document.createElement("div"); - li.appendChild(colorBox); - li.appendChild(document.createTextNode(" " + folderName)); - colorBox.appendChild(document.createTextNode("OO")); + var colorBox = document.createElement("div"); + li.appendChild(colorBox); + li.appendChild(document.createTextNode(" " + folderName)); + colorBox.appendChild(document.createTextNode("OO")); - li.setAttribute("id", folder); - Event.observe(li, "mousedown", listRowMouseDownHandler); - Event.observe(li, "click", onRowClick); - $(checkBox).addClassName("checkBox"); + li.setAttribute("id", folder); + Event.observe(li, "mousedown", listRowMouseDownHandler); + Event.observe(li, "click", onRowClick); + $(checkBox).addClassName("checkBox"); - Event.observe(checkBox, "click", updateCalendarStatus.bindAsEventListener(checkBox)); + Event.observe(checkBox, "click", + updateCalendarStatus.bindAsEventListener(checkBox)); - $(colorBox).addClassName("colorBox"); - if (color) { - $(colorBox).setStyle({ color: color, - backgroundColor: color }); - } + $(colorBox).addClassName("colorBox"); + if (color) + $(colorBox).setStyle({color: color, + backgroundColor: color}); - var contactId = folder.split(":")[0]; - var url = URLForFolderID(folder) + "/canAccessContent"; - triggerAjaxRequest(url, calendarEntryCallback, folder); + var url = URLForFolderID(folder) + "/canAccessContent"; + triggerAjaxRequest(url, calendarEntryCallback, folder); - if (!document.styleSheets) return; - var theRules = new Array(); - var lastSheet = document.styleSheets[document.styleSheets.length - 1]; - if (lastSheet.insertRule) { // Mozilla - lastSheet.insertRule('.ownerIs' + contactId.cssSafeString() + ' {' - + ' background-color: ' - + color - + ' !important; }', 0); - } - else { // IE - lastSheet.addRule('.ownerIs' + contactId.cssSafeString(), - ' background-color: ' - + color - + ' !important; }'); - } + if (!document.styleSheets) return; + var theRules = new Array(); + var lastSheet = document.styleSheets[document.styleSheets.length - 1]; + if (lastSheet.insertRule) { // Mozilla + lastSheet.insertRule('.calendarFolder' + folder.substr(1) + ' {' + + ' background-color: ' + + color + + ' !important; }', 0); + } + else { // IE + lastSheet.addRule('.calendarFolder' + folder.substr(1), + ' background-color: ' + + color + + ' !important; }'); + } } function onFolderSubscribeCB(folderData) { var folder = $(folderData["folder"]); if (!folder) - appendCalendar(folderData["folderName"], folderData["folder"]); + appendCalendar(folderData["folderName"], folderData["folder"]); } function onFolderUnsubscribeCB(folderId) { - var node = $(folderId); - node.parentNode.removeChild(node); + var node = $(folderId); + node.parentNode.removeChild(node); + refreshEvents(); + refreshTasks(); + changeCalendarDisplay(); } function onCalendarRemove(event) { @@ -1419,15 +1435,59 @@ function onCalendarRemove(event) { if (nodes.length > 0) { nodes[0].deselect(); var folderId = nodes[0].getAttribute("id"); - var folderIdElements = folderId.split(":"); + var folderIdElements = folderId.split("_"); if (folderIdElements.length > 1) { - unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId); + unsubscribeFromFolder(folderId, onFolderUnsubscribeCB, folderId); + } + else { + var calId = folderIdElements[0].substr(1); + deletePersonalCalendar(calId); } } preventDefault(event); } +function deletePersonalCalendar(folderId) { + var label + = labels["Are you sure you want to delete the selected calendar?"]; + if (window.confirm(label)) { + if (document.deletePersonalCalendarAjaxRequest) { + document.deletePersonalCalendarAjaxRequest.aborted = true; + document.deletePersonalCalendarAjaxRequest.abort(); + } + var url = ApplicationBaseURL + "/" + folderId + "/deleteFolder"; + document.deletePersonalCalendarAjaxRequest + = triggerAjaxRequest(url, deletePersonalCalendarCallback, folderId); + } +} + +function deletePersonalCalendarCallback(http) { + if (http.readyState == 4) { + if (isHttpStatus204(http.status)) { + var ul = $("calendarList"); + var children = ul.childNodesWithTag("li"); + var i = 0; + var done = false; + while (!done && i < children.length) { + var currentFolderId = children[i].getAttribute("id").substr(1); + if (currentFolderId == http.callbackData) { + ul.removeChild(children[i]); + done = true; + } + else + i++; + } + refreshEvents(); + refreshTasks(); + changeCalendarDisplay(); + } + document.deletePersonalCalendarAjaxRequest = null; + } + else + log ("ajax problem 5: " + http.status); +} + function configureLists() { var list = $("tasksList"); list.multiselect = true; diff --git a/UI/WebServerResources/UIxContactsUserFolders.js b/UI/WebServerResources/UIxContactsUserFolders.js index d060d319a..bfcbd245c 100644 --- a/UI/WebServerResources/UIxContactsUserFolders.js +++ b/UI/WebServerResources/UIxContactsUserFolders.js @@ -30,7 +30,7 @@ function addLineToTree(tree, parent, line) { for (var i = 1; i < nodes.length; i++) { var folderInfos = nodes[i].split(":"); var icon = ResourcesURL + '/'; - if (folderInfos[2] == 'contact') + if (folderInfos[2] == 'Contacts') icon += 'tb-mail-addressbook-flat-16x16.png'; else icon += 'calendar-folder-16x16.png'; diff --git a/UI/WebServerResources/add-user-calendar.png b/UI/WebServerResources/add-user-calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..30c3926729341e6139a73fb00c1d19a20da78ead GIT binary patch literal 1168 zcmV;B1aJF^P){B`O6&2%rD}1RY64 zK~zY`?UhStlvfnTf0N8iCYi*^#2Bk%s)D9A@s$`OM*7f29~1(%T~sI(3Y9`BNU_jG z7jCag)7_DehwMK(^CzCjjZ@%Y!b@7cciAJG|u6p3Yx%WHg z{_pvp#|Qt*Vx21Y<(YEO0U=f+<^2{$|QbPQq&!-1&Q>_mtXb zgswwRfz;s=8k7QI7M!WjSea0l2Ba$6hCU}p+(i*oJTg8LS@On6xQtmCeEIDDE}xq_ z_GkdJWMd*_u!TTn-2f4@>>KAPI`QUdx(;{XiZEKKLnf30Ap~y8LJC1~>?R|>e@9KG zg*DH2aMbvXT`cF=y>57QZd2b zD+jrJ_Av)d5x&o@o6}UpBed?`!s^BpUVes#bOUQM zO;kPE%v@6&s_d%+@%TP4Cgd}oOyS2@kvQ;z8Z2Xy@ zhTmh#y0LtjY9Zz;!6<_QqBSX!+xC%&3!=s_J2?%2TXHBBET--j8EVLJaL;~nr2+%} zeQ3F6d5V+)1xT$!AR?$}HMtG1F!slnv}Nb0N+fV?hkV}RjJq4T!b0JrD+3(gLIsV> zR8bJj*S^vw94%6F?#5k)^aiG%ewRP3)y#Tv227rF%?^c~SxjsUTi7_lW_Yrnk@ydM z@YRu?j-xxeAEc<*DF?T2M&MzKT8cptM?36% zxe6-~WOIe~c&_qmpm{+j2b?|qTc|6;`7^)Jd)1|7#{payTn}pM+vvSGN^^(66*fLD zwzRQ@gC%^dKwt?$DG-SA?UhpmB8rgUcm^e7L@P4f>OaJ_OQ&$X zBGKyG>^qpI;Q0LYy@$+3X 1) { + var paths = parts[1].split("/"); + folder = "/" + parts[0] + "_" + paths[2]; + } + else + folder = serverFolder; + + return folder; } function listRowMouseDownHandler(event) { @@ -1277,12 +1291,25 @@ function onLoadHandler(event) { configureDragHandles(); configureSortableTableHeaders(); configureLinkBanner(); + translateLabels(); var progressImage = $("progressIndicator"); if (progressImage) progressImage.parentNode.removeChild(progressImage); Event.observe(document.body, "contextmenu", onBodyClickContextMenu); } +function translateLabels() { + if (typeof labels != "undefined") { + for (var key in labels) + labels[key] = labels[key].decodeEntities(); + } + + if (typeof clabels != "undefined") { + for (var key in clabels) + clabels[key] = clabels[key].decodeEntities(); + } +} + function onBodyClickContextMenu(event) { preventDefault(event); } @@ -1328,6 +1355,38 @@ function configureLinkBanner() { } } +/* folder creation */ +function createFolder(name, okCB, notOkCB) { + if (name) { + if (document.newFolderAjaxRequest) { + document.newFolderAjaxRequest.aborted = true; + document.newFolderAjaxRequest.abort(); + } + var url = ApplicationBaseURL + "/createFolder?name=" + name; + document.newFolderAjaxRequest + = triggerAjaxRequest(url, createFolderCallback, + {name: name, + okCB: okCB, + notOkCB: notOkCB}); + } +} + +function createFolderCallback(http) { + if (http.readyState == 4) { + var data = http.callbackData; + if (http.status == 201) { + if (data.okCB) + data.okCB(data.name, "/" + http.responseText); + } + else { + if (data.notOkCB) + data.notOkCB(name); + else + log("ajax problem:" + http.status); + } + } +} + addEvent(window, 'load', onLoadHandler); function parent$(element) { From 21718aeac2aaec564cca74bfd68956c5e00eb254 Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Fri, 14 Sep 2007 22:02:15 +0000 Subject: [PATCH 6/6] Monotone-Parent: 92e93f3527a76deed69fa61275517490d57f9a4f Monotone-Revision: f12c75a72aac13edc9728fe5a656c622487836dd Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-09-14T22:02:15 Monotone-Branch: ca.inverse.sogo --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index f0c0a1b08..b51426397 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ - fixed a bug where a false positive happening whenever a wrong user login was given during an indirect bind; - deleting a message no longer expunges its parent folder; +- implemented support for multiple calendars; +- it is not possible to rename folders; - fixed search in message content; - countless bugfixes;