]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1071 d1b88da0-ebda-0310...
authorwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 30 May 2007 20:26:42 +0000 (20:26 +0000)
committerwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 30 May 2007 20:26:42 +0000 (20:26 +0000)
78 files changed:
ChangeLog
SoObjects/Appointments/SOGoCalendarComponent.m
SoObjects/Mailer/SOGoMailAccount.h
SoObjects/Mailer/SOGoMailAccount.m
SoObjects/Mailer/SOGoMailAccounts.m
SoObjects/Mailer/SOGoMailBaseObject.m
SoObjects/Mailer/SOGoMailFolder.h
SoObjects/Mailer/SOGoMailFolder.m
SoObjects/Mailer/product.plist
SoObjects/SOGo/GNUmakefile
SoObjects/SOGo/LDAPUserManager.h
SoObjects/SOGo/LDAPUserManager.m
SoObjects/SOGo/NSArray+Utilities.h
SoObjects/SOGo/NSArray+Utilities.m
SoObjects/SOGo/NSDictionary+Utilities.h [new file with mode: 0644]
SoObjects/SOGo/NSDictionary+Utilities.m [new file with mode: 0644]
SoObjects/SOGo/NSObject+Utilities.h [new file with mode: 0644]
SoObjects/SOGo/NSObject+Utilities.m [new file with mode: 0644]
SoObjects/SOGo/NSString+Utilities.h
SoObjects/SOGo/NSString+Utilities.m
SoObjects/SOGo/SOGoContentObject.m
SoObjects/SOGo/SOGoFolder.m
SoObjects/SOGo/SOGoObject.h
SoObjects/SOGo/SOGoObject.m
SoObjects/SOGo/SOGoUser.h
SoObjects/SOGo/SOGoUser.m
UI/Common/UIxFolderActions.h
UI/Common/UIxFolderActions.m
UI/Common/UIxObjectActions.m
UI/MailerUI/English.lproj/Localizable.strings
UI/MailerUI/French.lproj/Localizable.strings
UI/MailerUI/GNUmakefile
UI/MailerUI/MailerUIProduct.m
UI/MailerUI/UIxMailAccountActions.h [new file with mode: 0644]
UI/MailerUI/UIxMailAccountActions.m [new file with mode: 0644]
UI/MailerUI/UIxMailFolderActions.h [new file with mode: 0644]
UI/MailerUI/UIxMailFolderActions.m [new file with mode: 0644]
UI/MailerUI/UIxMailListView.m
UI/MailerUI/UIxMailMainFrame.m
UI/MailerUI/product.plist
UI/SOGoUI/GNUmakefile
UI/SOGoUI/SOGoACLAdvisory.h [new file with mode: 0644]
UI/SOGoUI/SOGoACLAdvisory.m [new file with mode: 0644]
UI/SOGoUI/SOGoACLEnglishAdditionAdvisory.h [new file with mode: 0644]
UI/SOGoUI/SOGoACLEnglishAdditionAdvisory.m [new file with mode: 0644]
UI/SOGoUI/SOGoACLEnglishRemovalAdvisory.h [new file with mode: 0644]
UI/SOGoUI/SOGoACLEnglishRemovalAdvisory.m [new file with mode: 0644]
UI/SOGoUI/SOGoACLFrenchAdditionAdvisory.h [new file with mode: 0644]
UI/SOGoUI/SOGoACLFrenchAdditionAdvisory.m [moved from UI/MailerUI/UIxMailSplashView.m with 77% similarity]
UI/SOGoUI/SOGoACLFrenchRemovalAdvisory.h [new file with mode: 0644]
UI/SOGoUI/SOGoACLFrenchRemovalAdvisory.m [new file with mode: 0644]
UI/Templates/MailerUI/UIxMailAccountView.wox [deleted file]
UI/Templates/MailerUI/UIxMailMainFrame.wox
UI/Templates/SOGoACLEnglishAdditionAdvisory.wox [new file with mode: 0644]
UI/Templates/SOGoACLEnglishRemovalAdvisory.wox [new file with mode: 0644]
UI/Templates/SOGoACLFrenchAdditionAdvisory.wox [new file with mode: 0644]
UI/Templates/SOGoACLFrenchRemovalAdvisory.wox [new file with mode: 0644]
UI/Templates/UIxPageFrame.wox
UI/WebServerResources/ContactsUI.js
UI/WebServerResources/HTMLElement.js
UI/WebServerResources/HTMLInputElement.js
UI/WebServerResources/HTMLTableElement.js
UI/WebServerResources/HTMLUListElement.js
UI/WebServerResources/JavascriptAPIExtensions.js
UI/WebServerResources/MailerUI+dTree.js [new file with mode: 0644]
UI/WebServerResources/MailerUI.css
UI/WebServerResources/MailerUI.js
UI/WebServerResources/SOGoDragAndDrop.js
UI/WebServerResources/SOGoDragHandles.js
UI/WebServerResources/SchedulerUI.css
UI/WebServerResources/SchedulerUI.js
UI/WebServerResources/UIxAppointmentEditor.js
UI/WebServerResources/UIxAttendeesEditor.js
UI/WebServerResources/UIxComponentEditor.js
UI/WebServerResources/UIxTaskEditor.js
UI/WebServerResources/dtree.js
UI/WebServerResources/generic.css
UI/WebServerResources/generic.js

index 01566a18ac9613bd5806ebece4f2da1fc372822f..681ee4de67d48fcbf84f7205d49d80dc21cea886 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,176 @@
+2007-05-30  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * UI/Common/UIxObjectActions.m ([UIxObjectActions
+       -addUserInAclsAction]): send an acl addition mail.
+       ([UIxObjectActions -removeUserFromAclsAction]): send an acl
+       removal mail.
+
+       * UI/Common/UIxFolderActions.m ([UIxFolderActions
+       -_realActionWithFolderName:folderDict]): handle the possible
+       presence of the "mail-invitation" url parameter. If present, the
+       user will be redirected to the relevant folder.
+
+       * SoObjects/SOGo/SOGoUser.m ([SOGoUser -fullEmail]): new proxy method.
+       ([SOGoUser -language]): new method that returns the user's
+       preferred language, or the system's if none has been set yet.
+
+       * SoObjects/SOGo/SOGoObject.m ([SOGoObject -davURL]): new method
+       that returns the full dav url to self.
+       ([SOGoObject -soURL]): same as above but for the so url (Web UI).
+       ([SOGoObject -soURLToBaseContainerForUser:uid]): new method that
+       returns the full so url to the base of the SOGo module to which
+       self belongs, and for the specified user.
+       ([SOGoObject -soURLToBaseContainerForCurrentUser]): same as above
+       but for the current user.
+       ([SOGoObject -httpURLForAdvisoryToUser:uid]): new protocol method
+       required by the acl advisory templates and which returns a link
+       the target user can click to activate its new subscription.
+       ([SOGoObject -resourceURLForAdvisoryToUser:uid]): same as above
+       but for inclusion of the application/x-sogo-notification part,
+       which will be handled by the Lightning enhancer plugin.
+
+       * UI/MailerUI/UIxMailFolderActions.m ([UIxMailFolderActions -subscribeAction]) 
+       ([UIxMailFolderActions -unsubscribeAction]): new stub methods that
+       do nothing yet since imap folder subscription is not handled yet.
+
+       * SoObjects/SOGo/SOGoContentObject.m
+       ([-hasSupportForDefaultRoles]): removed method.
+
+       * SoObjects/SOGo/LDAPUserManager.m ([LDAPUserManager
+       -getFullEmailForUID:uid]): new method that returns the username +
+       email pair.
+
+       * SoObjects/Appointments/SOGoCalendarComponent.m
+       ([SOGoCalendarComponent +initialize]): the default language for
+       mail templates is now set to English.
+
+       * UI/SOGoUI/SOGoACLFrenchRemovalAdvisory.[hm]: new subclass of
+       SOGoACLAdvisory implementing the french template for user removal
+       from acls.
+
+       * UI/SOGoUI/SOGoACLFrenchAdditionAdvisory.[hm]: new subclass of
+       SOGoACLAdvisory implementing the french template for user
+       additions to acls.
+
+       * UI/SOGoUI/SOGoACLEnglishRemovalAdvisory.[hm]: new subclass of
+       SOGoACLAdvisory implementing the english template for user removal
+       from acls.
+
+       * UI/SOGoUI/SOGoACLEnglishAdditionAdvisory.[hm]: new subclass of
+       SOGoACLAdvisory implementing the english template for user
+       additions to acls.
+
+       * UI/SOGoUI/SOGoACLAdvisory.[hm]: new class module implemented the
+       supercall of all the acl advistory templates. The model is based
+       on SOGoAptMailNotification except that the template encapsulates
+       the message to be sent. Later, we might create a superclass common
+       to all template-based emails.
+
+       * SoObjects/SOGo/NSArray+Utilities.m ([NSMutableArray
+       -addRange:newRange]): new method that store a string
+       representation of the NSRange passed as parameter.
+       ([NSMutableArray -hasRangeIntersection:testRange]): tests whether
+       any range contained in self intersect with the one passed as parameter.
+
+       * SoObjects/SOGo/NSString+Utilities.m ([-stringByDetectingURLs]):
+       store ranges in an array to prevent them from intersecting with
+       each other during the passes.
+
+2007-05-29  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * SoObjects/Mailer/SOGoMailFolder.m ([SOGoMailFolder
+       -primaryFetchMailboxInfo]): useless method. Removed.
+
+2007-05-28  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * SoObjects/Mailer/SOGoMailFolder.m ([SOGoMailFolder
+       -toManyRelationshipKeys]): invoke [self subfolders].
+       ([SOGoMailFolder -subfolders]): new method containing what used to
+       be in toManyRelationshipKeys.
+       ([SOGoMailFolder -subfoldersURL]): same as above but returns imap
+       urls.
+
+       * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount
+       -allFolderPaths]): renamed version of "allFolderPathes", sorted by
+       named and at the beginning of which we put the predefined folders.
+
+       * UI/MailerUI/UIxMailFolderActions.m ([UIxMailFolderActions
+       -emptyTrashAction]): new method inspired by a similar one from
+       UIxMailListView, to which we added the ability to remove
+       subfolders.
+
+       * UI/MailerUI/UIxMailListView.m ([-emptyTrashAction]): removed
+       method. Replaced with a similar one in UIxMailFolderActions.
+
+       * UI/MailerUI/UIxMailFolderActions.m ([UIxMailFolderActions
+       -renameFolderAction]): implemented method.
+       ([UIxMailFolderActions -deleteFolderAction]): no longer delete the
+       specified folder. Instead, we put it in the trash folder.
+
+       * UI/MailerUI/UIxMailListView.m ([-createFolderAction]): removed
+       method, replaced with a similar method in the new
+       UIxMailFolderAction class module.
+       ([-deleteFolderAction]): idem.
+
+       * UI/MailerUI/UIxMailFolderActions.m ([UIxMailFolderActions
+       -createFolderAction]): new method implementing subfolder creation.
+       ([UIxMailFolderActions -renameFolderAction]): new method
+       implementing subfolder renaming (basic implementation to be
+       finalized later).
+       ([UIxMailFolderActions -deleteFolderAction]): new method
+       implementing folder deletion.
+
+       * UI/MailerUI/UIxMailFolderActions.[hm]: new module implementing
+       web actions related to the handling of imap folder.
+
+2007-05-25  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * SoObjects/Mailer/SOGoMailFolder.m ([SOGoMailFolder
+       -ownerInContext:localContext]): overriden method because we are an
+       IMAP4 client and we need a bit more intelligence to deduce the
+       owner of the current folder.
+       ([SOGoMailFolder -aclsForUser:uid]): aclForMailboxAtURL might
+       return an NSException so we need to be careful here to avoid a
+       crash.
+       ([SOGoMailFolder -aclUsers]): aclForMailboxAtURL might return an
+       NSException so we need to be careful here to avoid a crash.
+
+       * SoObjects/Mailer/SOGoMailAccounts.m
+       ([SOGoMailAccounts -fetchIdentitiesWithOnlyEmitterAccess:_flag])
+       there is no longer any concept of Intranet or Internet connection
+       handling.
+
+       * SoObjects/Mailer/SOGoMailAccount.m ([SOGoMailAccount
+       -sharedFolderName]): new method.
+       ([SOGoMailAccount -otherUsersFolderName]): new method.
+
+       * UI/MailerUI/UIxMailFolderMenu.[hm]: removed module, obsoleted by
+       new javascript code and the new UIxMailAccountActions class.
+
+       * UI/MailerUI/UIxMailTree.[hm]: removed module, obsoleted by new
+       javascript code and the new UIxMailAccountActions class.
+
+       * UI/MailerUI/UIxMailTreeBlock.[hm]: removed module, obsoleted by
+       new javascript code and the new UIxMailAccountActions class.
+
+       * UI/MailerUI/UIxMailAccountActions.m ([UIxMailAccountActions
+       -listMailboxesAction]): new method that returns a json-formatted
+       tree of all the mailboxes available to the current user.
+
+       * UI/MailerUI/UIxMailAccountActions.[hm]: new module implementing
+       web actions related to the handling of mail accounts.
+
+       * SoObjects/SOGo/NSDictionary+Utilities.[hm]: new extension
+       module.
+
+       * SoObjects/SOGo/NSObject+Utilities.m ([NSObject
+       -jsonRepresentation]): new interface method meant to be overriden
+       by the primitive classes.
+
 2007-05-23  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
+       * UI/MailerUI/UIxMailSplashView.m: removed.
+
        * SoObjects/Appointments/SOGoCalendarComponent.m
        ([SOGoCalendarComponent -getUIDsForICalPersons:iCalPersons]): add
        the uid to the list only when the user email is recognized by the
index 14267daf85c54e2a955c95c30efc8bb4080c614f..e6a6a65c3f8026173c920a7e2c8763ccaf80f4dc 100644 (file)
@@ -57,7 +57,7 @@ static BOOL sendEMailNotifications = NO;
       mailTemplateDefaultLanguage = [[ud stringForKey:@"SOGoDefaultLanguage"]
                                       retain];
       if (!mailTemplateDefaultLanguage)
-        mailTemplateDefaultLanguage = @"French";
+        mailTemplateDefaultLanguage = @"English";
 
       sendEMailNotifications
         = [ud boolForKey: @"SOGoAppointmentSendEMailNotifications"];
@@ -377,6 +377,8 @@ static BOOL sendEMailNotifications = NO;
           else
             recipient = email;
 
+#warning this could be optimized in a class hierarchy common with the \
+          SOGoObject's acl notification mechanism
           /* create page name */
           // TODO: select user's default language?
           pageName = [NSString stringWithFormat: @"SOGoAptMail%@%@",
@@ -513,7 +515,7 @@ static BOOL sendEMailNotifications = NO;
   iCalPerson *currentPerson;
   NSEnumerator *persons;
   NSMutableArray *uids;
-  NSString *email, *uid;
+  NSString *uid;
   LDAPUserManager *um;
 
   uids = [NSMutableArray array];
index 00fa792f6f44d976a1a261d26264ad869fec9d0b..d9bd07513cad13e3eebd6bca34a7c1e357ab2da5 100644 (file)
@@ -45,7 +45,7 @@
 
 /* folder pathes */
 
-- (NSArray *)allFolderPathes;
+- (NSArray *)allFolderPaths;
 - (NSArray *)additionalRootFolderNames; /* stuff like filters and drafts */
 
 /* shared accounts */
 - (SOGoMailFolder *)sentFolderInContext:(id)_ctx;
 - (SOGoMailFolder *)trashFolderInContext:(id)_ctx;
 
+/* user defaults */
+- (NSString *) sharedFolderName;
+- (NSString *) otherUsersFolderName;
+
 @end
 
 #endif /* __Mailer_SOGoMailAccount_H__ */
index a1c6285d92eb7a5411bebde5c5fea337cce9c66b..184274881e6b060313312859d309a479354f0f89 100644 (file)
@@ -134,12 +134,23 @@ static BOOL     useAltNamespace       = NO;
   return self;
 }
 
-- (NSArray *)allFolderPathes {
-  NSArray *pathes;
-  
-  pathes = [[self imap4Connection] allFoldersForURL:[self imap4URL] ];
-  pathes = [pathes sortedArrayUsingSelector:@selector(compare:)];
-  return pathes;
+- (NSArray *) allFolderPaths
+{
+  NSMutableArray *newFolders;
+  NSArray *rawFolders, *mainFolders;
+
+  rawFolders = [[self imap4Connection]
+                allFoldersForURL: [self imap4URL]];
+
+  mainFolders = [NSArray arrayWithObjects: inboxFolderName, draftsFolderName,
+                        sentFolder, trashFolder, nil];
+  newFolders = [NSMutableArray arrayWithArray: rawFolders];
+  [newFolders removeObjectsInArray: mainFolders];
+  [newFolders sortUsingSelector: @selector (caseInsensitiveCompare:)];
+  [newFolders replaceObjectsInRange: NSMakeRange (0, 0)
+             withObjectsFromArray: mainFolders];
+
+  return newFolders;
 }
 
 /* IMAP4 */
@@ -418,4 +429,14 @@ static BOOL     useAltNamespace       = NO;
   return [self shortTitle];
 }
 
+- (NSString *) sharedFolderName
+{
+  return sharedFolderName;
+}
+
+- (NSString *) otherUsersFolderName
+{
+  return otherUsersFolderName;
+}
+
 @end /* SOGoMailAccount */
index 836ee5549c1d7d718171d3eb9c0d21418625ef1c..d215e8e104ef6231a73737199f1230e8612ac490 100644 (file)
@@ -80,18 +80,13 @@ static NSString *AgenorShareLoginMarker  = @".-.";
     : [account arrayByAddingObjectsFromArray:shares];
 }
 
-- (NSArray *)fetchIdentitiesWithOnlyEmitterAccess:(BOOL)_flag {
-  WOContext *ctx;
-  
-  if ([self isInternetRequest]) { /* only show primary mailbox in Internet */
-    // just return the primary identity
-    id identity;
-    
-    identity = [[context activeUser] primaryMailIdentity];
-    return [identity isNotNull] ? [NSArray arrayWithObject:identity] : nil;
-  }
-  
-  return [[ctx activeUser] fetchAllMailIdentitiesWithOnlyEmitterAccess:_flag];
+- (NSArray *) fetchIdentitiesWithOnlyEmitterAccess: (BOOL) _flag
+{
+  NSString *accountString;
+
+  accountString = [[context activeUser] primaryIMAP4AccountString];
+
+  return [NSArray arrayWithObject: accountString];
 }
 
 - (NSArray *)fetchAllIdentities {
@@ -185,11 +180,13 @@ static NSString *AgenorShareLoginMarker  = @".-.";
 
 /* WebDAV */
 
-- (BOOL)davIsCollection {
+- (BOOL) davIsCollection
+{
   return YES;
 }
 
 /* acls */
+
 - (NSArray *) aclsForUser: (NSString *) uid
 {
   return nil;
index 8a715c8638defdeb1ffbebdeb8d4560b57294810..af97cb7c2a779c7c959f08ca02c82fbf8a27c6f2 100644 (file)
@@ -183,8 +183,6 @@ static BOOL debugOn = YES;
   return NO;
 }
 
-/* acls */
-#warning one day there will be code here to support IMAP acls
 - (NSArray *) aclsForUser: (NSString *) uid
 {
   return nil;
index a698bdaaaed0f5b356de1af2a90d9e70be76c058..f6fd2f538c157a19f22dc6584f51432c2579e440 100644 (file)
@@ -40,7 +40,6 @@
 {
   NSArray            *filenames;
   NSString           *folderType;
-  NGImap4MailboxInfo *selectInfo;
 }
 
 /* messages */
@@ -60,6 +59,9 @@
 
 - (NSString *)outlookFolderClass;
 
+- (NSArray *) subfolders;
+- (NSArray *) subfoldersURL;
+
 @end
 
 #endif /* __Mailer_SOGoMailFolder_H__ */
index 6c7c84cb1a6a68a16675e9af06d39c4adede04b6..f3b86ab151b49c010ea2a004a244adec58500ae6 100644 (file)
 #import <NGExtensions/NSNull+misc.h>
 #import <NGExtensions/NSURL+misc.h>
 #import <NGExtensions/NSObject+Logs.h>
+#import <NGExtensions/NSString+misc.h>
 
 #import <NGImap4/NGImap4Connection.h>
-#import <NGImap4/NGImap4MailboxInfo.h>
 #import <NGImap4/NGImap4Client.h>
 
 #import <SoObjects/SOGo/SOGoPermissions.h>
+#import <SoObjects/SOGo/SOGoUser.h>
 #import <SoObjects/SOGo/NSArray+Utilities.h>
 
 #import "SOGoMailObject.h"
@@ -45,11 +46,13 @@ static NSString *defaultUserID =  @"anyone";
 
 static BOOL useAltNamespace = NO;
 
-+ (int)version {
++ (int) version
+{
   return [super version] + 0 /* v1 */;
 }
 
-+ (void)initialize {
++ (void) initialize
+{
   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
 
   NSAssert2([super version] == 1,
@@ -59,8 +62,8 @@ static BOOL useAltNamespace = NO;
   useAltNamespace = [ud boolForKey:@"SOGoSpecialFoldersInRoot"];
 }
 
-- (void)dealloc {
-  [selectInfo release];
+- (void) dealloc
+{
   [filenames  release];
   [folderType release];
   [super dealloc];
@@ -68,17 +71,52 @@ static BOOL useAltNamespace = NO;
 
 /* IMAP4 */
 
-- (NSString *)relativeImap4Name {
+- (NSString *) relativeImap4Name
+{
   return [self nameInContainer];
 }
 
 /* listing the available folders */
 
-- (NSArray *)toManyRelationshipKeys {
-  return [[self imap4Connection] subfoldersForURL:[self imap4URL]];
+- (NSArray *) toManyRelationshipKeys
+{
+  return [self subfolders];
+}
+
+- (NSArray *) subfolders
+{
+  return [[self imap4Connection] subfoldersForURL: [self imap4URL]];
+}
+
+- (NSArray *) subfoldersURL
+{
+  NSURL *selfURL, *currentURL;
+  NSMutableArray *subfoldersURL;
+  NSEnumerator *subfolders;
+  NSString *selfPath, *currentFolder;
+
+  subfoldersURL = [NSMutableArray array];
+  selfURL = [self imap4URL];
+  selfPath = [selfURL path];
+  subfolders = [[self subfolders] objectEnumerator];
+  currentFolder = [subfolders nextObject];
+  while (currentFolder)
+    {
+      currentURL = [[NSURL alloc]
+                    initWithScheme: [selfURL scheme]
+                    host: [selfURL host]
+                    path: [selfPath stringByAppendingPathComponent:
+                                      currentFolder]];
+      [currentURL autorelease];
+      [subfoldersURL addObject: currentURL];
+      currentFolder = [subfolders nextObject];
+    }
+
+  return subfoldersURL;
 }
 
-- (NSArray *)toOneRelationshipKeys {
+- (NSArray *) toOneRelationshipKeys
+{
   NSArray  *uids;
   unsigned count;
   
@@ -110,7 +148,8 @@ static BOOL useAltNamespace = NO;
   return filenames;
 }
 
-- (EODataSource *)contentDataSourceInContext:(id)_ctx {
+- (EODataSource *) contentDataSourceInContext: (id) _ctx
+{
   SOGoMailFolderDataSource *ds;
   
   ds = [[SOGoMailFolderDataSource alloc] initWithImap4URL:[self imap4URL]
@@ -118,55 +157,48 @@ static BOOL useAltNamespace = NO;
   return [ds autorelease];
 }
 
-/* mailbox raw ops */
-
-- (NSException *)primaryFetchMailboxInfo {
-  /* returns nil if fetch was successful */
-  id info;
-  
-  if (selectInfo != nil)
-    return nil; /* select info exists, => no error */
-  
-  info = [[self imap4Connection] infoForMailboxAtURL:[self imap4URL]];
-  if ([info isKindOfClass:[NSException class]])
-    return info;
-  
-  selectInfo = [info retain];
-  return nil; /* no error */
-}
-
 /* messages */
 
-- (NSArray *)fetchUIDsMatchingQualifier:(id)_q sortOrdering:(id)_so {
+- (NSArray *) fetchUIDsMatchingQualifier: (id) _q
+                           sortOrdering: (id) _so
+{
   /* seems to return an NSArray of NSNumber's */
   return [[self imap4Connection] fetchUIDsInURL:[self imap4URL]
                                 qualifier:_q sortOrdering:_so];
 }
 
-- (NSArray *)fetchUIDs:(NSArray *)_uids parts:(NSArray *)_parts {
+- (NSArray *) fetchUIDs: (NSArray *) _uids
+                 parts: (NSArray *) _parts
+{
   return [[self imap4Connection] fetchUIDs:_uids inURL:[self imap4URL]
                                 parts:_parts];
 }
 
-- (NSException *)postData:(NSData *)_data flags:(id)_flags {
+- (NSException *) postData: (NSData *) _data
+                    flags: (id) _flags
+{
   return [[self imap4Connection] postData:_data flags:_flags
                                 toFolderURL:[self imap4URL]];
 }
 
-- (NSException *)expunge {
-  return [[self imap4Connection] expungeAtURL:[self imap4URL]];
+- (NSException *) expunge
+{
+  return [[self imap4Connection] expungeAtURL: [self imap4URL]];
 }
 
 /* flags */
 
-- (NSException *)addFlagsToAllMessages:(id)_f {
+- (NSException *) addFlagsToAllMessages: (id) _f
+{
   return [[self imap4Connection] addFlags:_f 
-                                toAllMessagesInURL:[self imap4URL]];
+                                toAllMessagesInURL: [self imap4URL]];
 }
 
 /* name lookup */
 
-- (BOOL)isMessageKey:(NSString *)_key inContext:(id)_ctx {
+- (BOOL) isMessageKey: (NSString *) _key
+           inContext: (id) _ctx
+{
   /*
     Every key starting with a digit is consider an IMAP4 message key. This is
     not entirely correct since folders could also start with a number.
@@ -185,7 +217,9 @@ static BOOL useAltNamespace = NO;
   return NO;
 }
 
-- (id)lookupImap4Folder:(NSString *)_key inContext:(id)_ctx {
+- (id) lookupImap4Folder: (NSString *) _key
+              inContext: (id) _ctx
+{
   // TODO: we might want to check for existence prior controller creation
   NSURL *sf;
 
@@ -210,13 +244,18 @@ static BOOL useAltNamespace = NO;
                                  inContainer:self] autorelease];
 }
 
-- (id)lookupImap4Message:(NSString *)_key inContext:(id)_ctx {
+- (id) lookupImap4Message: (NSString *) _key
+               inContext: (id) _ctx
+{
   // TODO: we might want to check for existence prior controller creation
   return [[[SOGoMailObject alloc] initWithName:_key 
                                  inContainer:self] autorelease];
 }
 
-- (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_acquire {
+- (id) lookupName: (NSString *) _key
+       inContext: (id)_ctx
+         acquire: (BOOL) _acquire
+{
   id obj;
   
   if ([self isMessageKey:_key inContext:_ctx]) {
@@ -244,21 +283,26 @@ static BOOL useAltNamespace = NO;
 
 /* WebDAV */
 
-- (BOOL)davIsCollection {
+- (BOOL) davIsCollection
+{
   return YES;
 }
 
-- (NSException *)davCreateCollection:(NSString *)_name inContext:(id)_ctx {
+- (NSException *) davCreateCollection: (NSString *) _name
+                           inContext: (id) _ctx
+{
   return [[self imap4Connection] createMailbox:_name atURL:[self imap4URL]];
 }
 
-- (NSException *)delete {
+- (NSException *) delete
+{
   /* Note: overrides SOGoObject -delete */
   return [[self imap4Connection] deleteMailboxAtURL:[self imap4URL]];
 }
 
-- (NSException *)davMoveToTargetObject:(id)_target newName:(NSString *)_name
-  inContext:(id)_ctx
+- (NSException *) davMoveToTargetObject: (id) _target
+                               newName: (NSString *) _name
+                             inContext: (id)_ctx
 {
   NSURL *destImapURL;
   
@@ -286,8 +330,10 @@ static BOOL useAltNamespace = NO;
   return [[self imap4Connection] moveMailboxAtURL:[self imap4URL] 
                                 toURL:destImapURL];
 }
-- (NSException *)davCopyToTargetObject:(id)_target newName:(NSString *)_name
-  inContext:(id)_ctx
+
+- (NSException *) davCopyToTargetObject: (id) _target
+                               newName: (NSString *) _name
+                             inContext: (id) _ctx
 {
   [self logWithFormat:@"TODO: should copy collection as '%@' to: %@",
        _name, _target];
@@ -296,8 +342,13 @@ static BOOL useAltNamespace = NO;
 }
 
 /* folder type */
+- (NSString *) folderType
+{
+  return @"Mail";
+}
 
-- (NSString *)outlookFolderClass {
+- (NSString *) outlookFolderClass
+{
   // TODO: detect Trash/Sent/Drafts folders
   SOGoMailAccount *account;
   NSString *n;
@@ -420,24 +471,61 @@ static BOOL useAltNamespace = NO;
 
 - (NSArray *) aclUsers
 {
+  NSArray *users;
   NSDictionary *imapAcls;
 
-  imapAcls = [imap4 aclForMailboxAtURL: [self imap4URL]];
+  imapAcls = [[self imap4Connection] aclForMailboxAtURL: [self imap4URL]];
+  if ([imapAcls isKindOfClass: [NSDictionary class]])
+    users = [imapAcls allKeys];
+  else
+    users = nil;
 
-  return [imapAcls allKeys];
+  return users;
+}
+
+- (NSMutableArray *) _sharesACLs
+{
+  NSMutableArray *acls;
+  SOGoMailAccount *mailAccount;
+  NSString *path;
+  NSArray *names;
+  unsigned int count;
+
+  acls = [NSMutableArray array];
+
+  mailAccount = [self mailAccountFolder];
+  path = [[self imap4Connection] imap4FolderNameForURL: [self imap4URL]];
+  names = [path componentsSeparatedByString: @"/"];
+  count = [names count];
+
+  if ([path hasPrefix: [mailAccount sharedFolderName]])
+    [acls addObject: SOGoRole_ObjectViewer];
+  else if ([path hasPrefix: [mailAccount otherUsersFolderName]])
+    [acls addObject: SOGoRole_ObjectViewer];
+  else
+    [acls addObject: SoRole_Owner];
+
+  return acls;
 }
 
 - (NSArray *) aclsForUser: (NSString *) uid
 {
   NSDictionary *imapAcls;
+  NSMutableArray *acls;
   NSString *userAcls;
 
-  imapAcls = [imap4 aclForMailboxAtURL: [self imap4URL]];
-  userAcls = [imapAcls objectForKey: uid];
-  if (!([userAcls length] || [uid isEqualToString: defaultUserID]))
-    userAcls = [imapAcls objectForKey: defaultUserID];
+  acls = [self _sharesACLs];
+  imapAcls = [[self imap4Connection] aclForMailboxAtURL: [self imap4URL]];
+  if ([imapAcls isKindOfClass: [NSDictionary class]])
+    {
+      userAcls = [imapAcls objectForKey: uid];
+      if (!([userAcls length] || [uid isEqualToString: defaultUserID]))
+       userAcls = [imapAcls objectForKey: defaultUserID];
+      if ([userAcls length])
+       [acls addObjectsFromArray: [self _imapAclsToSOGoAcls: userAcls]];
+    }
 
-  return [self _imapAclsToSOGoAcls: userAcls];
+  return acls;
 }
 
 - (void) removeAclsForUsers: (NSArray *) users
@@ -447,7 +535,7 @@ static BOOL useAltNamespace = NO;
   NSString *folderName;
   NGImap4Client *client;
 
-  folderName = [imap4 imap4FolderNameForURL: [self imap4URL]];
+  folderName = [[self imap4Connection] imap4FolderNameForURL: [self imap4URL]];
   client = [imap4 client];
 
   uids = [users objectEnumerator];
@@ -465,7 +553,7 @@ static BOOL useAltNamespace = NO;
   NSString *acls, *folderName;
 
   acls = [self _sogoAclsToImapAcls: roles];
-  folderName = [imap4 imap4FolderNameForURL: [self imap4URL]];
+  folderName = [[self imap4Connection] imap4FolderNameForURL: [self imap4URL]];
   [[imap4 client] setACL: folderName rights: acls uid: uid];
 }
 
@@ -474,9 +562,77 @@ static BOOL useAltNamespace = NO;
   return defaultUserID;
 }
 
-- (BOOL) hasSupportForDefaultRoles
+- (NSString *) ownerInContext: (WOContext *) localContext
 {
-  return YES;
+  SOGoMailAccount *mailAccount;
+  NSString *path, *owner;
+  NSArray *names;
+
+  mailAccount = [self mailAccountFolder];
+  path = [[self imap4Connection] imap4FolderNameForURL: [self imap4URL]];
+
+  if ([path hasPrefix: [mailAccount sharedFolderName]])
+    owner = @"anyone";
+  else if ([path hasPrefix: [mailAccount otherUsersFolderName]])
+    {
+      names = [path componentsSeparatedByString: @"/"];
+      if ([names count] > 1)
+       owner = [names objectAtIndex: 1];
+      else
+       owner = @"anyone";
+    }
+  else
+    owner = [super ownerInContext: localContext];
+
+  return owner;
+}
+
+- (NSString *) otherUsersPathToFolder
+{
+  NSString *userPath, *selfPath, *otherUsers, *sharedFolders;
+  SOGoMailAccount *account;
+
+  account = [self mailAccountFolder];
+  otherUsers = [account otherUsersFolderName];
+  sharedFolders = [account sharedFolderName];
+
+  selfPath = [[self imap4URL] path];
+  if ([selfPath hasPrefix: [NSString stringWithFormat: @"/%@", otherUsers]]
+      || [selfPath hasPrefix:
+                    [NSString stringWithFormat: @"/%@", sharedFolders]])
+    userPath = selfPath;
+  else
+    userPath = [NSString stringWithFormat: @"/%@/%@%@",
+                        [otherUsers stringByEscapingURL],
+                        [self ownerInContext: context],
+                        selfPath];
+
+  return userPath;
+}
+
+- (NSString *) httpURLForAdvisoryToUser: (NSString *) uid;
+{
+  SOGoUser *user;
+
+  user = [SOGoUser userWithLogin: uid roles: nil];
+
+  return [NSString stringWithFormat: @"%@/%@%@",
+                  [self soURLToBaseContainerForUser: uid],
+                  [user primaryIMAP4AccountString],
+                  [self otherUsersPathToFolder]];
+}
+
+- (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid;
+{
+  NSURL *selfURL, *userURL;
+
+  selfURL = [self imap4URL];
+  userURL = [[NSURL alloc] initWithScheme: [selfURL scheme]
+                          host: [selfURL host]
+                          path: [self otherUsersPathToFolder]];
+  [userURL autorelease];
+
+  return [userURL absoluteString];
 }
 
 @end /* SOGoMailFolder */
index a28051643c09640249802f221e6bb858a61e84d8..9e202f3e76c08ef236a2a15eb8eb17b83957a992 100644 (file)
     SOGoMailFolder = {
       superclass    = "SOGoMailBaseObject";
       defaultRoles = {
-        "View"          = ( "Owner", "AuthorizedSubscriber" );
-        "Access Contents Information" = ( "Owner", "AuthorizedSubscriber" );
+        "View" = ( "Owner", "ObjectViewer" );
+        "Access Contents Information" = ( "Owner", "ObjectReader" );
         "Add Documents, Images, and Files" = ( "Owner", "ObjectCreator" );
         "Delete Objects" = ( "Owner", "ObjectEraser" );
-        "WebDAV Access" = ( "Owner", "AuthorizedSubscriber" );
-        "ReadAcls" = ( "Owner", "AuthorizedSubscriber" );
-        "SaveAcls" = ( "Owner" );
+        "WebDAV Access" = ( "Owner", "ObjectViewer" );
+        "ReadAcls" = ( "Owner", "ObjectViewer" );
+        "SaveAcls" = ( "Owner", "MailAdministrator" );
       };
     };
     SOGoSharedInboxFolder = {
index 3ad28ac9f3b0054c27e9e91728dc3124359696c7..c5a1dcd05b10c18f75a99600cf856d22848540ff 100644 (file)
@@ -32,11 +32,14 @@ libSOGo_HEADER_FILES = \
        LDAPSource.h                    \
        SOGoPermissions.h               \
        SOGoLRUCache.h                  \
-       NSArray+Utilities.h             \
        NSObject+AptComparison.h        \
        WOContext+Agenor.h              \
        SOGoDAVRendererTypes.h          \
-       NSString+Utilities.h                    \
+       NSArray+Utilities.h             \
+       NSDictionary+URL.h              \
+       NSDictionary+Utilities.h        \
+       NSObject+Utilities.h            \
+       NSString+Utilities.h            \
        NSDictionary+URL.h              \
        NSCalendarDate+SOGo.h           \
        \
@@ -62,6 +65,8 @@ libSOGo_OBJC_FILES = \
        AgenorUserDefaults.m            \
        NSArray+Utilities.m             \
        NSDictionary+URL.m              \
+       NSDictionary+Utilities.m        \
+       NSObject+Utilities.m            \
        NSString+Utilities.m            \
        NSCalendarDate+SOGo.m           \
        \
index d7dd8faa3aabfaf5a373cb4731aa3e632a95318a..6a3c6510b8e0f53d74b50cad4bb9a048230151b5 100644 (file)
@@ -54,6 +54,7 @@
 
 - (NSString *) getCNForUID: (NSString *) uid;
 - (NSString *) getEmailForUID: (NSString *) uid;
+- (NSString *) getFullEmailForUID: (NSString *) uid;
 - (NSString *) getUIDForEmail: (NSString *) email;
 
 - (BOOL) checkLogin: (NSString *) login
index 6b0379d1e6da973ca9c03dea4ff79152e2414662..e79c1f294e36692cb9a377827538a1bcb360c5cd 100644 (file)
@@ -195,6 +195,17 @@ static NSString *defaultMailDomain = nil;
   return [contactInfos objectForKey: @"c_email"];
 }
 
+- (NSString *) getFullEmailForUID: (NSString *) uid
+{
+  NSDictionary *contactInfos;
+
+  contactInfos = [self contactInfosForUserWithUIDorEmail: uid];
+
+  return [NSString stringWithFormat: @"%@ <%@>",
+                  [contactInfos objectForKey: @"cn"],
+                  [contactInfos objectForKey: @"c_email"]];
+}
+
 - (NSString *) getUIDForEmail: (NSString *) email
 {
   NSDictionary *contactInfos;
index 2617538d34b13d2d4df28ede5fa0f77fc2caccbd..025b2bceae8fb9bd9b144f5f333215486a124927 100644 (file)
@@ -29,6 +29,8 @@
 
 @interface NSArray (SOGoArrayUtilities)
 
+- (NSString *) jsonRepresentation;
+
 - (NSArray *) stringsWithFormat: (NSString *) format;
 
 #ifdef GNUSTEP_BASE_LIBRARY
@@ -43,6 +45,9 @@
 
 - (void) addObjectUniquely: (id) object;
 
+- (void) addRange: (NSRange) newRange;
+- (BOOL) hasRangeIntersection: (NSRange) testRange;
+
 @end
 
 #endif /* NSARRAY_UTILITIES_H */
index 75dec348cb7dc260e313b13542e03c0a3eaa539d..66054efb8f62a86e66284bcf861809ec9c1d7b80 100644 (file)
                                  withObject: object2];
 }
 
+- (NSString *) jsonRepresentation
+{
+  id currentElement;
+  NSMutableArray *jsonElements;
+  NSEnumerator *elements;
+  NSString *representation;
+
+  jsonElements = [NSMutableArray new];
+
+  elements = [self objectEnumerator];
+  currentElement = [elements nextObject];
+  while (currentElement)
+    {
+      [jsonElements addObject: [currentElement jsonRepresentation]];
+      currentElement = [elements nextObject];
+    }
+  representation = [NSString stringWithFormat: @"[%@]",
+                            [jsonElements componentsJoinedByString: @", "]];
+  [jsonElements release];
+
+  return representation;
+}
+
 @end
 
 @implementation NSMutableArray (SOGoArrayUtilities)
     [self addObject: object];
 }
 
+- (void) addRange: (NSRange) newRange
+{
+  [self addObject: NSStringFromRange (newRange)];
+}
+
+- (BOOL) hasRangeIntersection: (NSRange) testRange
+{
+  NSEnumerator *ranges;
+  NSString *currentRangeString;
+  NSRange currentRange;
+  BOOL response;
+
+  response = NO;
+
+  ranges = [self objectEnumerator];
+  currentRangeString = [ranges nextObject];
+  while (!response && currentRangeString)
+    {
+      currentRange = NSRangeFromString (currentRangeString);
+      if (NSLocationInRange (testRange.location, currentRange)
+         || NSLocationInRange (NSMaxRange (testRange), currentRange))
+       response = YES;
+      else
+       currentRangeString = [ranges nextObject];
+    }
+
+  return response;
+}
+
 @end
 
diff --git a/SoObjects/SOGo/NSDictionary+Utilities.h b/SoObjects/SOGo/NSDictionary+Utilities.h
new file mode 100644 (file)
index 0000000..df40a34
--- /dev/null
@@ -0,0 +1,36 @@
+/* NSDictionary+Utilities.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef NSDICTIONARY_UTILITIES_H
+#define NSDICTIONARY_UTILITIES_H
+
+#import <Foundation/NSDictionary.h>
+
+@class NSString;
+
+@interface NSDictionary (SOGoDictionaryUtilities)
+
+- (NSString *) jsonRepresentation;
+
+@end
+
+#endif /* NSDICTIONARY_UTILITIES_H */
diff --git a/SoObjects/SOGo/NSDictionary+Utilities.m b/SoObjects/SOGo/NSDictionary+Utilities.m
new file mode 100644 (file)
index 0000000..5b21ce2
--- /dev/null
@@ -0,0 +1,55 @@
+/* NSDictionary+Utilities.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSString.h>
+
+#import "NSObject+Utilities.h"
+#import "NSDictionary+Utilities.h"
+
+@implementation NSDictionary (SOGoDictionaryUtilities)
+
+- (NSString *) jsonRepresentation
+{
+  NSMutableArray *values;
+  NSString *representation, *currentKey, *currentValue, *currentPair;
+  NSEnumerator *keys;
+
+  values = [NSMutableArray new];
+  keys = [[self allKeys] objectEnumerator];
+  currentKey = [keys nextObject];
+  while (currentKey)
+    {
+      currentValue = [[self objectForKey: currentKey] jsonRepresentation];
+      currentPair = [NSString stringWithFormat: @"%@: %@",
+                             [currentKey jsonRepresentation], currentValue];
+      [values addObject: currentPair];
+      currentKey = [keys nextObject];
+    }
+  representation = [NSString stringWithFormat: @"{%@}",
+                            [values componentsJoinedByString: @", "]];
+  [values release];
+
+  return representation;
+}
+
+@end
diff --git a/SoObjects/SOGo/NSObject+Utilities.h b/SoObjects/SOGo/NSObject+Utilities.h
new file mode 100644 (file)
index 0000000..11610aa
--- /dev/null
@@ -0,0 +1,36 @@
+/* NSObject+Utilities.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef NSOBJECT_UTILITIES_H
+#define NSOBJECT_UTILITIES_H
+
+#import <Foundation/NSObject.h>
+
+@class NSString;
+
+@interface NSObject (SOGoObjectUtilities)
+
+- (NSString *) jsonRepresentation;
+
+@end
+
+#endif /* NSOBJECT+UTILITIES_H */
diff --git a/SoObjects/SOGo/NSObject+Utilities.m b/SoObjects/SOGo/NSObject+Utilities.m
new file mode 100644 (file)
index 0000000..d013f09
--- /dev/null
@@ -0,0 +1,36 @@
+/* NSObject+Utilities.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <Foundation/NSString.h>
+
+#import "NSObject+Utilities.h"
+
+@implementation NSObject (SOGoObjectUtilities)
+
+- (NSString *) jsonRepresentation
+{
+  [self subclassResponsibility: _cmd];
+
+  return nil;
+}
+
+@end
index 01728e9e36077d6ec19a71fb9e19ce3cbebea5ad..29679f53218ebb224ce3534c56ebb0605d9fa506 100644 (file)
@@ -40,6 +40,8 @@
 
 - (NSString *) stringByDetectingURLs;
 
+- (NSString *) jsonRepresentation;
+
 #ifndef GNUSTEP_BASE_LIBRARY
 - (BOOL) boolValue;
 #endif
index 987ad47c79ab44a41286dbcb7bafce119630d271..b689ef8509dcbd28df77cae1982bcfd2fa9079fa 100644 (file)
 #import <Foundation/NSCharacterSet.h>
 #import <Foundation/NSEnumerator.h>
 
-#import "NSString+Utilities.h"
+#import "NSArray+Utilities.h"
 #import "NSDictionary+URL.h"
 
+#import "NSString+Utilities.h"
+
 static NSMutableCharacterSet *urlNonEndingChars = nil;
 static NSMutableCharacterSet *urlAfterEndingChars = nil;
 
@@ -145,6 +147,7 @@ static NSMutableCharacterSet *urlAfterEndingChars = nil;
 - (void) _handleURLs: (NSMutableString *) selfCopy
         textToMatch: (NSString *) match
              prefix: (NSString *) prefix
+           inRanges: (NSMutableArray *) ranges
 {
   NSRange httpRange, currentURL, rest;
   NSString *urlText, *newUrlText;
@@ -154,18 +157,24 @@ static NSMutableCharacterSet *urlAfterEndingChars = nil;
   httpRange = [selfCopy rangeOfString: match];
   while (httpRange.location != NSNotFound)
     {
-      currentURL = [selfCopy _rangeOfURLInRange: httpRange];
-      urlText = [selfCopy substringFromRange: currentURL];
-      if ([urlText length] > matchLength)
+      if ([ranges hasRangeIntersection: httpRange])
+       rest.location = NSMaxRange (httpRange);
+      else
        {
-         newUrlText = [NSString stringWithFormat: @"<a href=\"%@%@\">%@</a>",
-                                prefix, urlText, urlText];
-         [selfCopy replaceCharactersInRange: currentURL
-                   withString: newUrlText];
-         rest.location = currentURL.location + [newUrlText length];
+         currentURL = [selfCopy _rangeOfURLInRange: httpRange];
+         urlText = [selfCopy substringFromRange: currentURL];
+         if ([urlText length] > matchLength)
+           {
+             newUrlText = [NSString stringWithFormat: @"<a href=\"%@%@\">%@</a>",
+                                    prefix, urlText, urlText];
+             [selfCopy replaceCharactersInRange: currentURL
+                       withString: newUrlText];
+             currentURL
+               = NSMakeRange (currentURL.location, [newUrlText length]);
+             [ranges addRange: currentURL];
+           }
+         rest.location = NSMaxRange (currentURL);
        }
-      else
-       rest.location = currentURL.location + currentURL.length;
       length = [selfCopy length];
       rest.length = length - rest.location;
       httpRange = [selfCopy rangeOfString: match
@@ -176,14 +185,40 @@ static NSMutableCharacterSet *urlAfterEndingChars = nil;
 - (NSString *) stringByDetectingURLs
 {
   NSMutableString *selfCopy;
+  NSMutableArray *ranges;
 
+  ranges = [NSMutableArray new];
   selfCopy = [NSMutableString stringWithString: self];
-  [self _handleURLs: selfCopy textToMatch: @"://" prefix: @""];
-  [self _handleURLs: selfCopy textToMatch: @"@" prefix: @"mailto:"];
+  [self _handleURLs: selfCopy
+       textToMatch: @"://"
+       prefix: @""
+       inRanges: ranges];
+  [self _handleURLs: selfCopy
+       textToMatch: @"@"
+       prefix: @"mailto:"
+       inRanges: ranges];
+  [ranges release];
 
   return selfCopy;
 }
 
+- (NSString *) jsonRepresentation
+{
+  NSMutableString *representation;
+
+  representation = [NSMutableString stringWithString: self];
+  [representation replaceString: @"\\" withString: @"\\\\"];
+  [representation replaceString: @"\"" withString: @"\\\""];
+  [representation replaceString: @"/" withString: @"\\/"];
+  [representation replaceString: @"\b" withString: @"\\b"];
+  [representation replaceString: @"\f" withString: @"\\f"];
+  [representation replaceString: @"\n" withString: @"\\n"];
+  [representation replaceString: @"\r" withString: @"\\r"];
+  [representation replaceString: @"\t" withString: @"\\t"];
+
+  return [NSString stringWithFormat: @"\"%@\"", representation];
+}
+
 #if LIB_FOUNDATION_LIBRARY
 - (BOOL) boolValue
 {
index e2b11a44ef3ee7cfdfec9a5b646bbb6557123559..d5153f325f52db42da0fe55e37d52b5c5b42cc8c 100644 (file)
   return @"<default>";
 }
 
-- (BOOL) hasSupportForDefaultRoles
-{
-  return YES;
-}
-
 /* message type */
 
 - (NSString *) outlookMessageClass
index 2e3b7469f22580a8a72f7bea2d15cba166ff57cc..cf5b25c2e3a2546df31f61595d003816e4ab2aa2 100644 (file)
@@ -452,9 +452,14 @@ static NSString *defaultUserID = @"<default>";
   return defaultUserID;
 }
 
-- (BOOL) hasSupportForDefaultRoles
+- (NSString *) httpURLForAdvisoryToUser: (NSString *) uid
 {
-  return YES;
+  return [[self soURL] absoluteString];
+}
+
+- (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid
+{
+  return [[self davURL] absoluteString];
 }
 
 /* WebDAV */
index b265699efa6ea700cc9de240da08eeedb45e19d5..8d83c8d798836c05ae6b2aa18bd1a1bcb9c0b50a 100644 (file)
@@ -41,6 +41,7 @@
 @class NSMutableString;
 @class NSException;
 @class NSTimeZone;
+@class NSURL;
 
 @class WOContext;
 @class GCSFolderManager;
 - (NSString *) nameInContainer;
 - (id) container;
 
+- (NSURL *) davURL;
+- (NSURL *) soURL;
+- (NSURL *) soURLToBaseContainerForUser: (NSString *) uid;
+- (NSURL *) soURLToBaseContainerForCurrentUser;
+
 /* ownership */
 
 - (void) setOwner: (NSString *) newOwner;
           forUser: (NSString *) uid;
 - (void) removeAclsForUsers: (NSArray *) users;
 - (NSString *) defaultUserID;
-- (BOOL) hasSupportForDefaultRoles;
+
+- (void) sendACLAdditionAdvisoryToUser: (NSString *) uid;
+- (void) sendACLRemovalAdvisoryToUser: (NSString *) uid;
+
+- (NSString *) httpURLForAdvisoryToUser: (NSString *) uid;
+- (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid;
 
 /* description */
 
index 5ca5809f75ea623ce7b2789bb784495f79c1db20..cd60e58578c4ee4e46a6a9e4f66e5610bbb13827 100644 (file)
        Please use gnustep-base instead.
 #endif
 
-#import <NGObjWeb/WEClientCapabilities.h>
+#import <Foundation/NSClassDescription.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSUserDefaults.h>
+#import <Foundation/NSURL.h>
+#import <Foundation/NSValue.h>
+
+#import <NGObjWeb/SoClassSecurityInfo.h>
 #import <NGObjWeb/SoObject+SoDAV.h>
+#import <NGObjWeb/WEClientCapabilities.h>
+#import <NGObjWeb/WOApplication.h>
 #import <NGObjWeb/WOContext.h>
 #import <NGObjWeb/WOResponse.h>
 #import <NGObjWeb/WORequest.h>
-#import <NGObjWeb/WOApplication.h>
+#import <NGObjWeb/WORequest+So.h>
+#import <NGObjWeb/NSException+HTTP.h>
+#import <NGExtensions/NSObject+Logs.h>
 #import <NGCards/NSDictionary+NGCards.h>
-#import <GDLContentStore/GCSFolder.h>
-
-#import "common.h"
-
-#import "NSArray+Utilities.h"
-#import "NSString+Utilities.h"
+#import <UI/SOGoUI/SOGoACLAdvisory.h>
 
 #import "SOGoPermissions.h"
 #import "SOGoUser.h"
@@ -45,6 +50,9 @@
 
 #import "SOGoDAVRendererTypes.h"
 
+#import "NSArray+Utilities.h"
+#import "NSString+Utilities.h"
+
 #import "SOGoObject.h"
 
 @interface SOGoObject(Content)
@@ -737,9 +745,118 @@ static BOOL kontactGroupDAV = YES;
   return nil;
 }
 
-- (BOOL) hasSupportForDefaultRoles
+- (void) sendACLAdvisoryTemplate: (NSString *) template
+                         toUser: (NSString *) uid
 {
-  return NO;
+  NSString *language, *pageName;
+  SOGoUser *user;
+  SOGoACLAdvisory *page;
+  WOApplication *app;
+
+  user = [SOGoUser userWithLogin: uid roles: nil];
+  language = [user language];
+  pageName = [NSString stringWithFormat: @"SOGoACL%@%@Advisory",
+                      language, template];
+
+  app = [WOApplication application];
+  page = [app pageWithName: pageName inContext: context];
+  [page setACLObject: self];
+  [page setRecipientUID: uid];
+  [page send];
+}
+
+- (void) sendACLAdditionAdvisoryToUser: (NSString *) uid
+{
+  return [self sendACLAdvisoryTemplate: @"Addition"
+              toUser: uid];
+}
+
+- (void) sendACLRemovalAdvisoryToUser: (NSString *) uid
+{
+  return [self sendACLAdvisoryTemplate: @"Removal"
+              toUser: uid];
+}
+
+- (NSURL *) _urlPreferringParticle: (NSString *) expected
+                      overThisOne: (NSString *) possible
+{
+  NSURL *serverURL, *davURL;
+  NSMutableArray *path;
+  NSString *baseURL, *urlMethod;
+
+  serverURL = [context serverURL];
+  baseURL = [self baseURLInContext: context];
+  path = [NSMutableArray arrayWithArray: [baseURL componentsSeparatedByString:
+                                                   @"/"]];
+  urlMethod = [path objectAtIndex: 2];
+  if (![urlMethod isEqualToString: expected])
+    {
+      if ([urlMethod isEqualToString: possible])
+       [path replaceObjectAtIndex: 2 withObject: expected];
+      else
+       [path insertObject: expected atIndex: 2];
+    }
+
+  davURL = [[NSURL alloc] initWithScheme: [serverURL scheme]
+                         host: [serverURL host]
+                         path: [path componentsJoinedByString: @"/"]];
+  [davURL autorelease];
+
+  return davURL;
+}
+
+- (NSURL *) davURL
+{
+  return [self _urlPreferringParticle: @"dav" overThisOne: @"so"];
+}
+
+- (NSURL *) soURL
+{
+  return [self _urlPreferringParticle: @"so" overThisOne: @"dav"];
+}
+
+- (NSURL *) soURLToBaseContainerForUser: (NSString *) uid
+{
+  NSURL *soURL, *baseSoURL;
+  NSArray *basePath;
+  NSMutableArray *newPath;
+
+  soURL = [self soURL];
+  basePath = [[soURL path] componentsSeparatedByString: @"/"];
+  newPath
+    = [NSMutableArray arrayWithArray:
+                       [basePath subarrayWithRange: NSMakeRange (0, 5)]];
+  [newPath replaceObjectAtIndex: 3 withObject: uid];
+
+  baseSoURL = [[NSURL alloc] initWithScheme: [soURL scheme]
+                            host: [soURL host]
+                            path: [newPath componentsJoinedByString: @"/"]];
+  [baseSoURL autorelease];
+
+  return baseSoURL;
+}
+
+- (NSURL *) soURLToBaseContainerForCurrentUser
+{
+  NSString *currentLogin;
+
+  currentLogin = [[context activeUser] login];
+
+  return [self soURLToBaseContainerForUser: currentLogin];
+}
+
+- (NSString *) httpURLForAdvisoryToUser: (NSString *) uid
+{
+  [self subclassResponsibility: _cmd];
+
+  return nil;
+}
+
+- (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid
+{
+  [self subclassResponsibility: _cmd];
+
+  return nil;
 }
 
 /* description */
index 6b52688a152c0bb9b951ab4e51acba9aa0bd3ab9..c41acfc91fb06cec1578005bf83ef43c6318b611 100644 (file)
@@ -45,6 +45,7 @@
 @interface SOGoUser : SoUser
 {
   NSString *cn;
+  NSString *language;
   NSArray *allEmails;
   NSUserDefaults *userDefaults;
   NSUserDefaults *userSettings;
@@ -56,6 +57,8 @@
 
 /* properties */
 
+- (NSString *) fullEmail;
+
 - (NSString *) primaryEmail;
 - (NSString *) systemEmail;
 - (NSArray *) allEmails;
@@ -80,6 +83,7 @@
 - (NSUserDefaults *) userDefaults;
 - (NSUserDefaults *) userSettings;
 
+- (NSString *) language;
 - (NSTimeZone *) timeZone;
 - (NSTimeZone *) serverTimeZone;
 
index f84d3065597b744aa3473453120196f9c62874c0..e345602a72990c458be2ac37ad2c52f231eb8dbb 100644 (file)
@@ -35,6 +35,7 @@
 
 static NSTimeZone *serverTimeZone = nil;
 static NSString *fallbackIMAP4Server = nil;
+static NSString *defaultLanguage = nil;
 static NSURL *AgenorProfileURL = nil;
 
 @interface NSObject (SOGoRoles)
@@ -66,7 +67,14 @@ static NSURL *AgenorProfileURL = nil;
       AgenorProfileURL = [[NSURL alloc] initWithString: profileURL];
     }
   if (!fallbackIMAP4Server)
-    ASSIGN (fallbackIMAP4Server, [ud stringForKey: @"SOGoFallbackIMAP4Server"]);
+    ASSIGN (fallbackIMAP4Server,
+           [ud stringForKey: @"SOGoFallbackIMAP4Server"]);
+  if (!defaultLanguage)
+    {
+      ASSIGN (defaultLanguage, [ud stringForKey: @"SOGoDefaultLanguage"]);
+      if (!defaultLanguage)
+       ASSIGN (defaultLanguage, @"English");
+    }
 }
 
 + (SOGoUser *) userWithLogin: (NSString *) newLogin
@@ -87,6 +95,7 @@ static NSURL *AgenorProfileURL = nil;
       userDefaults = nil;
       userSettings = nil;
       allEmails = nil;
+      language = nil;
     }
 
   return self;
@@ -116,6 +125,8 @@ static NSURL *AgenorProfileURL = nil;
 {
   [userDefaults release];
   [userSettings release];
+  [allEmails release];
+  [language release];
   [super dealloc];
 }
 
@@ -144,6 +155,11 @@ static NSURL *AgenorProfileURL = nil;
 
 /* properties */
 
+- (NSString *) fullEmail
+{
+  return [[LDAPUserManager sharedUserManager] getFullEmailForUID: login];
+}
+
 - (NSString *) primaryEmail
 {
   if (!allEmails)
@@ -249,6 +265,19 @@ static NSURL *AgenorProfileURL = nil;
   return userSettings;
 }
 
+- (NSString *) language
+{
+  if (!language)
+    {
+      language = [[self userDefaults] stringForKey: @"Language"];
+      if (!language)
+       language = defaultLanguage;
+      [language retain];
+    }
+
+  return language;
+}
+
 - (NSTimeZone *) timeZone
 {
   NSString *timeZoneName;
index 88126ad384b6387c599cea9d6ffe475d51dafe74..b74a20a30286bba30e6101f85340f0ebbcc1fd9d 100644 (file)
@@ -43,6 +43,7 @@
   NSString *baseFolder;
   NSMutableString *subscriptionPointer;
   NSMutableDictionary *moduleSettings;
+  BOOL isMailInvitation;
 }
 
 - (WOResponse *) subscribeAction;
index fdd9f80172d9efd9ba9a489ebafea798e66ae2a6..94edaea4ad989496236b3e546ea43c5408ded4d1 100644 (file)
@@ -23,6 +23,7 @@
 #import <Foundation/NSDictionary.h>
 #import <Foundation/NSString.h>
 #import <Foundation/NSUserDefaults.h>
+#import <Foundation/NSURL.h>
 #import <Foundation/NSValue.h>
 
 #import <NGObjWeb/WOContext.h>
@@ -45,7 +46,7 @@
 
 - (void) _setupContext
 {
-  NSString *clientClass;
+  NSString *clientClass, *mailInvitationParam;
   SOGoUser *activeUser;
 
   activeUser = [context activeUser];
   if ([baseFolder isEqualToString: @"Contacts"])
     [subscriptionPointer appendFormat: @"/%@",
                         [clientObject nameInContainer]];
+
+  mailInvitationParam
+    = [[context request] formValueForKey: @"mail-invitation"];
+  isMailInvitation = [mailInvitationParam boolValue];
 }
 
 - (WOResponse *) _realActionWithFolderName: (NSDictionary *) folderDict
 {
   WOResponse *response;
   NSMutableDictionary *folderSubscription;
+  NSString *mailInvitationURL;
 
   response = [context response];
   if ([owner isEqualToString: login])
        [folderSubscription removeObjectForKey: subscriptionPointer];
 
       [ud synchronize];
-      [response setStatus: 204];
+
+      if (isMailInvitation)
+       {
+         mailInvitationURL
+           = [[clientObject soURLToBaseContainerForCurrentUser]
+               absoluteString];
+         [response setStatus: 302];
+         [response setHeader: mailInvitationURL
+                   forKey: @"location"];
+       }
+      else
+       [response setStatus: 204];
     }
 
   return response;
index f3cf99306cf1f94fad58e8c34bc3286ef56c8577..fd9c3d3cb3346039bf62db487254ffcdf47ab5dc 100644 (file)
@@ -53,6 +53,7 @@
          clientObject = [self clientObject];
          [clientObject setRoles: [clientObject aclsForUser: uid]
                        forUser: uid];
+         [clientObject sendACLAdditionAdvisoryToUser: uid];
           code = 204;
         }
     }
@@ -70,6 +71,7 @@
   NSString *uid;
   unsigned int code;
   LDAPUserManager *um;
+  SOGoObject *co;
 
   code = 403;
   request = [context request];
@@ -79,8 +81,9 @@
       um = [LDAPUserManager sharedUserManager];
       if ([um contactInfosForUserWithUIDorEmail: uid])
        {
-         [[self clientObject] removeAclsForUsers:
-                                [NSArray arrayWithObject: uid]];
+         co = [self clientObject];
+         [co removeAclsForUsers: [NSArray arrayWithObject: uid]];
+         [co sendACLRemovalAdvisoryToUser: uid];
           code = 204;
         }
     }
index b7c739f71ba22a8e5656156b7432f2c61315e691..9fbaf7c286df523b0d8043aca92222fd2ec316b3 100644 (file)
 "error_missingsubject"      = "Missing Subject";
 "error_missingrecipients"   = "Missing Recipients";
 "error_validationfailed"    = "Validation failed";
+
+/* Folder operations */
+"Name :" = "Name :";
+"Enter the new name of your folder :"
+ = "Enter the new name of your folder :";
+"Do you really want to move this folder into the trash ?"
+ = "Do you really want to move this folder into the trash ?";
+"Operation failed" = "Operation failed";
index f313571c3da19ef62ccb997120e70e1495424f75..7f0153861084dba52d69b585b39e9533daa5c6c5 100644 (file)
 
 /* Tree */
 
-"SentFolderName"   = "Éléments envoyés";
+"SentFolderName"   = "Envoyés";
 "TrashFolderName"  = "Corbeille";
-"InboxFolderName"  = "Boite de réception";
+"InboxFolderName"  = "Courrier entrant";
 "DraftsFolderName" = "Brouillons";
 "SieveFolderName"  = "Filtres";
 "Folders"          = "Dossiers"; 
 
 /* MailMoveToPopUp */
 
-"MoveTo"        = "Déplacer vers";
+"MoveTo" = "Déplacer vers";
 
 /* Address Popup menu */
 "Add to Address Book..." = "Ajouter au carnet d'adresses";
 "As Junk" = "Comme indésirable";
 "As Not Junk" = "Comme acceptable";
 "Run Junk Mail Controls" = "Lancer le contrôle des indésirables";
+
+/* Folder operations */
+"Name :" = "Nom:";
+"Enter the new name of your folder :"
+ = "Entrez le nouveau nom de votre dossier:";
+"Do you really want to move this folder into the trash ?"
+ = "Voulez-vous vraiment déplacer le dossier sélectionné dans la corbeille?";
+"Operation failed" = "L'opération a Ã©choué.";
index b8e7a4b8be1f9d5535bfb7dc0ce48071e277aeef..7467c0262013c334ca1fb3370533fadaa686b406 100644 (file)
@@ -17,11 +17,6 @@ MailerUI_OBJC_FILES += \
        WOContext+UIxMailer.m           \
        \
        UIxMailMainFrame.m              \
-       UIxMailTree.m                   \
-       UIxMailTreeBlock.m              \
-       UIxMailTreeBlockJS.m            \
-       UIxMailFolderMenu.m             \
-       UIxMailSplashView.m             \
        \
        UIxMailListView.m               \
        UIxMailView.m                   \
@@ -29,6 +24,8 @@ MailerUI_OBJC_FILES += \
        UIxMailMoveToPopUp.m            \
        UIxMailFilterPanel.m            \
        \
+       UIxMailAccountActions.m         \
+       UIxMailFolderActions.m          \
        UIxMailEditor.m                 \
        UIxMailEditorAttach.m           \
        UIxMailEditorAction.m           \
index 28883f201d1fb922e6b888950611b77edc6adf4b..031a7dd787a3359ec427849a81b86742ebcb337f 100644 (file)
@@ -18,7 +18,6 @@
   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.
 */
-// $Id$
 
 #import <Foundation/NSObject.h>
 
@@ -28,7 +27,5 @@
 
 @end
 
-#include "common.h"
-
 @implementation MailerUIProduct
 @end /* MailerUIProduct */
diff --git a/UI/MailerUI/UIxMailAccountActions.h b/UI/MailerUI/UIxMailAccountActions.h
new file mode 100644 (file)
index 0000000..e6c84f7
--- /dev/null
@@ -0,0 +1,41 @@
+/* UIxMailAccountActions.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef UIXMAILACCOUNTACTIONS_H
+#define UIXMAILACCOUNTACTIONS_H
+
+#import <NGObjWeb/WODirectAction.h>
+
+@class WOResponse;
+
+@interface UIxMailAccountActions : WODirectAction
+{
+  NSString *draftFolderName;
+  NSString *sentFolderName;
+  NSString *trashFolderName;
+}
+
+- (WOResponse *) listMailboxesAction;
+
+@end
+
+#endif /* UIXMAILACCOUNTACTIONS_H */
diff --git a/UI/MailerUI/UIxMailAccountActions.m b/UI/MailerUI/UIxMailAccountActions.m
new file mode 100644 (file)
index 0000000..472db88
--- /dev/null
@@ -0,0 +1,108 @@
+/* UIxMailAccountActions.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSEnumerator.h>
+
+#import <NGObjWeb/WOContext.h>
+#import <NGObjWeb/WOResponse.h>
+#import <NGImap4/NGImap4Connection.h>
+#import <SoObjects/Mailer/SOGoMailAccount.h>
+#import <SoObjects/SOGo/NSObject+Utilities.h>
+
+#import "UIxMailAccountActions.h"
+
+@implementation UIxMailAccountActions
+
+- (NSString *) _folderType: (NSString *) baseName
+{
+  NSString *folderType;
+
+  if ([baseName isEqualToString: @"INBOX"])
+    folderType = @"inbox";
+  else if ([baseName isEqualToString: draftFolderName])
+    folderType = @"draft";
+  else if ([baseName isEqualToString: sentFolderName])
+    folderType = @"sent";
+  else if ([baseName isEqualToString: trashFolderName])
+    folderType = @"trash";
+  else
+    folderType = @"folder";
+
+  return folderType;
+}
+
+- (NSDictionary *) _lineForFolder: (NSString *) folder
+{
+  NSArray *parts;
+  NSMutableDictionary *folderData;
+  NSString *baseName;
+
+  folderData = [NSMutableDictionary dictionary];
+  parts = [folder componentsSeparatedByString: @"/"];
+  baseName = [parts lastObject];
+  [folderData setObject: folder forKey: @"path"];
+  [folderData setObject: [self _folderType: baseName]
+             forKey: @"type"];
+
+  return folderData;
+}
+
+- (NSArray *) _jsonFolders: (NSEnumerator *) rawFolders
+{
+  NSMutableArray *folders;
+  NSString *currentFolder;
+
+  folders = [NSMutableArray array];
+
+  currentFolder = [rawFolders nextObject];
+  while (currentFolder)
+    {
+      [folders addObject: [self _lineForFolder: currentFolder]];
+      currentFolder = [rawFolders nextObject];
+    }
+
+  return folders;
+}
+
+- (WOResponse *) listMailboxesAction
+{
+  SOGoMailAccount *co;
+  NSArray *rawFolders, *folders;
+  WOResponse *response;
+
+  co = [self clientObject];
+  draftFolderName = [co draftsFolderNameInContext: context];
+  sentFolderName = [co sentFolderNameInContext: context];
+  trashFolderName = [co trashFolderNameInContext: context];
+
+  rawFolders = [co allFolderPaths];
+  folders = [self _jsonFolders: [rawFolders objectEnumerator]];
+
+  response = [context response];
+  [response appendContentString: [folders jsonRepresentation]];
+
+  return response;
+}
+
+@end
diff --git a/UI/MailerUI/UIxMailFolderActions.h b/UI/MailerUI/UIxMailFolderActions.h
new file mode 100644 (file)
index 0000000..df473df
--- /dev/null
@@ -0,0 +1,40 @@
+/* UIxMailFolderActions.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef UIXMAILFOLDERACTIONS_H
+#define UIXMAILFOLDERACTIONS_H
+
+#import <NGObjWeb/WODirectAction.h>
+
+@class WOResponse;
+
+@interface UIxMailFolderActions : WODirectAction
+{
+}
+
+- (WOResponse *) createFolderAction;
+- (WOResponse *) renameFolderAction;
+- (WOResponse *) deleteFolderAction;
+
+@end
+
+#endif /* UIXMAILFOLDERACTIONS_H */
diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m
new file mode 100644 (file)
index 0000000..8f971f5
--- /dev/null
@@ -0,0 +1,252 @@
+/* UIxMailFolderActions.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSEnumerator.h>
+#import <Foundation/NSURL.h>
+
+#import <NGObjWeb/WOContext.h>
+#import <NGObjWeb/WOResponse.h>
+#import <NGObjWeb/WORequest.h>
+#import <NGImap4/NGImap4Connection.h>
+
+#import <SoObjects/Mailer/SOGoMailFolder.h>
+#import <SoObjects/Mailer/SOGoTrashFolder.h>
+#import <SoObjects/Mailer/SOGoMailAccount.h>
+
+#import "UIxMailFolderActions.h"
+
+@implementation UIxMailFolderActions
+
+- (WOResponse *) createFolderAction
+{
+  SOGoMailFolder *co;
+  WOResponse *response;
+  NGImap4Connection *connection;
+  NSException *error;
+  NSString *folderName;
+
+  co = [self clientObject];
+  response = [context response];
+
+  folderName = [[context request] formValueForKey: @"name"];
+  if ([folderName length] > 0)
+    {
+      connection = [co imap4Connection];
+      error = [connection createMailbox: folderName atURL: [co imap4URL]];
+      if (error)
+       {
+         [response setStatus: 403];
+         [response appendContentString: @"Unable to create folder."];
+       }
+      else
+       [response setStatus: 204];
+    }
+  else
+    {
+      [response setStatus: 403];
+      [response appendContentString: @"Missing 'name' parameter."];
+    }
+
+  return response;  
+}
+
+- (NSURL *) _urlOfFolder: (NSURL *) srcURL
+              renamedTo: (NSString *) folderName
+{
+  NSString *path;
+  NSURL *destURL;
+
+  path = [[srcURL path] stringByDeletingLastPathComponent];
+
+  destURL = [[NSURL alloc] initWithScheme: [srcURL scheme]
+                          host: [srcURL host]
+                          path: [NSString stringWithFormat: @"%@%@",
+                                          path, folderName]];
+  [destURL autorelease];
+
+  return destURL;
+}
+
+- (WOResponse *) renameFolderAction
+{
+  SOGoMailFolder *co;
+  WOResponse *response;
+  NGImap4Connection *connection;
+  NSException *error;
+  NSString *folderName;
+  NSURL *srcURL, *destURL;
+
+  co = [self clientObject];
+  response = [context response];
+
+  folderName = [[context request] formValueForKey: @"name"];
+  if ([folderName length] > 0)
+    {
+      srcURL = [co imap4URL];
+      destURL = [self _urlOfFolder: srcURL renamedTo: folderName];
+      connection = [co imap4Connection];
+      error = [connection moveMailboxAtURL: srcURL
+                         toURL: destURL];
+      if (error)
+       {
+         [response setStatus: 403];
+         [response appendContentString: @"Unable to rename folder."];
+       }
+      else
+       [response setStatus: 204];
+    }
+  else
+    {
+      [response setStatus: 403];
+      [response appendContentString: @"Missing 'name' parameter."];
+    }
+
+  return response;  
+}
+
+- (NSURL *) _trashedURLOfFolder: (NSURL *) srcURL
+                        withCO: (SOGoMailFolder *) co
+{
+  NSURL *destURL;
+  NSString *trashFolderName, *folderName;
+
+  folderName = [[srcURL path] lastPathComponent];
+  trashFolderName
+    = [[co mailAccountFolder] trashFolderNameInContext: context];
+
+  destURL = [[NSURL alloc] initWithScheme: [srcURL scheme]
+                          host: [srcURL host]
+                          path: [NSString stringWithFormat: @"/%@/%@",
+                                          trashFolderName, folderName]];
+  [destURL autorelease];
+
+  return destURL;
+}
+
+- (WOResponse *) deleteFolderAction
+{
+  SOGoMailFolder *co;
+  WOResponse *response;
+  NGImap4Connection *connection;
+  NSException *error;
+  NSURL *srcURL, *destURL;
+
+  co = [self clientObject];
+  response = [context response];
+  connection = [co imap4Connection];
+  srcURL = [co imap4URL];
+  destURL = [self _trashedURLOfFolder: srcURL
+                 withCO: co];
+  connection = [co imap4Connection];
+  error = [connection moveMailboxAtURL: srcURL
+                     toURL: destURL];
+  if (error)
+    {
+      [response setStatus: 403];
+      [response appendContentString: @"Unable to move folder."];
+    }
+  else
+    [response setStatus: 204];
+
+  return response;
+}
+
+- (WOResponse *) emptyTrashAction 
+{
+  NSException *error;
+  SOGoTrashFolder *co;
+  NSEnumerator *subfolders;
+  WOResponse *response;
+  NGImap4Connection *connection;
+  NSURL *currentURL;
+
+  co = [self clientObject];
+  response = [context response];
+
+  error = [co addFlagsToAllMessages: @"deleted"];
+  if (!error)
+    error = [co expunge];
+  if (!error)
+    {
+      [co flushMailCaches];
+      connection = [co imap4Connection];
+      subfolders = [[co subfoldersURL] objectEnumerator];
+      currentURL = [subfolders nextObject];
+      while (currentURL)
+       {
+         [connection deleteMailboxAtURL: currentURL];
+         currentURL = [subfolders nextObject];
+       }
+    }
+  if (error)
+    {
+      [response setStatus: 403];
+      [response appendContentString: @"Unable to empty the trash folder."];
+    }
+  else
+    [response setStatus: 204];
+
+  return response;
+}
+
+#warning here should be done what should be done: IMAP subscription
+- (WOResponse *) _subscriptionStubAction
+{
+  NSString *mailInvitationParam, *mailInvitationURL;
+  WOResponse *response;
+  SOGoMailFolder *clientObject;
+
+  response = [context response];
+  mailInvitationParam
+    = [[context request] formValueForKey: @"mail-invitation"];
+  if ([mailInvitationParam boolValue])
+    {
+      clientObject = [self clientObject];
+      mailInvitationURL
+       = [[clientObject soURLToBaseContainerForCurrentUser]
+           absoluteString];
+      [response setStatus: 302];
+      [response setHeader: mailInvitationURL
+               forKey: @"location"];
+    }
+  else
+    {
+      [response setStatus: 403];
+      [response appendContentString: @"How did you end up here?"];
+    }
+
+  return response;
+}
+
+- (WOResponse *) subscribeAction
+{
+  return [self _subscriptionStubAction];
+}
+
+- (WOResponse *) unsubscribeAction
+{
+  return [self _subscriptionStubAction];
+}
+
+@end
index 8411b0e1b11926a1fd4dbb7d13f9983628bfba43..de669d916bcd160f4a584503efd01268aa588888 100644 (file)
@@ -539,97 +539,6 @@ static int attachmentFlagSize = 8096;
   return [self redirectToLocation:@"view"];
 }
 
-- (id) emptyTrashAction 
-{
-  // TODO: we might want to flush the caches?
-  NSException *error;
-  id client;
-  
-  if ((client = [self clientObject]) == nil) {
-    error = [NSException exceptionWithHTTPStatus:404 /* Not Found */
-                        reason:@"did not find mail folder"];
-    return [self redirectToViewWithError:error];
-  }
-
-  if (![client isKindOfClass:NSClassFromString(@"SOGoTrashFolder")]) {
-    /* would be better to move the method to an own class, but well .. */
-    error = [NSException exceptionWithHTTPStatus:400 /* Bad Request */
-                        reason:@"method cannot be invoked on "
-                                @"the specified object"];
-    return [self redirectToViewWithError:error];
-  }
-  
-  /* mark all as deleted */
-
-  [self logWithFormat:@"TODO: must mark all as deleted for empty-trash"];
-  
-  error = [[self clientObject] addFlagsToAllMessages:@"deleted"];
-  if (error != nil)
-    // TODO: improve error
-    return [self redirectToViewWithError:error];
-  
-  /* expunge */
-  
-  if ((error = [[self clientObject] expunge]) != nil)
-    // TODO: improve error
-    return [self redirectToViewWithError:error];
-  
-  if ([client respondsToSelector:@selector(flushMailCaches)])
-    [client flushMailCaches];
-  return [self redirectToLocation:@"view"];
-}
-
-/* folder operations */
-
-- (id) createFolderAction 
-{
-  NSException *error;
-  NSString    *folderName;
-  id client;
-  
-  folderName = [[[self context] request] formValueForKey:@"name"];
-  if ([folderName length] == 0) {
-    error = [NSException exceptionWithHTTPStatus:400 /* Bad Request */
-                        reason:@"missing 'name' query parameter!"];
-    return [self redirectToViewWithError:error];
-  }
-  
-  if ((client = [self clientObject]) == nil) {
-    error = [NSException exceptionWithHTTPStatus:404 /* Not Found */
-                        reason:@"did not find mail folder"];
-    return [self redirectToViewWithError:error];
-  }
-  
-  if ((error = [[self clientObject] davCreateCollection:folderName
-                                   inContext:[self context]]) != nil) {
-    return [self redirectToViewWithError:error];
-  }
-  
-  return [self redirectToLocation:[folderName stringByAppendingString:@"/"]];
-}
-
-- (id) deleteFolderAction 
-{
-  NSException *error;
-  NSString *url;
-  id client;
-  
-  if ((client = [self clientObject]) == nil) {
-    error = [NSException exceptionWithHTTPStatus:404 /* Not Found */
-                        reason:@"did not find mail folder"];
-    return [self redirectToViewWithError:error];
-  }
-  
-  /* jump to parent folder afterwards */
-  url = [[client container] baseURLInContext:[self context]];
-  if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
-  
-  if ((error = [[self clientObject] delete]) != nil)
-    return [self redirectToViewWithError:error];
-  
-  return [self redirectToLocation:url];
-}
-
 @end
 
 /* UIxMailListView */
index a90cdf1b41c7b37b0b9eea49f78dece424b0e8d6..43997a083fc4bfbd19de0008bd5c42bc8bdfb257 100644 (file)
   02111-1307, USA.
 */
 
-#import <Mailer/SOGoMailObject.h>
-#import <SOGo/NSString+Utilities.h>
+#import <SoObjects/Mailer/SOGoMailObject.h>
+#import <SoObjects/Mailer/SOGoMailAccounts.h>
+#import <SoObjects/SOGo/NSString+Utilities.h>
+#import <SoObjects/SOGo/NSObject+Utilities.h>
 #import <SOGoUI/UIxComponent.h>
 #import "UIxMailMainFrame.h"
 
@@ -48,6 +50,14 @@ static NSString *treeRootClassName = nil;
 }
 
 /* accessors */
+- (NSString *) mailAccounts
+{
+  SOGoMailAccounts *co;
+
+  co = [self clientObject];
+
+  return [[co fetchAllIdentities] jsonRepresentation];
+}
 
 - (NSString *)treeRootClassName {
   return treeRootClassName;
@@ -186,25 +196,25 @@ static NSString *treeRootClassName = nil;
 }
 
 /* FIXME: migrated methods which might not work yet... */
-#warning check this
-- (NSString *) mailFolderName
-{
-  NSMutableArray *mailboxes;
-  SOGoMailObject *currentObject;
-
-  mailboxes = [NSMutableArray new];
-  [mailboxes autorelease];
-
-  currentObject = [self clientObject];
-  while (![currentObject isKindOfClass: [SOGoMailAccounts class]])
-    {
-      [mailboxes insertObject: [currentObject nameInContainer] atIndex: 0];
-      currentObject = [currentObject container];
-    }
-
-  return [NSString stringWithFormat: @"/%@",
-                   [mailboxes componentsJoinedByString: @"/"]];
-}
+// #warning check this
+// - (NSString *) mailFolderName
+// {
+//   NSMutableArray *mailboxes;
+//   SOGoMailObject *currentObject;
+
+//   mailboxes = [NSMutableArray new];
+//   [mailboxes autorelease];
+
+//   currentObject = [self clientObject];
+//   while (![currentObject isKindOfClass: [SOGoMailAccounts class]])
+//     {
+//       [mailboxes insertObject: [currentObject nameInContainer] atIndex: 0];
+//       currentObject = [currentObject container];
+//     }
+
+//   return [NSString stringWithFormat: @"/%@",
+//                    [mailboxes componentsJoinedByString: @"/"]];
+// }
 
 - (id) composeAction
 {
index ea820f5b6cfe8d3a71f802bee0c78f27db45cf51..242c43da8d99ece18884b1d2282afddc1a863e83 100644 (file)
 { /* -*-javascript-*- */
-  requires = ( MAIN, MainUI, CommonUI, Mailer ); /* , Sieve */
+requires = ( MAIN, MainUI, CommonUI, Mailer ); /* , Sieve */
 
-  publicResources = (
-    "uix.css",
-    "mailer.css",
-    "mailer.js",
-    "generic.js",
-    "searchfield.js",
-    "UIxAppointmentEditor.js",
-    "UIxContactEditor.js",
-    "UIxMailToSelection.js",
+   publicResources = (
+      "uix.css",
+      "mailer.css",
+      "mailer.js",
+      "generic.js",
+      "searchfield.js",
+      "UIxAppointmentEditor.js",
+      "UIxContactEditor.js",
+      "UIxMailToSelection.js",
 
-    "lori_32x32.png",
+      "lori_32x32.png",
 
-    "tbtv_account_17x17.gif",
-    "tbtv_drafts_17x17.gif",
-    "tbtv_inbox_17x17.gif",
-    "tbtv_junction2_17x17.gif",
-    "tbtv_junction_17x17.gif",
-    "tbtv_leaf_corner_17x17.gif",
-    "tbtv_line_17x17.gif",
-    "tbtv_minus_17x17.gif",
-    "tbtv_plus_17x17.gif",
-    "tbtv_corner_17x17.gif",
-    "tbtv_corner_minus_17x17.gif",
-    "tbtv_corner_plus_17x17.gif",
-    "tbtv_sent_17x17.gif",
-    "tbtv_trash_17x17.gif",
+      "tbtv_account_17x17.gif",
+      "tbtv_drafts_17x17.gif",
+      "tbtv_inbox_17x17.gif",
+      "tbtv_junction2_17x17.gif",
+      "tbtv_junction_17x17.gif",
+      "tbtv_leaf_corner_17x17.gif",
+      "tbtv_line_17x17.gif",
+      "tbtv_minus_17x17.gif",
+      "tbtv_plus_17x17.gif",
+      "tbtv_corner_17x17.gif",
+      "tbtv_corner_minus_17x17.gif",
+      "tbtv_corner_plus_17x17.gif",
+      "tbtv_sent_17x17.gif",
+      "tbtv_trash_17x17.gif",
 
-    "tbtb_addressbook.png",
-    "tbtb_compose.png",
-    "tbtb_delete.png",
-    "tbtb_deletedoc.png",
-    "tbtb_filetofolder.png",
-    "tbtb_forward.png",
-    "tbtb_getmail.png",
-    "tbtb_next.png",
-    "tbtb_previous.png",
-    "tbtb_print.png",
-    "tbtb_reply.png",
-    "tbtb_replyall.png",
-    "tbtb_search.png",
-    "tbtb_trash.png",
+      "tbtb_addressbook.png",
+      "tbtb_compose.png",
+      "tbtb_delete.png",
+      "tbtb_deletedoc.png",
+      "tbtb_filetofolder.png",
+      "tbtb_forward.png",
+      "tbtb_getmail.png",
+      "tbtb_next.png",
+      "tbtb_previous.png",
+      "tbtb_print.png",
+      "tbtb_reply.png",
+      "tbtb_replyall.png",
+      "tbtb_search.png",
+      "tbtb_trash.png",
 
-    "tbtb_compose_addressbook_30x30.png",
-    "tbtb_compose_attach_30x30.png",
-    "tbtb_compose_clip_30x30.png",
-    "tbtb_compose_cut_30x30.png",
-    "tbtb_compose_dup_30x30.png",
-    "tbtb_compose_file_30x30.png",
-    "tbtb_compose_lock_30x30.png",
-    "tbtb_compose_quote_30x30.png",
-    "tbtb_compose_send_30x30.png",
-    "tbtb_compose_spell_30x30.png",
+      "tbtb_compose_addressbook_30x30.png",
+      "tbtb_compose_attach_30x30.png",
+      "tbtb_compose_clip_30x30.png",
+      "tbtb_compose_cut_30x30.png",
+      "tbtb_compose_dup_30x30.png",
+      "tbtb_compose_file_30x30.png",
+      "tbtb_compose_lock_30x30.png",
+      "tbtb_compose_quote_30x30.png",
+      "tbtb_compose_send_30x30.png",
+      "tbtb_compose_spell_30x30.png",
 
-    "message-mail.png",
-    "message-mail-read.png",
+      "message-mail.png",
+      "message-mail-read.png",
 
-    "icon_mark_flagged.gif",
-    "icon_mark_read.gif",
-    "icon_mark_unflagged.gif",
-    "icon_mark_unread.gif",
-    "icon_read.gif",
-    "icon_unread.gif",
+      "icon_mark_flagged.gif",
+      "icon_mark_read.gif",
+      "icon_mark_unflagged.gif",
+      "icon_mark_unread.gif",
+      "icon_read.gif",
+      "icon_unread.gif",
 
-    "title_attachment_14x14.png",
-    "title_config.png",
-    "title_junk.png",
-    "title_read_14x14.png",
-    "title_thread.png",
-    "title_sortdown_12x12.png",
-    "title_sortup_12x12.png",
-  );
+      "title_attachment_14x14.png",
+      "title_config.png",
+      "title_junk.png",
+      "title_read_14x14.png",
+      "title_thread.png",
+      "title_sortdown_12x12.png",
+      "title_sortup_12x12.png",
+      );
 
-  factories = {
-  };
+factories = {
+};
 
-  categories = {
-    SOGoMailFolder = {
+categories = {
+   SOGoMailFolder = {
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value = "SOGoMailObject.toolbar";
-        };
+        toolbar = {
+           protectedBy = "View";
+           value = "SOGoMailObject.toolbar";
+        };
       };
       methods = {
-        view = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-        };
-        ajax = {
-          protectedBy = "View";
-          pageName    = "UIxMailAjaxRequest";
-        };
-        index = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-        };
-        GET = { /* hack to make it work as the default method */
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-        };
-        markMessageUnread = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-          actionName  = "markMessageUnread";
-        };
-        markMessageRead = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-          actionName  = "markMessageRead";
-        };
-        getMail = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-          actionName  = "getMail";
-        };
-        expunge = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-          actionName  = "expunge";
-        };
-        createFolder = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-          actionName  = "createFolder";
-        };
-        deleteFolder = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-          actionName  = "deleteFolder";
-        };
-        compose = {
-          protectedBy = "View";
-          actionClass = "UIxMailEditorAction";
-          actionName  = "compose";
-        };
-       userRights = {
-          protectedBy = "ReadAcls";
-          pageName    = "UIxMailUserRightsEditor";
-       };
-       saveUserRights = {
-          protectedBy = "SaveAcls";
-          pageName    = "UIxMailUserRightsEditor";
-          actionName  = "saveUserRights";
-       };
+        subscribe = {
+           protectedBy = "<public>";
+           actionClass = "UIxMailFolderActions";
+           actionName = "subscribe";
+        };
+        unsubscribe = {
+           protectedBy = "<public>";
+           actionClass = "UIxMailFolderActions";
+           actionName = "unsubscribe";
+        };
+        view = {
+           protectedBy = "View";
+           pageName    = "UIxMailListView";
+        };
+        ajax = {
+           protectedBy = "View";
+           pageName    = "UIxMailAjaxRequest";
+        };
+        index = {
+           protectedBy = "View";
+           pageName    = "UIxMailListView";
+        };
+        GET = { /* hack to make it work as the default method */
+                protectedBy = "View";
+                pageName    = "UIxMailListView";
+        };
+        markMessageUnread = {
+           protectedBy = "View";
+           pageName    = "UIxMailListView";
+           actionName  = "markMessageUnread";
+        };
+        markMessageRead = {
+           protectedBy = "View";
+           pageName    = "UIxMailListView";
+           actionName  = "markMessageRead";
+        };
+        getMail = {
+           protectedBy = "View";
+           pageName    = "UIxMailListView";
+           actionName  = "getMail";
+        };
+        expunge = {
+           protectedBy = "View";
+           pageName    = "UIxMailListView";
+           actionName  = "expunge";
+        };
+        createFolder = {
+           protectedBy = "View";
+           actionClass = "UIxMailFolderActions";
+           actionName = "createFolder";
+        };
+        renameFolder = {
+           protectedBy = "View";
+           actionClass = "UIxMailFolderActions";
+           actionName = "renameFolder";
+        };
+        deleteFolder = {
+           protectedBy = "View";
+           actionClass = "UIxMailFolderActions";
+           actionName = "deleteFolder";
+        };
+        compose = {
+           protectedBy = "View";
+           actionClass = "UIxMailEditorAction";
+           actionName  = "compose";
+        };
+        userRights = {
+           protectedBy = "ReadAcls";
+           pageName    = "UIxMailUserRightsEditor";
+        };
+        saveUserRights = {
+           protectedBy = "SaveAcls";
+           pageName    = "UIxMailUserRightsEditor";
+           actionName  = "saveUserRights";
+        };
       };
-    };
+   };
 
-    SOGoTrashFolder = {
+   SOGoTrashFolder = {
       /* just a new toolbar, other things come from SOGoMailFolder */
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value = "SOGoMailObject.toolbar";
-        };
+        toolbar = {
+           protectedBy = "View";
+           value = "SOGoMailObject.toolbar";
+        };
       };
       methods = {
-        emptyTrash = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-          actionName  = "emptyTrash";
-        };
+        emptyTrash = {
+           protectedBy = "View";
+           actionClass = "UIxMailFolderActions";
+           actionName = "emptyTrash";
+        };
       };
-    };
+   };
 
-    SOGoMailObject = {
+   SOGoMailObject = {
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value = "SOGoMailObject.toolbar";
-        };
+        toolbar = {
+           protectedBy = "View";
+           value = "SOGoMailObject.toolbar";
+        };
       };
       methods = {
-        view = {
-          protectedBy = "View";
-          pageName    = "UIxMailView";
-        };
-        popupview = {
-          protectedBy = "View";
-          pageName    = "UIxMailPopupView";
-        };
-        move = {
-          protectedBy = "View";
-          pageName    = "UIxMailView";
-          actionName  = "move";
-        };
-        delete = {
-          protectedBy = "View";
-          pageName    = "UIxMailView";
-          actionName  = "delete";
-        };
-        trash = {
-          protectedBy = "View";
-          pageName    = "UIxMailView";
-          actionName  = "trash";
-        };
-        junk = {
-          protectedBy = "View";
-          pageName    = "UIxMailView";
-          actionName  = "junk";
-        };
-        edit = {
-          protectedBy = "View";
-          pageName    = "UIxMailEditor";
-        };
-        compose = {
-          protectedBy = "View";
-          actionClass = "UIxMailEditorAction";
-          actionName  = "compose";
-        };
-        reply = {
-          protectedBy = "View";
-          actionClass = "UIxMailReplyAction";
-          actionName  = "reply";
-        };
-        replyall = {
-          protectedBy = "View";
-          actionClass = "UIxMailReplyAction";
-          actionName  = "replyall";
-        };
-        forward = {
-          protectedBy = "View";
-          actionClass = "UIxMailForwardAction";
-          actionName  = "forward";
-        };
+        view = {
+           protectedBy = "View";
+           pageName    = "UIxMailView";
+        };
+        popupview = {
+           protectedBy = "View";
+           pageName    = "UIxMailPopupView";
+        };
+        move = {
+           protectedBy = "View";
+           pageName    = "UIxMailView";
+           actionName  = "move";
+        };
+        delete = {
+           protectedBy = "View";
+           pageName    = "UIxMailView";
+           actionName  = "delete";
+        };
+        trash = {
+           protectedBy = "View";
+           pageName    = "UIxMailView";
+           actionName  = "trash";
+        };
+        junk = {
+           protectedBy = "View";
+           pageName    = "UIxMailView";
+           actionName  = "junk";
+        };
+        edit = {
+           protectedBy = "View";
+           pageName    = "UIxMailEditor";
+        };
+        compose = {
+           protectedBy = "View";
+           actionClass = "UIxMailEditorAction";
+           actionName  = "compose";
+        };
+        reply = {
+           protectedBy = "View";
+           actionClass = "UIxMailReplyAction";
+           actionName  = "reply";
+        };
+        replyall = {
+           protectedBy = "View";
+           actionClass = "UIxMailReplyAction";
+           actionName  = "replyall";
+        };
+        forward = {
+           protectedBy = "View";
+           actionClass = "UIxMailForwardAction";
+           actionName  = "forward";
+        };
       };
-    };
+   };
 
-    SOGoMailAccounts = {
+   SOGoMailAccounts = {
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value = "SOGoMailObject.toolbar";
-        };
+        toolbar = {
+           protectedBy = "View";
+           value = "SOGoMailObject.toolbar";
+        };
       };
       methods = {
-        view = {
-          protectedBy = "View";
-          pageName    = "UIxMailMainFrame";
-        };
-        compose = {
-          protectedBy = "View";
-          pageName    = "UIxMailMainFrame";
-          actionName  = "compose";
-        };
-        getMail = {
-          protectedBy = "View";
-          pageName    = "UIxMailAccountsView";
-        };
+        view = {
+           protectedBy = "View";
+           pageName    = "UIxMailMainFrame";
+        };
+        compose = {
+           protectedBy = "View";
+           pageName    = "UIxMailMainFrame";
+           actionName  = "compose";
+        };
+        getMail = {
+           protectedBy = "View";
+           pageName    = "UIxMailAccountsView";
+        };
       };
-    };
+   };
 
-    SOGoMailAccount = {
+   SOGoMailAccount = {
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value = "SOGoMailObject.toolbar";
-        };
+        toolbar = {
+           protectedBy = "View";
+           value = "SOGoMailObject.toolbar";
+        };
       };
       methods = {
-        view = {
-          protectedBy = "View";
-          pageName    = "UIxMailAccountView";
-        };
-        getMail = {
-          protectedBy = "View";
-          pageName    = "UIxMailAccountView";
-        };
-        compose = {
-          protectedBy = "View";
-          actionClass = "UIxMailEditorAction";
-          actionName  = "compose";
-        };
-        createFolder = {
-          protectedBy = "View";
-          pageName    = "UIxMailAccountView";
-          actionName  = "createFolder";
-        };
+        compose = {
+           protectedBy = "View";
+           actionClass = "UIxMailEditorAction";
+           actionName  = "compose";
+        };
+        mailboxes = {
+           protectedBy = "View";
+           actionClass = "UIxMailAccountActions";
+           actionName = "listMailboxes";
+        };
       };
-    };
+   };
 
-    SOGoDraftsFolder = {
+   SOGoDraftsFolder = {
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value = ( /* the toolbar groups */
-            ( /* first group */
-              { link  = "getMail";
-               image = "tb-mail-getmail-flat-24x24.png";
-                cssClass = "tbicon_getmail"; label = "Get Mail"; },
-              {
-              link     = "#"; // "compose"; // target = "_blank";
-              isSafe = NO;
-               onclick  = "return openMessageWindow(null, 'compose');";
-              image = "tb-mail-write-flat-24x24.png";
-              cssClass = "tbicon_compose"; label = "Write"; },
-            )
-          );
-        };
+        toolbar = {
+           protectedBy = "View";
+           value = ( /* the toolbar groups */
+                     ( /* first group */
+                        { link  = "getMail";
+                          image = "tb-mail-getmail-flat-24x24.png";
+                          cssClass = "tbicon_getmail"; label = "Get Mail"; },
+                        {
+                           link     = "#"; // "compose"; // target = "_blank";
+                           isSafe = NO;
+                           onclick  = "return openMessageWindow(null, 'compose');";
+                           image = "tb-mail-write-flat-24x24.png";
+                           cssClass = "tbicon_compose"; label = "Write"; },
+                       )
+              );
+        };
       };
       methods = {
-        view = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-        };
-        getMail = {
-          protectedBy = "View";
-          pageName    = "UIxMailListView";
-        };
-        compose = {
-          protectedBy = "View";
-          actionClass = "UIxMailEditorAction";
-          actionName  = "compose";
-        };
+        view = {
+           protectedBy = "View";
+           pageName    = "UIxMailListView";
+        };
+        getMail = {
+           protectedBy = "View";
+           pageName    = "UIxMailListView";
+        };
+        compose = {
+           protectedBy = "View";
+           actionClass = "UIxMailEditorAction";
+           actionName  = "compose";
+        };
       };
-    };
+   };
 
-    SOGoDraftObject = {
+   SOGoDraftObject = {
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value       = "SOGoDraftObject.toolbar";
-        };
+        toolbar = {
+           protectedBy = "View";
+           value       = "SOGoDraftObject.toolbar";
+        };
       };
       methods = {
-        view = { /* somewhat hackish */
-          protectedBy = "View";
-          pageName    = "UIxMailEditor";
-        };
-        edit = {
-          protectedBy = "View";
-          pageName    = "UIxMailEditor";
-          actionName  = "edit";
-        };
-        save = {
-          protectedBy = "View";
-          pageName    = "UIxMailEditor";
-          actionName  = "save";
-        };
-        delete = {
-          protectedBy = "View";
-          pageName    = "UIxMailEditor";
-          actionName  = "delete";
-        };
+        view = { /* somewhat hackish */
+                 protectedBy = "View";
+                 pageName    = "UIxMailEditor";
+        };
+        edit = {
+           protectedBy = "View";
+           pageName    = "UIxMailEditor";
+           actionName  = "edit";
+        };
+        save = {
+           protectedBy = "View";
+           pageName    = "UIxMailEditor";
+           actionName  = "save";
+        };
+        delete = {
+           protectedBy = "View";
+           pageName    = "UIxMailEditor";
+           actionName  = "delete";
+        };
 
-        viewAttachments = {
-          protectedBy = "View";
-          pageName    = "UIxMailEditorAttach";
-          actionName  = "viewAttachments";
-        };
-        attach = {
-          protectedBy = "View";
-          pageName    = "UIxMailEditorAttach";
-          actionName  = "attach";
-        };
-        deleteAttachment = {
-          protectedBy = "View";
-          pageName    = "UIxMailEditorAttach";
-          actionName  = "deleteAttachment";
-        };
-        send = {
-          protectedBy = "View";
-          pageName    = "UIxMailEditor";
-          actionName  = "send";
-        };
+        viewAttachments = {
+           protectedBy = "View";
+           pageName    = "UIxMailEditorAttach";
+           actionName  = "viewAttachments";
+        };
+        attach = {
+           protectedBy = "View";
+           pageName    = "UIxMailEditorAttach";
+           actionName  = "attach";
+        };
+        deleteAttachment = {
+           protectedBy = "View";
+           pageName    = "UIxMailEditorAttach";
+           actionName  = "deleteAttachment";
+        };
+        send = {
+           protectedBy = "View";
+           pageName    = "UIxMailEditor";
+           actionName  = "send";
+        };
       };
-    };
+   };
 
-    /* Sieve */
+   /* Sieve */
 
-/*    SOGoSieveScriptsFolder = {
+   /*    SOGoSieveScriptsFolder = {
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value = (
-            (
-              {
-              link  = "getMail";
-              image = "tb-mail-getmail-flat-24x24.png";
-              cssClass = "tbicon_getmail"; label = "Get Mail";
-              },
-              {
-              link     = "#"; // "compose"; // target = "_blank";
-              onclick  = "clickedNewFilter(this); return false";
-              image = "tb-mail-write-flat-24x24.png";
-              cssClass = "tbicon_compose"; label = "New Filter";
-              },
-            ),
-            (
-              { link = "#";
-                cssClass = "tbicon_delete"; label = "Delete"; },
-            ),
-          );
-        };
+        toolbar = {
+           protectedBy = "View";
+           value = (
+              (
+              {
+                 link  = "getMail";
+                 image = "tb-mail-getmail-flat-24x24.png";
+                 cssClass = "tbicon_getmail"; label = "Get Mail";
+              },
+                 {
+                    link     = "#"; // "compose"; // target = "_blank";
+                    onclick  = "clickedNewFilter(this); return false";
+                    image = "tb-mail-write-flat-24x24.png";
+                    cssClass = "tbicon_compose"; label = "New Filter";
+                 },
+              ),
+              (
+              { link = "#";
+              cssClass = "tbicon_delete"; label = "Delete"; },
+              ),
+              );
+        };
       };
       methods = {
-        view = {
-          protectedBy = "View";
-          pageName    = "UIxFilterList";
-        };
-        create = {
-          protectedBy = "View";
-          pageName    = "UIxFilterList";
-          actionName  = "create";
-        };
+        view = {
+           protectedBy = "View";
+           pageName    = "UIxFilterList";
+        };
+        create = {
+           protectedBy = "View";
+           pageName    = "UIxFilterList";
+           actionName  = "create";
+        };
       };
-    };
+   };
 
-    SOGoSieveScriptObject = {
+   SOGoSieveScriptObject = {
       slots = {
-        toolbar = {
-          protectedBy = "View";
-          value = (
-            ( { link  = "#";
-                onclick  = "clickedEditorSave(this);return false;";
-               image = "tb-mail-file-flat-24x24.png";
-               cssClass = "tbicon_save"; label = "Save"; },
-              { link = "#";
-                onclick  = "clickedEditorDelete(this);return false;";
-               image = "tb-mail-delete-flat-24x24.png";
-                cssClass = "tbicon_delete"; label = "Delete"; },
-            )
-          );
-        };
+        toolbar = {
+           protectedBy = "View";
+           value = (
+              ( { link  = "#";
+              onclick  = "clickedEditorSave(this);return false;";
+              image = "tb-mail-file-flat-24x24.png";
+              cssClass = "tbicon_save"; label = "Save"; },
+                 { link = "#";
+                   onclick  = "clickedEditorDelete(this);return false;";
+                   image = "tb-mail-delete-flat-24x24.png";
+                   cssClass = "tbicon_delete"; label = "Delete"; },
+                )
+              );
+        };
       };
       methods = {
-        edit = {
-          protectedBy = "View";
-          pageName    = "UIxSieveEditor";
-          actionName  = "edit";
-        };
-        save = {
-          protectedBy = "View";
-          pageName    = "UIxSieveEditor";
-          actionName  = "save";
-        };
-        delete = {
-          protectedBy = "View";
-          pageName    = "UIxSieveEditor";
-          actionName  = "delete";
-        };
+        edit = {
+           protectedBy = "View";
+           pageName    = "UIxSieveEditor";
+           actionName  = "edit";
+        };
+        save = {
+           protectedBy = "View";
+           pageName    = "UIxSieveEditor";
+           actionName  = "save";
+        };
+        delete = {
+           protectedBy = "View";
+           pageName    = "UIxSieveEditor";
+           actionName  = "delete";
+        };
       };
-    }; */
-  };
+   }; */
+};
 }
index 13ea2c5ff7c5429ee6e77de76ea653e053fa8f6b..172d94a320dcaed866467945072db9d372c9589e 100644 (file)
@@ -29,6 +29,12 @@ libSOGoUI_OBJC_FILES +=              \
        SOGoAptFormatter.m      \
        SOGoJSStringFormatter.m \
        WOContext+UIx.m         \
+       \
+       SOGoACLAdvisory.m       \
+       SOGoACLFrenchAdditionAdvisory.m         \
+       SOGoACLFrenchRemovalAdvisory.m          \
+       SOGoACLEnglishAdditionAdvisory.m        \
+       SOGoACLEnglishRemovalAdvisory.m
 
 # make
 
diff --git a/UI/SOGoUI/SOGoACLAdvisory.h b/UI/SOGoUI/SOGoACLAdvisory.h
new file mode 100644 (file)
index 0000000..788a49a
--- /dev/null
@@ -0,0 +1,50 @@
+/* SOGoACLAdvisory.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SOGOACLADVISORY_H
+#define SOGOACLADVISORY_H
+
+#import "UIxComponent.h"
+
+@interface SOGoACLAdvisory : UIxComponent
+{
+  SOGoObject *aclObject;
+  NSString *recipientUID;
+
+  BOOL isSubject;
+  BOOL isBody;
+}
+
+- (void) setACLObject: (SOGoObject *) newACLObject;
+- (void) setRecipientUID: (NSString *) newRecipientUID;
+- (void) send;
+
+- (BOOL) isSubject;
+- (BOOL) isBody;
+
+- (NSString *) subject;
+- (NSString *) body;
+- (NSString *) aclMethod;
+
+@end
+
+#endif /* SOGOACLADVISORY_H */
diff --git a/UI/SOGoUI/SOGoACLAdvisory.m b/UI/SOGoUI/SOGoACLAdvisory.m
new file mode 100644 (file)
index 0000000..78a146e
--- /dev/null
@@ -0,0 +1,202 @@
+/* SOGoACLAdvisory.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <NGObjWeb/WOResponse.h>
+#import <NGExtensions/NGHashMap.h>
+#import <NGMail/NGMimeMessage.h>
+#import <NGMail/NGSendMail.h>
+#import <NGMime/NGMimeBodyPart.h>
+#import <NGMime/NGMimeMultipartBody.h>
+
+#import <SoObjects/SOGo/SOGoUser.h>
+#import <SoObjects/SOGo/SOGoObject.h>
+#import <SoObjects/SOGo/LDAPUserManager.h>
+#import <SoObjects/SOGo/NSCalendarDate+SOGo.h>
+
+#import "SOGoACLAdvisory.h"
+
+@implementation SOGoACLAdvisory
+
+- (id) init
+{
+  if ((self = [super init]))
+    {
+      aclObject = nil;
+      recipientUID = nil;
+
+      isSubject = NO;
+      isBody = NO;
+    }
+
+  return self;
+}
+
+- (void) dealloc
+{
+  [recipientUID release];
+  [aclObject release];
+  [super dealloc];
+}
+
+- (void) setACLObject: (SOGoObject *) newACLObject
+{
+  ASSIGN (aclObject, newACLObject);
+}
+
+- (void) setRecipientUID: (NSString *) newRecipientUID
+{
+  ASSIGN (recipientUID, newRecipientUID);
+}
+
+- (BOOL) isSubject
+{
+  return isSubject;
+}
+
+- (BOOL) isBody
+{
+  return isBody;
+}
+
+- (NSString *) currentUserName
+{
+  return [[context activeUser] cn];
+}
+
+- (NSString *) httpAdvisoryURL
+{
+  NSMutableString *url;
+
+  url
+    = [NSMutableString stringWithString:
+                        [aclObject httpURLForAdvisoryToUser: recipientUID]];
+  if (![url hasSuffix: @"/"])
+    [url appendString: @"/"];
+
+  return url;
+}
+
+- (NSString *) resourceName
+{
+  return [aclObject nameInContainer];
+}
+
+- (NSString *) subject
+{
+  NSString *subject;
+
+  isSubject = YES;
+  subject = [[self generateResponse] contentAsString];
+  isSubject = NO;
+
+  return [subject stringByTrimmingSpaces];
+}
+
+- (NSString *) body
+{
+  NSString *body;
+
+  isBody = YES;
+  body = [[self generateResponse] contentAsString];
+  isBody = NO;
+
+  return [body stringByTrimmingSpaces];
+}
+
+- (NSString *) aclMethod
+{
+  [self subclassResponsibility: _cmd];
+
+  return nil;
+}
+
+- (NGMimeBodyPart *) _textPart
+{
+  NGMutableHashMap *headerMap;
+  NGMimeBodyPart *part;
+  NSData *body;
+
+  headerMap = [NGMutableHashMap hashMapWithCapacity: 1];
+  [headerMap setObject: @"text/plain; charset=utf-8" forKey: @"content-type"];
+
+  part = [NGMimeBodyPart bodyPartWithHeader: headerMap];
+  body = [[self body] dataUsingEncoding: NSUTF8StringEncoding];
+  [part setBody: [self body]];
+
+  return part;
+}
+
+- (NGMimeBodyPart *) _sogoNotificationPart
+{
+  NGMutableHashMap *headerMap;
+  NGMimeBodyPart *part;
+  NSData *body;
+
+  /* calendar part */
+  headerMap = [NGMutableHashMap hashMapWithCapacity: 1];
+  [headerMap setObject: [NSString stringWithFormat:
+                                   @"%@; method=%@; type=%@; charset=%@",
+                                 @"application/x-sogo-notification",
+                                 [self aclMethod], [aclObject folderType],
+                                 @"utf-8"]
+            forKey: @"content-type"];
+
+  part = [NGMimeBodyPart bodyPartWithHeader: headerMap];
+  body = [[aclObject resourceURLForAdvisoryToUser: recipientUID]
+          dataUsingEncoding: NSUTF8StringEncoding];
+  [part setBody: body];
+
+  return part;
+}
+
+- (void) send
+{
+  NSString *recipient, *date;
+  NGMutableHashMap *headerMap;
+  NGMimeMessage *message;
+  NGMimeMultipartBody *body;
+  SOGoUser *activeUser;
+
+  activeUser = [context activeUser];
+  recipient = [[LDAPUserManager sharedUserManager] getFullEmailForUID: recipientUID];
+
+  headerMap = [NGMutableHashMap hashMapWithCapacity: 5];
+  [headerMap setObject: @"multipart/alternative" forKey: @"content-type"];
+  [headerMap setObject: [activeUser fullEmail] forKey: @"From"];
+  [headerMap setObject: recipient forKey: @"To"];
+  date = [[NSCalendarDate date] rfc822DateString];
+  [headerMap setObject: date forKey: @"Date"];
+  [headerMap setObject: [self subject] forKey: @"Subject"];
+  message = [NGMimeMessage messageWithHeader: headerMap];
+
+  body = [[NGMimeMultipartBody alloc] initWithPart: message];
+  [body addBodyPart: [self _textPart]];
+  [body addBodyPart: [self _sogoNotificationPart]];
+  [message setBody: body];
+  [body release];
+
+  [[NGSendMail sharedSendMail] sendMimePart: message
+                              toRecipients: [NSArray arrayWithObject: recipient]
+                              sender: [activeUser primaryEmail]];
+}
+
+@end
diff --git a/UI/SOGoUI/SOGoACLEnglishAdditionAdvisory.h b/UI/SOGoUI/SOGoACLEnglishAdditionAdvisory.h
new file mode 100644 (file)
index 0000000..cfc2bc5
--- /dev/null
@@ -0,0 +1,31 @@
+/* SOGoACLEnglishAdditionAdvisory.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SOGOACLFRENCHADDITIONADVISORY_H
+#define SOGOACLFRENCHADDITIONADVISORY_H
+
+#import "SOGoACLAdvisory.h"
+
+@interface SOGoACLEnglishAdditionAdvisory : SOGoACLAdvisory
+@end
+
+#endif /* SOGOACLFRENCHADDITIONADVISORY_H */
diff --git a/UI/SOGoUI/SOGoACLEnglishAdditionAdvisory.m b/UI/SOGoUI/SOGoACLEnglishAdditionAdvisory.m
new file mode 100644 (file)
index 0000000..323684d
--- /dev/null
@@ -0,0 +1,32 @@
+/* SOGoACLEnglishAdditionAdvisory.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import "SOGoACLEnglishAdditionAdvisory.h"
+
+@implementation SOGoACLEnglishAdditionAdvisory
+
+- (NSString *) aclMethod
+{
+  return @"add";
+}
+
+@end
diff --git a/UI/SOGoUI/SOGoACLEnglishRemovalAdvisory.h b/UI/SOGoUI/SOGoACLEnglishRemovalAdvisory.h
new file mode 100644 (file)
index 0000000..7590f10
--- /dev/null
@@ -0,0 +1,31 @@
+/* SOGoACLEnglishRemovalAdvisory.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SOGOACLENGLISHREMOVALADVISORY_H
+#define SOGOACLENGLISHREMOVALADVISORY_H
+
+#import "SOGoACLAdvisory.h"
+
+@interface SOGoACLEnglishRemovalAdvisory : SOGoACLAdvisory
+@end
+
+#endif /* SOGOACLENGLISHREMOVALADVISORY_H */
diff --git a/UI/SOGoUI/SOGoACLEnglishRemovalAdvisory.m b/UI/SOGoUI/SOGoACLEnglishRemovalAdvisory.m
new file mode 100644 (file)
index 0000000..f5eacbc
--- /dev/null
@@ -0,0 +1,32 @@
+/* SOGoACLEnglishRemovalAdvisory.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import "SOGoACLEnglishRemovalAdvisory.h"
+
+@implementation SOGoACLEnglishRemovalAdvisory
+
+- (NSString *) aclMethod
+{
+  return @"add";
+}
+
+@end
diff --git a/UI/SOGoUI/SOGoACLFrenchAdditionAdvisory.h b/UI/SOGoUI/SOGoACLFrenchAdditionAdvisory.h
new file mode 100644 (file)
index 0000000..2b482ac
--- /dev/null
@@ -0,0 +1,31 @@
+/* SOGoACLFrenchAdditionAdvisory.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SOGOACLFRENCHADDITIONADVISORY_H
+#define SOGOACLFRENCHADDITIONADVISORY_H
+
+#import "SOGoACLAdvisory.h"
+
+@interface SOGoACLFrenchAdditionAdvisory : SOGoACLAdvisory
+@end
+
+#endif /* SOGOACLFRENCHADDITIONADVISORY_H */
similarity index 77%
rename from UI/MailerUI/UIxMailSplashView.m
rename to UI/SOGoUI/SOGoACLFrenchAdditionAdvisory.m
index 6280118894c8bad94be578885233b7cd32d9082b..229dcbc9521f3f13b3e1293a6edd1f2566341940 100644 (file)
@@ -1,6 +1,6 @@
-/* UIxMailSplashView - this file is part of SOGo
+/* SOGoACLFrenchAdditionAdvisory.m - this file is part of SOGo
  *
- * Copyright (C) 2006 Inverse groupe conseil
+ * Copyright (C) 2007 Inverse groupe conseil
  *
  * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
  *
  * Boston, MA 02111-1307, USA.
  */
 
-#import <SOGoUI/UIxComponent.h>
+#import "SOGoACLFrenchAdditionAdvisory.h"
 
-@interface UIxMailSplashView : UIxComponent
-@end
+@implementation SOGoACLFrenchAdditionAdvisory
 
-@implementation UIxMailSplashView
-@end /* UIxMailSplashView */
+@end
diff --git a/UI/SOGoUI/SOGoACLFrenchRemovalAdvisory.h b/UI/SOGoUI/SOGoACLFrenchRemovalAdvisory.h
new file mode 100644 (file)
index 0000000..9a6c963
--- /dev/null
@@ -0,0 +1,31 @@
+/* SOGoACLFrenchRemovalAdvisory.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SOGOACLFRENCHREMOVALADVISORY_H
+#define SOGOACLFRENCHREMOVALADVISORY_H
+
+#import "SOGoACLAdvisory.h"
+
+@interface SOGoACLFrenchRemovalAdvisory : SOGoACLAdvisory
+@end
+
+#endif /* SOGOACLFRENCHREMOVALADVISORY_H */
diff --git a/UI/SOGoUI/SOGoACLFrenchRemovalAdvisory.m b/UI/SOGoUI/SOGoACLFrenchRemovalAdvisory.m
new file mode 100644 (file)
index 0000000..050d2cf
--- /dev/null
@@ -0,0 +1,27 @@
+/* SOGoACLFrenchRemovalAdvisory.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import "SOGoACLFrenchRemovalAdvisory.h"
+
+@implementation SOGoACLFrenchRemovalAdvisory
+
+@end
diff --git a/UI/Templates/MailerUI/UIxMailAccountView.wox b/UI/Templates/MailerUI/UIxMailAccountView.wox
deleted file mode 100644 (file)
index 26cef68..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version='1.0' standalone='yes'?>
-  <div style="padding: 1em;"
-    xmlns="http://www.w3.org/1999/xhtml"
-    xmlns:var="http://www.skyrix.com/od/binding"
-    xmlns:const="http://www.skyrix.com/od/constant"
-    xmlns:uix="OGo:uix"
-    xmlns:rsrc="OGo:url"
-    xmlns:label="OGo:label">
-    <h2>
-      SOGo Mail - <var:string value="objectTitle" />
-      
-      <var:if condition="clientObject.isSharedAccount">
-        <var:string label:value="Shared Account: " />
-      </var:if>
-      
-    </h2>
-    <var:if condition="clientObject.isSharedAccount">
-      <div>
-        <var:string label:value="Share: " />
-        <var:string value="clientObject.sharedAccountName" />
-      </div>
-    </var:if>
-    
-    <h3>Email</h3>
-    <p>
-      <a href="INBOX/" onclick="initMailboxSelection(currentMailbox + '/INBOX'); openMailbox(currentMailbox + '/INBOX'); return false;"><img rsrc:src="read-messages.png" /><var:string label:value="Read messages" /></a><br />
-      <a href="#" onclick="clickedCompose(this);"><img rsrc:src="write-message.png" /><var:string label:value="Write a new message" /></a><br />
-    </p>
-
-    <h3>Accounts</h3>
-    <p>
-      <a href=""><img rsrc:src="account-settings.png" />View settings for this account</a><br />
-      <a href=""><img rsrc:src="create-account.png" />Create a new account</a> [TBD: not in Agenor]<br />
-    </p>
-    
-    <h3>Advanced Features</h3>
-    <p>
-      <a href=""><img rsrc:src="search-messages.png" />Search messages</a><br />
-      <a href=""><img rsrc:src="manage-filters.png" />Manage message filters</a><br />
-      <a href=""><img rsrc:src="manage-imap.png" />Manage folder subscriptions</a><br />
-      <a href=""><img rsrc:src="offline-settings.png" />Offline settings</a> [TBD: not in Agenor]<br />
-    </p>
-  </div>
index e5e57d9dc36141447e4d94eaed31915a8b2b4ebc..21bed1e35e398ce7e58cdc3abd91056de7448c0d 100644 (file)
@@ -2,12 +2,17 @@
   <var:component xmlns="http://www.w3.org/1999/xhtml"
     xmlns:var="http://www.skyrix.com/od/binding"
     xmlns:const="http://www.skyrix.com/od/constant"
-    xmlns:uix="OGo:uix"
+    xmlns:rsrc="OGo:url"
     xmlns:label="OGo:label"
     className="UIxPageFrame"
     title="title"
     popup="isPopup"
     >
+    <script type="text/javascript" rsrc:src="dtree.js"><!-- space --></script>
+    <script type="text/javascript" rsrc:src="MailerUI+dTree.js"><!-- space --></script>
+    <script type="text/javascript">
+      var mailAccounts = '<var:string value="mailAccounts" const:escapeHTML="NO"/>'.evalJSON(true);
+    </script>
     <div class="menu" id="accountIconMenu">
       <ul>
         <li><var:string label:value="Subscribe..." /></li>
       </ul>
     </div>
 
-    <var:component
-      className="UIxMailFolderMenu"
-      const:menuId="mailboxes-menu"
-      const:parentMenu="0"
-      rootClassName="treeRootClassName" 
-      const:treeFolderAction="view" />
-
     <div class="menu" id="mark-menu">
       <ul id="">
         <li><var:string label:value="As Read" /></li>
 
     <div id="leftPanel">
       <div class="titlediv"><var:string label:value="Folders" /></div>
-      <var:component className="UIxMailTree" 
-        rootClassName="treeRootClassName" 
-        const:treeFolderAction="view" 
-        />
+      <div id="folderTreeContent"><!-- space --></div>
     </div>
-      
+
     <div class="dragHandle" id="verticalDragHandle"><!-- space --></div>
 
     <div id="rightPanel">
         <div id="mailboxContent"><!-- space --></div>
         <div class="dragHandle" id="rightDragHandle"><!-- space --></div>
         <div id="messageContent"><!-- space --></div>
-      <script type="text/javascript">
-        initMailboxSelection('<var:string value="mailFolderName" />');
-      </script>
     </div>
 
     <var:string value="errorAlertJavaScript" const:escapeHTML="NO" />
diff --git a/UI/Templates/SOGoACLEnglishAdditionAdvisory.wox b/UI/Templates/SOGoACLEnglishAdditionAdvisory.wox
new file mode 100644 (file)
index 0000000..b15cd0d
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE container>
+<container 
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:var="http://www.skyrix.com/od/binding"
+  xmlns:const="http://www.skyrix.com/od/constant"
+  xmlns:rsrc="OGo:url"
+  xmlns:label="OGo:label">
+
+<var:if condition="isSubject">
+    <var:string value="currentUserName"/> has added you
+</var:if>
+
+<var:if condition="isBody">
+<var:string value="currentUserName"/> has added you to the access list for his '<var:string value="resourceName"/>' folder.
+You can subscribe directly to that folder by following this link:
+    <var:string value="httpAdvisoryURL"/>subscribe?mail-invitation=YES
+
+Otherwise, you will be able to subscribe later from the SOGo web interface.
+</var:if>
+
+</container>
diff --git a/UI/Templates/SOGoACLEnglishRemovalAdvisory.wox b/UI/Templates/SOGoACLEnglishRemovalAdvisory.wox
new file mode 100644 (file)
index 0000000..eff944b
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE container>
+<container 
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:var="http://www.skyrix.com/od/binding"
+  xmlns:const="http://www.skyrix.com/od/constant"
+  xmlns:rsrc="OGo:url"
+  xmlns:label="OGo:label">
+
+<var:if condition="isSubject">
+    <var:string value="currentUserName"/> has removed you
+</var:if>
+
+<var:if condition="isBody">
+<var:string value="currentUserName"/> has removed you from the access list for his '<var:string value="resourceName"/>' folder.
+You can unsubscribe directly to that folder by following this link:
+    <var:string value="httpAdvisoryURL"/>unsubscribe?mail-invitation=YES
+
+Otherwise, you will be able to unsubscribe later from the SOGo web interface.
+</var:if>
+
+</container>
diff --git a/UI/Templates/SOGoACLFrenchAdditionAdvisory.wox b/UI/Templates/SOGoACLFrenchAdditionAdvisory.wox
new file mode 100644 (file)
index 0000000..4686ccf
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE container>
+<container 
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:var="http://www.skyrix.com/od/binding"
+  xmlns:const="http://www.skyrix.com/od/constant"
+  xmlns:rsrc="OGo:url"
+  xmlns:label="OGo:label">
+
+<var:if condition="isSubject">
+    <var:string value="currentUserName"/> vous a ajouté
+</var:if>
+
+<var:if condition="isBody">
+<var:string value="currentUserName"/> vous a ajouté a sa liste de permission pour son dossier '<var:string value="resourceName"/>'.
+Vous pouvez vous inscrire directement a ce dossier en cliquant sur le lien suivant:
+    <var:string value="httpAdvisoryURL"/>unsubscribe?mail-invitation=YES
+
+Autrement, il vous sera toujours possible de vous inscrire plus tard via l'interface web de SOGo.
+</var:if>
+
+</container>
diff --git a/UI/Templates/SOGoACLFrenchRemovalAdvisory.wox b/UI/Templates/SOGoACLFrenchRemovalAdvisory.wox
new file mode 100644 (file)
index 0000000..7679866
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE container>
+<container 
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:var="http://www.skyrix.com/od/binding"
+  xmlns:const="http://www.skyrix.com/od/constant"
+  xmlns:rsrc="OGo:url"
+  xmlns:label="OGo:label">
+
+<var:if condition="isSubject">
+    <var:string value="currentUserName"/> vous a enlevé
+</var:if>
+
+<var:if condition="isBody">
+<var:string value="currentUserName"/> vous a enlevé de sa liste de permission pour son dossier '<var:string value="resourceName"/>'.
+Vous pouvez vous désinscrire directement en cliquant sur le lien suivant:
+    <var:string value="httpAdvisoryURL"/>unsubscribe?mail-invitation=YES
+
+Autrement, il vous sera toujours possible de vous désinscrire plus tard via l'interface web de SOGo.
+</var:if>
+
+</container>
index 2792a14f737559383e21dfefdff437755e13c58f..f74e885f563b12147c6f7c3b3865eb12c2b94fbf 100644 (file)
 <?xml version="1.0" standalone="yes"?>
-  <container 
-    xmlns="http://www.w3.org/1999/xhtml"
-    xmlns:var="http://www.skyrix.com/od/binding"
-    xmlns:const="http://www.skyrix.com/od/constant"
-    xmlns:rsrc="OGo:url"
+<!DOCTYPE container>
+<container 
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:var="http://www.skyrix.com/od/binding"
+  xmlns:const="http://www.skyrix.com/od/constant"
+  xmlns:rsrc="OGo:url"
     xmlns:label="OGo:label"
-    ><var:string var:value="doctype" const:escapeHTML="NO" />
-    <var:if condition="hideFrame" const:negate="YES"
-      ><html>
-        <head>
-          <title>
-            <var:string value="title"/>
-          </title>
-          <meta name="hideFrame" var:content="hideFrame" />
-          <meta name="description" content="SOGo Web Interface" />
-          <meta name="author" content="SKYRIX Software AG/Inverse groupe conseil" />
-          <meta name="robots" content="stop" />
-          <link href="mailto:supper@inverse.ca" rev="made" />
-          <link rel="shortcut icon" rsrc:href="lori_16x16.ico" type="image/x-icon" />
-          <link type="text/css" rel="stylesheet" rsrc:href="generic.css" />
-          <link type="text/css" rel="stylesheet" rsrc:href="dtree.css" />
-          <var:if condition="hasProductSpecificCSS"
-            ><link type="text/css" rel="stylesheet" var:href="productCSSURL"
-              /></var:if>
-          <var:if condition="hasPageSpecificCSS"
-            ><link type="text/css" rel="stylesheet" var:href="pageCSSURL"
-              /></var:if>
-        </head>
+  ><var:string var:value="doctype" const:escapeHTML="NO" />
+  <var:if condition="hideFrame" const:negate="YES"
+    ><html>
+      <head>
+       <title>
+         <var:string value="title"/>
+       </title>
+       <meta name="hideFrame" var:content="hideFrame" />
+       <meta name="description" content="SOGo Web Interface" />
+       <meta name="author" content="SKYRIX Software AG/Inverse groupe conseil" />
+       <meta name="robots" content="stop" />
+       <link href="mailto:supper@inverse.ca" rev="made" />
+       <link rel="shortcut icon" rsrc:href="lori_16x16.ico" type="image/x-icon" />
+       <link type="text/css" rel="stylesheet" rsrc:href="generic.css" />
+       <link type="text/css" rel="stylesheet" rsrc:href="dtree.css" />
+       <var:if condition="hasProductSpecificCSS"
+         ><link type="text/css" rel="stylesheet" var:href="productCSSURL"
+           /></var:if>
+       <var:if condition="hasPageSpecificCSS"
+         ><link type="text/css" rel="stylesheet" var:href="pageCSSURL"
+           /></var:if>
+      </head>
 
-        <body oncontextmenu="return false;" var:class="bodyClasses">
-          <script type="text/javascript">
-            var UserFolderURL = '<var:string value="userFolderPath" />';
-            var ApplicationBaseURL = '<var:string value="applicationPath" />';
-            var ResourcesURL = '/SOGo.woa/WebServerResources';
-            var UserLogin = '<var:string value="shortUserNameForDisplay" />';
-          </script>
+      <body var:class="bodyClasses">
+       <script type="text/javascript">
+         var UserFolderURL = '<var:string value="userFolderPath" />';
+         var ApplicationBaseURL = '<var:string value="applicationPath" />';
+         var ResourcesURL = '/SOGo.woa/WebServerResources';
+         var UserLogin = '<var:string value="shortUserNameForDisplay" />';
+       </script>
 
-          <script type="text/javascript" rsrc:src="prototype.js"><!-- space required --></script>
-          <script type="text/javascript" rsrc:src="JavascriptAPIExtensions.js"><!-- space required --></script>
-          <script type="text/javascript" rsrc:src="HTMLElement.js"><!-- space required --></script>
-          <script type="text/javascript" rsrc:src="HTMLInputElement.js"><!-- space required --></script>
-          <script type="text/javascript" rsrc:src="HTMLTableElement.js"><!-- space required --></script>
-          <script type="text/javascript" rsrc:src="HTMLUListElement.js"><!-- space required --></script>
-          <script type="text/javascript" rsrc:src="generic.js"><!-- space required --></script>
-          <script type="text/javascript" rsrc:src="SOGoDragAndDrop.js"><!-- space required --></script>
-          <script type="text/javascript" rsrc:src="SOGoDragHandles.js"><!-- space required --></script>
-          <var:if condition="hasProductSpecificJavaScript"
-            ><script type="text/javascript" var:src="productJavaScriptURL"><!-- space required --></script
-              ></var:if>
-          <var:if condition="hasPageSpecificJavaScript"
-            ><script type="text/javascript" var:src="pageJavaScriptURL"> <!-- space required --></script
-              ></var:if>
-          <var:js-stringtable
-            var:framework="productFrameworkName"
-            const:identifier="labels" />
+       <script type="text/javascript" rsrc:src="_IEtoW3C.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="events.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="prototype.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="JavascriptAPIExtensions.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="HTMLElement.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="HTMLInputElement.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="HTMLTableElement.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="HTMLUListElement.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="generic.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="SOGoDragAndDrop.js"><!-- space required --></script>
+       <script type="text/javascript" rsrc:src="SOGoDragHandles.js"><!-- space required --></script>
+       <var:if condition="hasProductSpecificJavaScript"
+         ><script type="text/javascript" var:src="productJavaScriptURL"><!-- space required --></script
+           ></var:if>
+       <var:if condition="hasPageSpecificJavaScript"
+         ><script type="text/javascript" var:src="pageJavaScriptURL"> <!-- space required --></script
+           ></var:if>
+       <var:js-stringtable
+         var:framework="productFrameworkName"
+         const:identifier="labels" />
 
-          <var:if condition="isPopup" const:negate="YES"
-            ><var:if condition="context.isUIxDebugEnabled"
-              ><div id="logConsole"><!-- space --></div></var:if>
+       <var:if condition="isPopup" const:negate="YES"
+         ><var:if condition="context.isUIxDebugEnabled"
+           ><div id="logConsole"><!-- space --></div></var:if>
 
-            <div id="linkBanner" class="linkbanner">
-              <a var:href="relativeCalendarPath"
-                ><var:string label:value="Calendar" /></a> |
-              <a var:href="relativeContactsPath"
-                ><var:string label:value="Address Book" /></a> |
-              <a var:href="relativeMailPath"
-                ><var:string label:value="Mail" /></a>
-<!--              | <a var:href="logoffPath"
-                ><var:string label:value="Logoff" /></a> -->
-              <var:if condition="context.isUIxDebugEnabled"
-                >| <a href="#"><var:string
-                    label:value="Log Console (dev.)" /></a
-                  ></var:if>
-            </div>
-          </var:if
-            
-            ><var:component className="UIxToolbar" var:toolbar="toolbar"
-            />
+         <div id="linkBanner" class="linkbanner">
+           <a var:href="relativeCalendarPath"
+             ><var:string label:value="Calendar" /></a> |
+           <a var:href="relativeContactsPath"
+             ><var:string label:value="Address Book" /></a> |
+           <a var:href="relativeMailPath"
+             ><var:string label:value="Mail" /></a>
+           <!--              | <a var:href="logoffPath"
+           ><var:string label:value="Logoff" /></a> -->
+           <var:if condition="context.isUIxDebugEnabled"
+             >| <a href="#"><var:string
+                 label:value="Log Console (dev.)" /></a
+               ></var:if>
+         </div>
+       </var:if
+         
+         ><var:component className="UIxToolbar" var:toolbar="toolbar"
+         />
 
-          <div class="pageContent"
-            ><var:component-content
-              /></div>
-          <noscript>
-            <div class="javascriptPopupBackground">
-            </div>
-            <div class="javascriptMessagePseudoWindow noJavascriptErrorMessage">
-              <var:string label:value="noJavascriptError"
-                /><br /><br
-                /><a class="button" var:href="page.context.uri"
-                ><var:string label:value="noJavascriptRetry"
-                  /></a>
-            </div>
-          </noscript>
-        </body>
-      </html>
-    </var:if>
+       <div class="pageContent"
+         ><var:component-content
+           /></div>
+       <noscript>
+         <div class="javascriptPopupBackground">
+         </div>
+         <div class="javascriptMessagePseudoWindow noJavascriptErrorMessage">
+           <var:string label:value="noJavascriptError"
+             /><br /><br
+             /><a class="button" var:href="page.context.uri"
+             ><var:string label:value="noJavascriptRetry"
+               /></a>
+         </div>
+       </noscript>
+      </body>
+    </html>
+  </var:if>
 
-    <var:if condition="hideFrame">
-      <var:component-content />
-    </var:if>
-  </container>
-  
+  <var:if condition="hideFrame">
+    <var:component-content />
+  </var:if>
+</container>
index 3342911333614e540f85e1021711a0f09597d524..264ccac5a48f8bfc3329c76a07b5a6ca867c4887 100644 (file)
@@ -90,7 +90,7 @@ function contactsListCallback(http) {
 
 function onContactFoldersContextMenu(event) {
   var menu = $("contactFoldersMenu");
-  menu.addEventListener("hideMenu", onContactFoldersContextMenuHide, false);
+  Event.observe(menu, "hideMenu", onContactFoldersContextMenuHide, false);
   popupMenu(event, "contactFoldersMenu", this);
 
   var topNode = $("contactFolders");
@@ -104,7 +104,7 @@ function onContactFoldersContextMenu(event) {
 
 function onContactContextMenu(event, element) {
   var menu = $("contactMenu");
-  menu.addEventListener("hideMenu", onContactContextMenuHide, false);
+  Event.observe(menu, "hideMenu", onContactContextMenuHide, false);
   popupMenu(event, "contactMenu", element);
 
   var topNode = $("contactsList");
@@ -440,9 +440,7 @@ function appendAddressBook(name, folder) {
    var li = document.createElement("li");
    li.setAttribute("id", folder);
    li.appendChild(document.createTextNode(name));
-   li.addEventListener("mousedown", listRowMouseDownHandler, false);
-   li.addEventListener("click", onRowClick, false);
-   li.addEventListener("contextmenu", onContactFoldersContextMenu, false);
+   setEventsOnContactFolder(li);
    $("contactFolders").appendChild(li);
 }
 
@@ -578,31 +576,33 @@ function deniedFoldersLookupCallback(http) {
 function configureAbToolbar() {
   var toolbar = $("abToolbar");
   var links = toolbar.childNodesWithTag("a");
-  links[0].addEventListener("click", onAddressBookNew, false);
-  links[1].addEventListener("click", onAddressBookAdd, false);
-  links[2].addEventListener("click", onAddressBookRemove, false);
+  Event.observe(links[0], "click", onAddressBookNew, false);
+  Event.observe(links[1], "click", onAddressBookAdd, false);
+  Event.observe(links[2], "click", onAddressBookRemove, false);
 }
 
 function configureContactFolders() {
   var contactFolders = $("contactFolders");
   if (contactFolders) {
-    contactFolders.addEventListener("selectionchange",
-                                    onFolderSelectionChange, false);
+    Event.observe(contactFolders, "selectionchange", onFolderSelectionChange, false);
     var lis = contactFolders.childNodesWithTag("li");
-    for (var i = 0; i < lis.length; i++) {
-      lis[i].addEventListener("mousedown", listRowMouseDownHandler, false);
-      lis[i].addEventListener("click", onRowClick, false);
-      lis[i].addEventListener("contextmenu", onContactFoldersContextMenu, false);
-    }
+    for (var i = 0; i < lis.length; i++)
+      setEventsOnContactFolder(lis[i]);
 
     lookupDeniedFolders();
-    contactFolders.style.visibility = "visible;";
-
+    contactFolders.setStyle({ visibility: 'visible' });
+    
     var personalFolder = $("/personal");
     personalFolder.select();
   }
 }
 
+function setEventsOnContactFolder(node) {
+  Event.observe(node, "mousedown", listRowMouseDownHandler, false);
+  Event.observe(node, "click", onRowClick, false);
+  Event.observe(node, "contextmenu", onContactFoldersContextMenu, false);
+}
+
 function onMenuSharing(event) {
    var folders = $("contactFolders");
    var selected = folders.getSelectedNodes()[0];
@@ -612,9 +612,8 @@ function onMenuSharing(event) {
    openAclWindow(url + "/acls", title);
 }
 
-function initializeMenus() {
-   menus["menuIds"] = new Array("contactFoldersMenu", "contactMenu",
-                               "searchMenu");
+function getMenus() {
+   var menus = {};
    menus["contactFoldersMenu"] = new Array(null, "-", null,
                                           null, "-", null, "-",
                                           onMenuSharing);
@@ -623,17 +622,17 @@ function initializeMenus() {
                                    onMenuDeleteContact);
    menus["searchMenu"] = new Array(setSearchCriteria);
 
-   initMenus();
+   return menus;
 }
 
 function configureSearchField() {
    var searchValue = $("searchValue");
 
-   searchValue.addEventListener("mousedown", onSearchMouseDown, false);
-   searchValue.addEventListener("click", popupSearchMenu, false);
-   searchValue.addEventListener("blur", onSearchBlur, false);
-   searchValue.addEventListener("focus", onSearchFocus, false);
-   searchValue.addEventListener("keydown", onSearchKeyDown, false);
+   Event.observe(searchValue, "mousedown", onSearchMouseDown.bindAsEventListener(searchValue), false);
+   Event.observe(searchValue, "click", popupSearchMenu.bindAsEventListener(searchValue), false);
+   Event.observe(searchValue, "blur", onSearchBlur.bindAsEventListener(searchValue), false);
+   Event.observe(searchValue, "focus", onSearchFocus.bindAsEventListener(searchValue), false);
+   Event.observe(searchValue, "keydown", onSearchKeyDown.bindAsEventListener(searchValue), false);
 }
 
 function configureSelectionButtons() {
@@ -641,8 +640,7 @@ function configureSelectionButtons() {
    if (container) {
       var buttons = container.childNodesWithTag("input");
       for (var i = 0; i < buttons.length; i++)
-        buttons[i].addEventListener("click", onConfirmContactSelection,
-                                    false);
+       Event.observe(buttons[i], "click", onConfirmContactSelection.bindAsEventListener(buttons[i]), false);
    }
 }
 
@@ -659,4 +657,5 @@ var initContacts = {
   }
 }
 
-window.addEventListener("load", initContacts, false);
+//window.addEventListener("load", initContacts, false);
+Event.observe(window, "load", initContacts, false);
index 44e876b99fb15928a337e73eb872340203014ecc..ef2bd894f9071bf31a630f0513798eec4dcc2f3d 100644 (file)
-if (navigator.vendor == "Apple Computer, Inc." || navigator.vendor == "KDE") { // WebCore/KHTML  
-  /*
-    Crossbrowser HTMLElement Prototyping
-    Copyright (C) 2005  Jason Davis, http://www.browserland.org
-    Additional thanks to Brothercake, http://www.brothercake.com
-    
-    This code is licensed under the LGPL:
-    http://www.gnu.org/licenses/lgpl.html
-  */
-
-  (function(c) {
-    for (var i in c)
-      window["HTML" + i + "Element"] = document.createElement(c[ i ]).constructor;
-  })({
-               Html: "html", Head: "head", Link: "link", Title: "title", Meta: "meta",
-                       Base: "base", IsIndex: "isindex", Style: "style", Body: "body", Form: "form",
-                       Select: "select", OptGroup: "optgroup", Option: "option", Input: "input",
-                       TextArea: "textarea", Button: "button", Label: "label", FieldSet: "fieldset",
-                       Legend: "legend", UList: "ul", OList: "ol", DList: "dl", Directory: "dir",
-                       Menu: "menu", LI: "li", Div: "div", Paragraph: "p", Heading: "h1", Quote: "q",
-                       Pre: "pre", BR: "br", BaseFont: "basefont", Font: "font", HR: "hr", Mod: "ins",
-                       Anchor: "a", Image: "img", Object: "object", Param: "param", Applet: "applet",
-                       Map: "map", Area: "area", Script: "script", Table: "table", TableCaption: "caption",
-                       TableCol: "col", TableSection: "tbody", TableRow: "tr", TableCell: "td",
-                       FrameSet: "frameset", Frame: "frame", IFrame: "iframe"
-                       });
-  
-  function HTMLElement() {}
-  //HTMLElement.prototype     = HTMLHtmlElement.__proto__.__proto__;   
-  var HTMLDocument          = document.constructor;
-  var HTMLCollection        = document.links.constructor;
-  var HTMLOptionsCollection = document.createElement("select").options.constructor;
-  var Text                  = document.createTextNode("").constructor;
-  //var Node                  = Text;
-  
-  // More efficient for Safari 2
-  function Document() {} 
-  function Event() {} 
-  function HTMLCollection() {} 
-  function HTMLElement() {} 
-  function Node() {} 
-  Document.prototype = window["[[DOMDocument]]"]; 
-  Event.prototype = window["[[DOMEvent]]"]; 
-  HTMLCollection.prototype = window["[[HTMLCollection.prototype]]"]; 
-  HTMLElement.prototype = window["[[DOMElement.prototype]]"]; 
-  Node.prototype = window["[[DOMNode.prototype]]"]; 
-}
-
 /* custom extensions to the DOM api */
-HTMLElement.prototype.addInterface = function(objectInterface) {
-  Object.extend(this, objectInterface);
-  if (this.bind)
-    this.bind();
-}
-
-HTMLElement.prototype.childNodesWithTag = function(tagName) {
-  var matchingNodes = new Array();
-  var tagName = tagName.toUpperCase();
-
-  for (var i = 0; i < this.childNodes.length; i++) {
-    if (typeof(this.childNodes[i]) == "object"
-        && this.childNodes[i].tagName
-        && this.childNodes[i].tagName.toUpperCase() == tagName)
-      matchingNodes.push(this.childNodes[i]);
-  }
-
-  return matchingNodes;
-}
-
-HTMLElement.prototype.addClassName = function(className) {
-  var classStr = '' + this.getAttribute("class");
+Element.addMethods({
+
+  addInterface: function(element, objectInterface) {
+    element = $(element);
+    Object.extend(element, objectInterface);
+    if (element.bind)
+      element.bind();
+  },
+
+  childNodesWithTag: function(element, tagName) {
+    element = $(element);
+    var matchingNodes = new Array();
+    var tagName = tagName.toUpperCase();
+    
+    for (var i = 0; i < element.childNodes.length; i++) {
+      if (typeof(element.childNodes[i]) == "object"
+         && element.childNodes[i].tagName
+         && element.childNodes[i].tagName.toUpperCase() == tagName)
+       matchingNodes.push(element.childNodes[i]);
+    }
 
-  position = classStr.indexOf(className, 0);
-  if (position < 0) {
-    classStr = classStr + ' ' + className;
-    this.setAttribute('class', classStr);
-  }
-}
+    return matchingNodes;
+  },
 
-HTMLElement.prototype.removeClassName = function(className) {
-  var classStr = '' + this.getAttribute('class');
+  removeClassName: function(element, className) {
+    element = $(element);
+    var classStr = '' + element.readAttribute('class');
 
-  position = classStr.indexOf(className, 0);
-  while (position > -1) {
-    classStr1 = classStr.substring(0, position); 
-    classStr2 = classStr.substring(position + 10, classStr.length);
-    classStr = classStr1 + classStr2;
     position = classStr.indexOf(className, 0);
-  }
-
-  this.setAttribute('class', classStr);
-}
-
-HTMLElement.prototype.hasClassName = function(className) {
-  var classStr = '' + this.getAttribute('class');
-  position = classStr.indexOf(className, 0);
-  return (position > -1);
-}
-
-HTMLElement.prototype.getParentWithTagName = function(tagName) {
-  var currentElement = this;
-  tagName = tagName.toUpperCase();
-
-  currentElement = currentElement.parentNode;
-  while (currentElement
-         && currentElement.tagName != tagName) {
-    currentElement = currentElement.parentNode;
-  }
-
-  return currentElement;
-}
-
-HTMLElement.prototype.cascadeLeftOffset = function() {
-  var currentElement = this;
-
-  var offset = 0;
-  while (currentElement) {
-    offset += currentElement.offsetLeft;
-    currentElement = currentElement.getParentWithTagName("div");
-  }
-
-  return offset;
-}
-
-HTMLElement.prototype.cascadeTopOffset = function() {
-  var currentElement = this;
-  var offset = 0;
-
-  var i = 0;
+    while (position > -1) {
+      classStr1 = classStr.substring(0, position); 
+      classStr2 = classStr.substring(position + 10, classStr.length);
+      classStr = classStr1 + classStr2;
+      position = classStr.indexOf(className, 0);
+    }
+    
+    element.setAttribute('class', classStr);
+  },
 
-  while (currentElement
-         && currentElement instanceof HTMLElement) {
-    offset += currentElement.offsetTop;
+  getParentWithTagName: function(element, tagName) {
+    element = $(element);
+    var currentElement = element;
+    tagName = tagName.toUpperCase();
+    
     currentElement = currentElement.parentNode;
-    i++;
-  }
+    while (currentElement
+          && currentElement.tagName != tagName) {
+      currentElement = currentElement.parentNode;
+    }
+    
+    return currentElement;
+  },
 
-  return offset;
-}
-
-HTMLElement.prototype.dump = function(additionalInfo, additionalKeys) {
-  var id = this.getAttribute("id");
-  var nclass = this.getAttribute("class");
-  
-  var str = this.tagName;
-  if (id)
-    str += "; id = " + id;
-  if (nclass)
-    str += "; class = " + nclass;
-
-  if (additionalInfo)
-    str += "; " + additionalInfo;
-
-  if (additionalKeys)
-    for (var i = 0; i < additionalKeys.length; i++) {
-      var value = this.getAttribute(additionalKeys[i]);
-      if (value)
-        str += "; " + additionalKeys[i] + " = " + value;
+  cascadeLeftOffset: function(element) {
+    element = $(element);
+    var currentElement = element;
+    
+    var offset = 0;
+    while (currentElement) {
+      offset += currentElement.offsetLeft;
+      currentElement = currentElement.getParentWithTagName("div");
     }
+    
+    return offset;
+  },
 
-  log (str);
-}
+  cascadeTopOffset: function(element) {
+    element = $(element);
+    var currentElement = element;
+    var offset = 0;
+    
+    var i = 0;
+    
+    while (currentElement && currentElement.tagName) {
+      offset += currentElement.offsetTop;
+      currentElement = currentElement.parentNode;
+      i++;
+    }
+    
+    return offset;
+  },
+  dump: function(element, additionalInfo, additionalKeys) {
+    element = $(element);
+    var id = element.getAttribute("id");
+    var nclass = element.getAttribute("class");
+    
+    var str = element.tagName;
+    if (id)
+      str += "; id = " + id;
+    if (nclass)
+      str += "; class = " + nclass;
+    
+    if (additionalInfo)
+      str += "; " + additionalInfo;
+    
+    if (additionalKeys)
+      for (var i = 0; i < additionalKeys.length; i++) {
+       var value = element.getAttribute(additionalKeys[i]);
+       if (value)
+         str += "; " + additionalKeys[i] + " = " + value;
+      }
+    
+    log (str);
+  },
 
-HTMLElement.prototype.getSelectedNodes = function() {
-  var selArray = new Array();
+  getSelectedNodes: function(element) {
+    element = $(element);
+    var selArray = new Array();
+    
+    for (var i = 0; i < element.childNodes.length; i++) {
+      node = element.childNodes.item(i);
+      if (node.nodeType == 1
+         && isNodeSelected(node))
+       selArray.push(node);
+    }
+    
+    return selArray;
+  },
 
-  for (var i = 0; i < this.childNodes.length; i++) {
-    node = this.childNodes.item(i);
-    if (node.nodeType == 1
-       && isNodeSelected(node))
-      selArray.push(node);
-  }
+  getSelectedNodesId: function(element) {
+    element = $(element);
+    var selArray = new Array();
+    
+    for (var i = 0; i < element.childNodes.length; i++) {
+      node = element.childNodes.item(i);
+      if (node.nodeType == 1
+         && isNodeSelected(node))
+       selArray.push(node.getAttribute("id"));
+    }
 
-  return selArray;
-}
+    return selArray;
+  },
 
-HTMLElement.prototype.getSelectedNodesId = function() {
-  var selArray = new Array();
+  onContextMenu: function(element, event) {
+    element = $(element);
+    var popup = element.sogoContextMenu;
 
-  for (var i = 0; i < this.childNodes.length; i++) {
-    node = this.childNodes.item(i);
-    if (node.nodeType == 1
-       && isNodeSelected(node))
-      selArray.push(node.getAttribute("id"));
+    if (document.currentPopupMenu)
+      hideMenu(event, document.currentPopupMenu);
+    
+    var menuTop = event.pageY;
+    var menuLeft = event.pageX;
+    var heightDiff = (window.innerHeight
+                     - (menuTop + popup.offsetHeight));
+    if (heightDiff < 0)
+      menuTop += heightDiff;
+    
+    var leftDiff = (window.innerWidth
+                   - (menuLeft + popup.offsetWidth));
+    if (leftDiff < 0)
+      menuLeft -= popup.offsetWidth;
+    
+    popup.style.top = menuTop + "px;";
+    popup.style.left = menuLeft + "px;";
+    popup.style.visibility = "visible;";
+    
+    document.currentPopupMenu = popup;
+    Event.observe(document.body, "click", onBodyClickMenuHandler);
+  },
+
+  attachMenu: function(element, menuName) {
+    element = $(element);
+    element.sogoContextMenu = $(menuName);
+    Event.observe(element, "contextmenu", element.onContextMenu.bindAsEventListener(element));
+  },
+
+  select: function(element) {
+    element = $(element);
+    element.addClassName('_selected');
+  },
+
+  deselect: function(element) {
+    element = $(element);
+    element.removeClassName('_selected');
+  },
+
+  deselectAll: function(element) {
+    element = $(element);
+    for (var i = 0; i < element.childNodes.length; i++) {
+      var node = element.childNodes.item(i);
+      if (node.nodeType == 1)
+       node.deselect();
+    }
   }
 
-  return selArray;
-}
-
-HTMLElement.prototype.onContextMenu = function(event) {
-  var popup = this.sogoContextMenu;
-
-  if (document.currentPopupMenu)
-    hideMenu(event, document.currentPopupMenu);
-
-  var menuTop = event.pageY;
-  var menuLeft = event.pageX;
-  var heightDiff = (window.innerHeight
-                   - (menuTop + popup.offsetHeight));
-  if (heightDiff < 0)
-    menuTop += heightDiff;
-
-  var leftDiff = (window.innerWidth
-                 - (menuLeft + popup.offsetWidth));
-  if (leftDiff < 0)
-    menuLeft -= popup.offsetWidth;
-
-  popup.style.top = menuTop + "px;";
-  popup.style.left = menuLeft + "px;";
-  popup.style.visibility = "visible;";
-
-  bodyOnClick = "" + document.body.getAttribute("onclick");
-  document.body.setAttribute("onclick", "onBodyClick(event);");
-  document.currentPopupMenu = popup;
-}
-
-HTMLElement.prototype.attachMenu = function(menuName) {
-  this.sogoContextMenu = $(menuName);
-  Event.observe(this, "contextmenu", this.onContextMenu);
-}
-
-HTMLElement.prototype.select = function() {
-  this.addClassName('_selected');
-}
-
-HTMLElement.prototype.deselect = function() {
-  this.removeClassName('_selected');
-}
-
-HTMLElement.prototype.deselectAll = function () {
-  for (var i = 0; i < this.childNodes.length; i++) {
-    var node = this.childNodes.item(i);
-    if (node.nodeType == 1)
-      node.deselect();
-  }
-}
+});
index a3a1528a416dca95df7ec8d7e77d1309767bcd66..9af238a56ed2ad0da9a7b07a09fd164ef58f6a1e 100644 (file)
@@ -1,75 +1,61 @@
-HTMLInputElement.prototype._replicate = function() {
-  if (this.replica) {
-    this.replica.value = this.value;
+Form.Element.Methods._replicate =  function(element) {
+  element = $(element);
+  if (element.replica) {
+    element.replica.value = $F(element);
     var onReplicaChangeEvent = document.createEvent("UIEvents");
     onReplicaChangeEvent.initEvent("change", true, true);
-    this.replica.dispatchEvent(onReplicaChangeEvent);
+    element.replica.dispatchEvent(onReplicaChangeEvent);
   }
 }
 
-HTMLInputElement.prototype.assignReplica = function(otherInput) {
-  if (!this._onChangeBound) {
-    this.addEventListener("change", this._replicate, false);
-    this._onChangeBound = true;
+Form.Element.Methods.assignReplica = function(element, otherInput) {
+  element = $(element);
+  if (!element._onChangeBound) {
+    Event.observe(element, "change", element._replicate, false);
+    element._onChangeBound = true;
   }
-  this.replica = otherInput;
+  element.replica = otherInput;
 }
 
-HTMLInputElement.prototype.valueAsDate = function () {
-  return this.value.asDate();
+Form.Element.Methods.valueAsDate = function(element) {
+  return $F(element).asDate();
 }
 
-HTMLInputElement.prototype.setValueAsDate = function(dateValue) {
-  if (!this.dateSeparator)
-    this._detectDateSeparator();
-  this.value = dateValue.stringWithSeparator(this.dateSeparator);
+Form.Element.Methods.setValueAsDate = function(element, dateValue) {
+  element = $(element);
+  if (!element.dateSeparator)
+    element._detectDateSeparator();
+  element.value = dateValue.stringWithSeparator(element.dateSeparator);
 }
 
-HTMLInputElement.prototype.updateShadowValue = function () {
-  this.setAttribute("shadow-value", this.value);
+Form.Element.Methods.updateShadowValue = function(element) {
+  element = $(element);
+  element.setAttribute("shadow-value", $F(element));
 }
 
-HTMLInputElement.prototype._detectDateSeparator = function() {
-  var date = this.value.split("/");
+Form.Element.Methods._detectDateSeparator = function(element) {
+  element = $(element);
+  var date = $F(element).split("/");
   if (date.length == 3)
-    this.dateSeparator = "/";
+    element.dateSeparator = "/";
   else
-    this.dateSeparator = "-";
+    element.dateSeparator = "-";
 }
 
-HTMLInputElement.prototype.valueAsShortDateString = function() {
+Form.Element.Methods.valueAsShortDateString = function(element) {
+  element = $(element);
   var dateStr = '';
-
-  if (!this.dateSeparator)
-    this._detectDateSeparator();
-
-  var date = this.value.split(this.dateSeparator);
-  if (this.dateSeparator == '/')
+  
+  if (!element.dateSeparator)
+    element._detectDateSeparator();
+  
+  var date = $F(element).split(element.dateSeparator);
+  if (element.dateSeparator == '/')
     dateStr += date[2] + date[1] + date[0];
   else
     dateStr += date[0] + date[1] + date[2];
-
+  
   return dateStr;
 }
 
-/* "select" is part of the inputs so it's included here */
-HTMLSelectElement.prototype._replicate = function() {
-  if (this.replica) {
-    this.replica.value = this.value;
-    var onReplicaChangeEvent = document.createEvent("UIEvents");
-    onReplicaChangeEvent.initEvent("change", true, true);
-    this.replica.dispatchEvent(onReplicaChangeEvent);
-  }
-}
-
-HTMLSelectElement.prototype.assignReplica = function(otherSelect) {
-  if (!this._onChangeBound) {
-    this.addEventListener("change", this._replicate, false);
-    this._onChangeBound = true;
-  }
-  this.replica = otherSelect;
-}
-
-HTMLSelectElement.prototype.updateShadowValue = function () {
-  this.setAttribute("shadow-value", this.value);
-}
+Element.addMethods();
index 0390497aee500e1cef1f1a5fbe1ea40d3eb91ff6..98a81bb1b9a2cab9da39ef3546746887733a801b 100644 (file)
@@ -1,28 +1,39 @@
-HTMLTableElement.prototype.getSelectedRows = function() {
-  var tbody = (this.getElementsByTagName('tbody'))[0];
+Element.addMethods({
+  getSelectedRows: function(element) {
+    element = $(element);
+    if (element.tagName == 'TABLE') {
+      var tbody = (element.getElementsByTagName('tbody'))[0];
+      
+      return tbody.getSelectedNodes();
+    }
+    else if (element.tagName == 'UL') {
+      return element.getSelectedNodes();
+    }
+  },
 
-  return tbody.getSelectedNodes();
-}
+  getSelectedRowsId: function(element) {
+    element = $(element);
+    if (element.tagName == 'TABLE') {
+      var tbody = (element.getElementsByTagName('tbody'))[0];
+      
+      return tbody.getSelectedNodesId();
+    }
+    else if (element.tagName == 'UL') {
+      return element.getSelectedNodesId();
+    }
+  },
 
-HTMLTableElement.prototype.getSelectedRowsId = function() {
-  var tbody = (this.getElementsByTagName('tbody'))[0];
-
-  return tbody.getSelectedNodesId();
-}
-
-HTMLTableElement.prototype.selectRowsMatchingClass = function(className) {
-  var tbody = (this.getElementsByTagName('tbody'))[0];
-  var nodes = tbody.childNodes;
-  for (var i = 0; i < nodes.length; i++) {
-    var node = nodes.item(i);
-    if (node instanceof HTMLElement
-        && node.hasClassName(className))
-      node.select();
+  selectRowsMatchingClass: function(element, className) {
+    element = $(element);
+    if (element.tagName == 'TABLE') {
+      var tbody = (element.getElementsByTagName('tbody'))[0];
+      var nodes = tbody.childNodes;
+      for (var i = 0; i < nodes.length; i++) {
+       var node = nodes.item(i);
+       if (node instanceof HTMLElement
+           && node.hasClassName(className))
+         node.select();
+      }
+    }
   }
-}
-
-HTMLTableElement.prototype.deselectAll = function() {
-  var nodes = this.getSelectedRows();
-  for (var i = 0; i < nodes.length; i++)
-    nodes[i].deselect();
-}
+}); // Element.addMethods
index 8b622fb3f1e43fcad07969d9905551a4ee1f813f..6e7b793b407b64f44a73adc7c734fcf8569bf5e5 100644 (file)
@@ -1,7 +1,7 @@
-HTMLUListElement.prototype.getSelectedRows = function() {
-  return this.getSelectedNodes();
-}
-
-HTMLUListElement.prototype.getSelectedRowsId = function() {
-  return this.getSelectedNodesId();
-}
+//HTMLUListElement.prototype.getSelectedRows = function() {
+//  return this.getSelectedNodes();
+//}
+//
+//HTMLUListElement.prototype.getSelectedRowsId = function() {
+//  return this.getSelectedNodesId();
+//}
index fc7649ab8ee4b01029e908035015d20cf3a83714..088a7f10af05981268be87f3fdc6991b7650dda4 100644 (file)
@@ -2,6 +2,15 @@ String.prototype.trim = function() {
   return this.replace(/(^\s+|\s+$)/g, '');
 }
 
+String.prototype.repeat = function(count) {
+   var newString = "";
+   for (var i = 0; i < count; i++) {
+      newString += this;
+   }
+
+   return newString;
+}
+
 String.prototype.capitalize = function() {
   return this.replace(/\w+/g,
                       function(a) {
diff --git a/UI/WebServerResources/MailerUI+dTree.js b/UI/WebServerResources/MailerUI+dTree.js
new file mode 100644 (file)
index 0000000..085b253
--- /dev/null
@@ -0,0 +1,42 @@
+var MailerUIdTreeExtension = {
+   elementCounter: 1,
+   folderIcons: { account: "tbtv_account_17x17.gif",
+                 inbox: "tbtv_inbox_17x17.gif",
+                 sent: "tbtv_sent_17x17.gif",
+                 draft: "tbtv_drafts_17x17.gif",
+                 trash: "tbtv_trash_17x17.gif" },
+   folderNames: { inbox: labels["InboxFolderName"],
+                 sent: labels["SentFolderName"],
+                 draft: labels["DraftsFolderName"],
+                 trash: labels["TrashFolderName"] },
+   _addFolderNode: function (parent, name, fullName, type) {
+      var icon = this.folderIcons[type];
+      if (icon)
+        icon = ResourcesURL + "/"  + icon;
+      else
+        icon = "";
+      var displayName = this.folderNames[type];
+      if (!displayName)
+        displayName = name;
+      this.add(this.elementCounter, parent, displayName, 1, '#', fullName,
+              type, '', '', icon, icon);
+      this.elementCounter++;
+   },
+   _addFolder: function (parent, folder) {
+      var thisCounter = this.elementCounter;
+      var fullName = "";
+      var currentFolder = folder;
+      while (currentFolder) {
+        fullName = "/" + currentFolder.name + fullName;
+        currentFolder = currentFolder.parentFolder;
+      }
+      this._addFolderNode(parent, folder.name, fullName, folder.type);
+      for (var i = 0; i < folder.children.length; i++)
+      this._addFolder(thisCounter, folder.children[i]);
+   },
+   addMailAccount: function (mailAccount) {
+      this._addFolder(0, mailAccount);
+   }
+};
+
+Object.extend(dTree.prototype, MailerUIdTreeExtension);
index 0e7f60d30d3d04f791b6c0d3990b060e8cd16929..7cef75b4ae99026b4314f660d05097a37e52b40f 100644 (file)
@@ -449,6 +449,10 @@ table.linked_attachment_meta
   font-style: italic;
 }
 
+DIV[datatype~="additional"] > A.node > SPAN.nodeName
+{ color: #777;
+  font-style: italic; }
+
 /* drag-n-drop */
 IMG.dragMessage
 {
index 075d020cec8be4a3b18e5c53f7b736881cf6c441..0deaf4c37ecce2630b40a441e1ad700e21dfe9f2 100644 (file)
@@ -1,9 +1,11 @@
 /* JavaScript for SOGoMail */
+var accounts = {};
+var mailboxTree;
 
 var currentMessages = new Array();
 var maxCachedMessages = 20;
 var cachedMessages = new Array();
-var currentMailbox = '';
+var currentMailbox = null;
 
 var usersRightsWindowHeight = 320;
 var usersRightsWindowWidth = 400;
@@ -299,7 +301,7 @@ function uixDeleteSelectedMessages(sender) {
       var rowId = rowIds[i].substr(4);
       /* send AJAX request (synchronously) */
 
-         var messageId = currentMailbox + "/" + rowId;
+      var messageId = currentMailbox + "/" + rowId;
       url = ApplicationBaseURL + messageId + "/trash?jsonly=1";
       http = createHTTPClient();
       http.open("GET", url, false /* not async */);
@@ -339,7 +341,7 @@ function moveMessages(rowIds, folder) {
 
       /* send AJAX request (synchronously) */
          
-         var messageId = currentMailbox + "/" + rowIds[i];
+      var messageId = currentMailbox + "/" + rowIds[i];
       url = ApplicationBaseURL + messageId + "/move?jsonly=1&tofolder=" + folder;
       http = createHTTPClient();
       http.open("GET", url, false /* not async */);
@@ -374,21 +376,36 @@ function onMenuDeleteMessage(event) {
 }
 
 function onMailboxTreeItemClick(event) {
-   var topNode = $("d");
+   var topNode = $("mailboxTree");
    var mailbox = this.parentNode.getAttribute("dataname");
 
-   if (topNode.selectedEntry) {
-      log ("deselecting");
+   if (topNode.selectedEntry)
       topNode.selectedEntry.deselect();
-   }
    this.select();
    topNode.selectedEntry = this;
 
-   if (this.parentNode.getAttribute("datatype") != "account")
+   var datatype = this.parentNode.getAttribute("datatype");
+   if (datatype == "account" || datatype == "additional") {
+      currentMailbox = mailbox;
+      $("messageContent").innerHTML = "";
+      var body = $("messageList").tBodies[0];
+      for (var i = body.rows.length - 1; i > 0; i--)
+        body.deleteRow(i);
+   }
+   else
       openMailbox(mailbox);
+   
    event.preventDefault();
 }
 
+function onMailboxMenuMove() {
+   window.alert("unimplemented");
+}
+
+function onMailboxMenuCopy() {
+   window.alert("unimplemented");
+}
+
 function _refreshWindowMailbox() {
    openMailbox(currentMailbox, true);
 }
@@ -397,7 +414,7 @@ function refreshMailbox() {
    var topWindow = getTopWindow();
    if (topWindow)
       topWindow._refreshWindowMailbox();
-   
+
    return false;
 }
 
@@ -476,11 +493,10 @@ function messageListCallback(http) {
       configureSortableTableHeaders();
    }
    else
-      log("ajax fuckage");
+      log("problem during ajax request");
 }
 
 function onMessageContextMenu(event) {
-   log("messagelistmenu");
    var menu = $('messageListMenu');
    Event.observe(menu, "hideMenu", onMessageContextMenuHide);
    popupMenu(event, "messageListMenu", this);
@@ -513,8 +529,6 @@ function onFolderMenuClick(event) {
    var onhide, menuName;
    
    var menutype = this.parentNode.getAttribute("datatype");
-   //   log("parentNode: " + this.parentNode.tagName);
-   //   log("menutype: " + menutype);
    if (menutype) {
       if (menutype == "inbox") {
         menuName = "inboxIconMenu";
@@ -533,17 +547,19 @@ function onFolderMenuClick(event) {
    Event.observe(menu, "hideMenu", onFolderMenuHide);
    popupMenu(event, menuName, this.parentNode);
 
-   var topNode = $('d');
+   var topNode = $("mailboxTree");
    if (topNode.selectedEntry)
       topNode.selectedEntry.deselect();
    if (topNode.menuSelectedEntry)
       topNode.menuSelectedEntry.deselect();
    topNode.menuSelectedEntry = this;
    this.select();
+
+   event.preventDefault();
 }
 
 function onFolderMenuHide(event) {
-   var topNode = $('d');
+   var topNode = $("mailboxTree");
 
    if (topNode.menuSelectedEntry) {
       topNode.menuSelectedEntry.deselect();
@@ -689,7 +705,7 @@ function messageCallback(http) {
       }
    }
    else
-      log ("ajax fuckage");
+      log("problem during ajax request");
 }
 
 function processMailboxMenuAction(mailbox) {
@@ -808,34 +824,14 @@ function expandUpperTree(node) {
         var id = currentNode.getAttribute("id");
         var number = parseInt(id.substr(2));
         if (number > 0) {
-           var cn = d.aNodes[number];
-           d.nodeStatus(1, number, cn._ls);
+           var cn = mailboxTree.aNodes[number];
+           mailboxTree.nodeStatus(1, number, cn._ls);
         }
       }
       currentNode = currentNode.parentNode;
    }
 }
 
-function initMailboxSelection(mailboxName) {
-   currentMailbox = mailboxName;
-   //   log("initMailboxSelection: " + mailboxName);
-   var tree = $("d");
-   var treeNodes = document.getElementsByClassName("dTreeNode", tree);
-   var i = 0;
-   while (i < treeNodes.length
-         && treeNodes[i].getAttribute("dataname") != currentMailbox)
-      i++;
-   if (i < treeNodes.length) {
-      //     log ("found mailbox");
-      var links = document.getElementsByClassName("node", treeNodes[i]);
-      if (tree.selectedEntry)
-        tree.selectedEntry.deselect();
-      links[0].select();
-      tree.selectedEntry = links[0];
-      expandUpperTree(links[0]);
-   }
-}
-
 function onHeaderClick(event) {
    if (document.messageListAjaxRequest) {
       document.messageListAjaxRequest.aborted = true;
@@ -851,7 +847,7 @@ function onHeaderClick(event) {
 }
 
 function onSearchFormSubmit() {
-   log ("search not implemented");
+   log("search not implemented");
 
    return false;
 }
@@ -888,8 +884,8 @@ var mailboxSpanDrop = function(data) {
 
 var plusSignEnter = function() {
    var nodeNr = parseInt(this.id.substr(2));
-   if (!d.aNodes[nodeNr]._io)
-   this.plusSignTimer = setTimeout("openPlusSign('" + nodeNr + "');", 1000);
+   if (!mailboxTree.aNodes[nodeNr]._io)
+     this.plusSignTimer = setTimeout("openPlusSign('" + nodeNr + "');", 1000);
 }
 
 var plusSignExit = function() {
@@ -900,8 +896,8 @@ var plusSignExit = function() {
 }
 
 function openPlusSign(nodeNr) {
-   d.nodeStatus(1, nodeNr, d.aNodes[nodeNr]._ls);
-   d.aNodes[nodeNr]._io = 1;
+   mailboxTree.nodeStatus(1, nodeNr, mailboxTree.aNodes[nodeNr]._ls);
+   mailboxTree.aNodes[nodeNr]._io = 1;
    this.plusSignTimer = null;
 }
 
@@ -915,14 +911,14 @@ var messageListGhost = function () {
    newDiv.ghostOffsetX = 10;
    newDiv.ghostOffsetY = 5;
 
-   var imgCode = '<img src="' + ResourcesURL + '/message-mail.png" />';
+   var newImg = document.createElement("img");
+   newImg.src = ResourcesURL + "/message-mail.png";
 
-   var current = this;
-   while (!current.getSelectedRows)
-   current = current.parentNode;
-   var count = current.getSelectedRows().length;
-   var text = imgCode + '<br />' + count + ' messages...';
-   newDiv.innerHTML = text;
+   var list = $("messageList");
+   var count = list.getSelectedRows().length;
+   newDiv.appendChild(newImg);
+   newDiv.appendChild(document.createElement("br"));
+   newDiv.appendChild(document.createTextNode(count + " messages..."));
 
    return newDiv;
 }
@@ -988,9 +984,9 @@ function configureDragHandles() {
 
 /* dnd */
 function initDnd() {
-   //   log ("MailerUI initDnd");
+   //   log("MailerUI initDnd");
 
-   var tree = $("d");
+   var tree = $("mailboxTree");
    if (tree) {
       var images = tree.getElementsByTagName("img");
       for (var i = 0; i < images.length; i++) {
@@ -1020,18 +1016,10 @@ function refreshContacts() {
 function openInbox(node) {
    var done = false;
    openMailbox(node.parentNode.getAttribute("dataname"));
-   var tree = $("d");
+   var tree = $("mailboxTree");
    tree.selectedEntry = node;
    node.select();
-   var currentNode = node.parentNode.parentNode;
-   while (!done) {
-      var number = currentNode.getAttribute("id").substr(2);
-      d.o(number);
-      if (number == "1")
-        done = true;
-      else
-        currentNode = currentNode.parentNode;
-   }
+   mailboxTree.o(1);
 }
 
 function configureSearchField() {
@@ -1047,62 +1035,321 @@ function configureSearchField() {
 function initMailer(event) {
    if (!document.body.hasClassName("popup")) {
       configureSearchField();
-      var inboxFound = false;
       configureMessageListEvents();
       initDnd();
-      var tree = $("d");
-      var nodes = document.getElementsByClassName("node", tree);
-      for (i = 0; i < nodes.length; i++) {
-        Event.observe(nodes[i], "click", onMailboxTreeItemClick);
-        Event.observe(nodes[i], "contextmenu", onFolderMenuClick);
-        if (!inboxFound
-            && nodes[i].parentNode.getAttribute("datatype") == "inbox") {
-           openInbox(nodes[i]);
-           inboxFound = true;
+      currentMailbox = "/" + accounts[0] + "/INBOX";
+      initMailboxTree();
+   }
+}
+
+function initMailboxTree() {
+   mailboxTree = new dTree("mailboxTree");
+   mailboxTree.config.folderLinks = true;
+   mailboxTree.config.hideRoot = true;
+
+   mailboxTree.icon.root = ResourcesURL + "/tbtv_account_17x17.gif";
+   mailboxTree.icon.folder = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
+   mailboxTree.icon.folderOpen = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
+   mailboxTree.icon.node = ResourcesURL + "/tbtv_leaf_corner_17x17.gif";
+   mailboxTree.icon.line = ResourcesURL + "/tbtv_line_17x17.gif";
+   mailboxTree.icon.join = ResourcesURL + "/tbtv_junction_17x17.gif";
+   mailboxTree.icon.joinBottom = ResourcesURL + "/tbtv_corner_17x17.gif";
+   mailboxTree.icon.plus = ResourcesURL + "/tbtv_plus_17x17.gif";
+   mailboxTree.icon.plusBottom = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
+   mailboxTree.icon.minus = ResourcesURL + "/tbtv_minus_17x17.gif";
+   mailboxTree.icon.minusBottom = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
+   mailboxTree.icon.nlPlus = ResourcesURL + "/tbtv_corner_plus_17x17.gif";
+   mailboxTree.icon.nlMinus = ResourcesURL + "/tbtv_corner_minus_17x17.gif";
+   mailboxTree.icon.empty = ResourcesURL + "/empty.gif";
+
+   mailboxTree.add(0, -1, '');
+
+   mailboxTree.pendingRequests = mailAccounts.length;
+   for (var i = 0; i < mailAccounts.length; i++) {
+      var url = ApplicationBaseURL + "/" + mailAccounts[i] + "/mailboxes";
+      triggerAjaxRequest(url, onLoadMailboxesCallback, mailAccounts[i]);
+   }
+}
+
+function updateMailboxTreeInPage() {
+   $("folderTreeContent").innerHTML = mailboxTree;
+
+   var inboxFound = false;
+   var tree = $("mailboxTree");
+   var nodes = document.getElementsByClassName("node", tree);
+   for (i = 0; i < nodes.length; i++) {
+      Event.observe(nodes[i], "click", onMailboxTreeItemClick.bindAsEventListener(nodes[i]));
+      Event.observe(nodes[i], "contextmenu", onFolderMenuClick.bindAsEventListener(nodes[i]));
+      if (!inboxFound
+         && nodes[i].parentNode.getAttribute("datatype") == "inbox") {
+        openInbox(nodes[i]);
+        inboxFound = true;
+      }
+   }
+}
+
+function mailboxMenuNode(type, name) {
+   var newNode = document.createElement("li");
+   var icon = MailerUIdTreeExtension.folderIcons[type];
+   if (!icon)
+      icon = "tbtv_leaf_corner_17x17.gif";
+   var image = document.createElement("img");
+   image.src = ResourcesURL + "/" + icon;
+   newNode.appendChild(image);
+   newNode.appendChild(document.createTextNode(" " + name));
+
+   return newNode;
+}
+
+function generateMenuForMailbox(mailbox, prefix, callback) {
+   var menuDIV = document.createElement("div");
+   menuDIV.addClassName("menu");
+   menuDIV.setAttribute("id", prefix + "Submenu");
+   var menu = document.createElement("ul");
+   menuDIV.appendChild(menu);
+
+   var callbacks = new Array();
+   if (mailbox.type != "account") {
+      var newNode = document.createElement("li");
+      newNode.mailbox = mailbox;
+      newNode.appendChild(document.createTextNode("coucou"));
+      menu.appendChild(newNode);
+      menu.appendChild(document.createElement("li"));
+      callbacks.push(callback);
+      callbacks.push("-");
+   }
+
+   var submenuCount = 0;
+   for (var i = 0; i < mailbox.children.length; i++) {
+      var child = mailbox.children[i];
+      var newNode = mailboxMenuNode(child.type, child.name);
+      menu.appendChild(newNode);
+      if (child.children.length > 0) {
+        var newPrefix = prefix + submenuCount;
+        var newSubmenu = generateMenuForMailbox(child,
+                                                newPrefix,
+                                                callback);
+        document.body.appendChild(newSubmenu);
+        callbacks.push(newPrefix + "Submenu");
+        submenuCount++;
+      }
+      else {
+        newNode.mailbox = child;
+        callbacks.push(callback);
+      }
+   }
+   initMenu(menuDIV, callbacks);
+
+   return menuDIV;
+}
+
+function updateMailboxMenus() {
+   var mailboxActions = { move: onMailboxMenuMove,
+                         copy: onMailboxMenuCopy };
+
+   for (key in mailboxActions) {
+      var menuId = key + "MailboxMenu";
+      var menuDIV = $(menuId);
+      if (menuDIV)
+        menuDIV.parentNode.removeChild(menuDIV);
+      menuDIV = document.createElement("div");
+      menuDIV.addClassName("menu");
+      menuDIV.setAttribute("id", menuId);
+      var menu = document.createElement("ul");
+      menuDIV.appendChild(menu);
+
+      var submenuIds = new Array();
+      for (var i = 0; i < mailAccounts.length; i++) {
+        var menuEntry = mailboxMenuNode("account", mailAccounts[i]);
+        menu.appendChild(menuEntry);
+        var mailbox = accounts[mailAccounts[i]];
+        var newSubmenu = generateMenuForMailbox(mailbox,
+                                                key, mailboxActions[key]);
+        document.body.appendChild(newSubmenu);
+        submenuIds.push(newSubmenu.getAttribute("id"));
+      }
+      initMenu(menuDIV, submenuIds);
+
+      document.body.appendChild(menuDIV);
+   }
+}
+
+function onLoadMailboxesCallback(http) {
+   if (http.readyState == 4
+       && http.status == 200) {
+      var newAccount = buildMailboxes(http.callbackData,
+                                     http.responseText);
+      accounts[http.callbackData] = newAccount;
+      mailboxTree.addMailAccount(newAccount);
+      mailboxTree.pendingRequests--;
+      if (!mailboxTree.pendingRequests) {
+        updateMailboxTreeInPage();
+        updateMailboxMenus();
+      }
+  }
+
+//       var tree = $("mailboxTree");
+//       var treeNodes = document.getElementsByClassName("dTreeNode", tree);
+//       var i = 0;
+//       while (i < treeNodes.length
+//          && treeNodes[i].getAttribute("dataname") != currentMailbox)
+//      i++;
+//       if (i < treeNodes.length) {
+//      //     log("found mailbox");
+//      var links = document.getElementsByClassName("node", treeNodes[i]);
+//      if (tree.selectedEntry)
+//         tree.selectedEntry.deselect();
+//      links[0].select();
+//      tree.selectedEntry = links[0];
+//      expandUpperTree(links[0]);
+//       }
+}
+
+function buildMailboxes(accountName, encoded) {
+   var account = new Mailbox("account", accountName);
+   var data = encoded.evalJSON(true);
+   for (var i = 0; i < data.length; i++) {
+      var currentNode = account;
+      var names = data[i].path.split("/");
+      for (var j = 1; j < (names.length - 1); j++) {
+        var node = currentNode.findMailboxByName(names[j]);
+        if (!node) {
+           node = new Mailbox("additional", names[j]);
+           currentNode.addMailbox(node);
         }
+        currentNode = node;
+      }
+      var basename = names[names.length-1];
+      var leaf = currentNode.findMailboxByName(basename);
+      if (leaf)
+        leaf.type = data[i].type;
+      else {
+        leaf = new Mailbox(data[i].type, basename);
+        currentNode.addMailbox(leaf);
       }
    }
+
+   return account;
+}
+
+function onMenuCreateFolder(event) {
+   var name = window.prompt(labels["Name :"].decodeEntities(), "");
+   if (name && name.length > 0) {
+      var folderID = document.menuTarget.getAttribute("dataname");
+      var urlstr = URLForFolderID(folderID) + "/createFolder?name=" + name;
+      triggerAjaxRequest(urlstr, folderOperationCallback);
+   }
+}
+
+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");
+      var urlstr = URLForFolderID(folderID) + "/renameFolder?name=" + name;
+      triggerAjaxRequest(urlstr, folderOperationCallback);
+   }
+}
+
+function onMenuDeleteFolder(event) {
+   var answer = window.confirm(labels["Do you really want to move this folder into the trash ?"].decodeEntities());
+   if (answer) {
+      var folderID = document.menuTarget.getAttribute("dataname");
+      var urlstr = URLForFolderID(folderID) + "/deleteFolder";
+      triggerAjaxRequest(urlstr, folderOperationCallback);
+   }
 }
 
-function initializeMenus() {
-   menus["menuIds"] = new Array("accountIconMenu", "inboxIconMenu",
-                               "trashIconMenu", "mailboxIconMenu",
-                               "addressMenu", "messageListMenu",
-                               "messageContentMenu", "label-menu",
-                               "mark-menu");
-   menus["accountIconMenu"] = new Array(null, null, null, null, null, null,
-                                       null, null, null, onMenuSharing);
-   menus["inboxIconMenu"] = new Array(null, null, null, "-", null, null,
-                                     null, "-", null, onMenuSharing);
-   menus["trashIconMenu"] = new Array(null, null, null, "-", null, null, null,
-                                     null, "-", null, onMenuSharing);
-   menus["mailboxIconMenu"] = new Array(null, null, null, "-", null, null,
-                                       null, null, null, "-", null,
+function onMenuEmptyTrash(event) {
+   var folderID = document.menuTarget.getAttribute("dataname");
+   var urlstr = URLForFolderID(folderID) + "/emptyTrash";
+   triggerAjaxRequest(urlstr, folderOperationCallback);
+}
+
+function folderOperationCallback(http) {
+   if (http.readyState == 4
+       && http.status == 204)
+      initMailboxTree();
+   else
+      window.alert(labels["Operation failed"].decodeEntities());
+}
+
+function getMenus() {
+   var menus = {}
+   menus["accountIconMenu"] = new Array(null, null, onMenuCreateFolder, null,
+                                       null, null);
+   menus["inboxIconMenu"] = new Array(null, null, null, "-", null,
+                                     onMenuCreateFolder, null, "-", null,
+                                     onMenuSharing);
+   menus["trashIconMenu"] = new Array(null, null, null, "-", null,
+                                     onMenuCreateFolder, null,
+                                     onMenuEmptyTrash, "-", null,
+                                     onMenuSharing);
+   menus["mailboxIconMenu"] = new Array(null, null, null, "-", null,
+                                       onMenuCreateFolder,
+                                       onMenuRenameFolder,
+                                       null, onMenuDeleteFolder, "-", null,
                                        onMenuSharing);
    menus["addressMenu"] = new Array(newContactFromEmail, newEmailTo, null);
    menus["messageListMenu"] = new Array(onMenuOpenMessage, "-",
                                        onMenuReplyToSender,
                                        onMenuReplyToAll,
                                        onMenuForwardMessage, null,
-                                       "-", "mailboxes-menu",
-                                       "mailboxes-menu", "label-menu",
+                                       "-", "moveMailboxMenu",
+                                       "copyMailboxMenu", "label-menu",
                                        "mark-menu", "-", null, null,
                                        null, onMenuDeleteMessage);
    menus["messageContentMenu"] = new Array(onMenuReplyToSender,
                                           onMenuReplyToAll,
                                           onMenuForwardMessage,
-                                          null,
-                                          "mailboxes-menu",
-                                          "mailboxes-menu",
+                                          null, "moveMailboxMenu",
+                                          "copyMailboxMenu",
                                           "-", "label-menu", "mark-menu",
-                                           "-", null, null, null,
+                                          "-",
+                                          null, null, null,
                                           onMenuDeleteMessage);
    menus["label-menu"] = new Array(null, "-", null , null, null, null , null,
                                   null);
    menus["mark-menu"] = new Array(null, null, null, null, "-", null, "-",
                                  null, null, null);
 
-   initMenus();
+   return menus;
 }
 
 Event.observe(window, "load", initMailer);
+
+function Mailbox(type, name) {
+   this.type = type;
+   this.name = name;
+   this.parentFolder = null;
+   this.children = new Array();
+   return this;
+}
+
+Mailbox.prototype.dump = function(indent) {
+   if (!indent)
+     indent = 0;
+   log(" ".repeat(indent) + this.name);
+   for (var i = 0; i < this.children.length; i++) {
+      this.children[i].dump(indent + 2);
+   }
+}
+
+Mailbox.prototype.findMailboxByName = function(name) {
+   var mailbox = null;
+
+   var i = 0;
+   while (!mailbox && i <this.children.length)
+      if (this.children[i].name == name)
+        mailbox = this.children[i];
+      else
+        i++;
+
+   return mailbox;
+}
+
+Mailbox.prototype.addMailbox = function(mailbox) {
+   mailbox.parentFolder = this;
+   this.children.push(mailbox);
+}
index 83adb8d3d2354dfecf9abeed90ee143b79dfc7d8..1056e904463aa3b647740dbbda955c059cc09f53 100644 (file)
@@ -159,7 +159,7 @@ document.DNDManager = {
       document.DNDManager.currentDndOperation = null;
     }
   },
-  currentDndOperation: null,
+  currentDndOperation: null
 }
 
 /* DNDOperation */
index f1501bca46ff0d530d40ac7e5ad5f1cddd9146bc..bcd4b1942acb215b9e7ad8fa8352a2b43997ed31 100644 (file)
@@ -11,9 +11,12 @@ var SOGoDragHandlesInterface = {
   rightBlock: null,
   upperBlock: null,
   lowerBlock: null,
+  startHandleDraggingBinded: null,
+  stopHandleDraggingBinded: null,
+  moveBinded: null,
   bind: function () {
-    this.addEventListener("mousedown", this.startHandleDragging, false);
-    this.onmousedown = function() { return false }
+    this.startHandleDraggingBound = this.startHandleDragging.bindAsEventListener(this);
+    Event.observe(this, "mousedown", this.startHandleDraggingBound, false);
   },
   _determineType: function () {
     if (this.leftBlock && this.rightBlock)
@@ -45,29 +48,16 @@ var SOGoDragHandlesInterface = {
         this.origLower = this.lowerBlock.offsetTop - 5;
         document.body.style.cursor = "n-resize";
       }
-      document._currentDragHandle = this;
-      if (document.addEventListener) {
-       document.addEventListener("mouseup", this.documentStopHandleDragging, true);
-       document.addEventListener("mousemove", this.documentMove, true);
-      } else if (window.addEventListener) {
-       window.addEventListener("mouseup", this.documentStopHandleDragging, true);
-       window.addEventListener("mousemove", this.documentMove, true);
-      }
+      this.stopHandleDraggingBound = this.stopHandleDragging.bindAsEventListener(this);
+      Event.observe(document.body, "mouseup", this.stopHandleDraggingBound, true);
+      this.moveBound = this.move.bindAsEventListener(this);
+      Event.observe(document.body, "mousemove", this.moveBound, true);
       this.move(event);
       event.cancelBubble = true;
     }
 
     return false;
   },
-  documentStopHandleDragging: function (event) {
-    var handle = document._currentDragHandle;
-    return handle.stopHandleDragging(event);
-  },
-  documentMove: function (event) {
-    var handle = document._currentDragHandle;
-    if (!handle) return false;
-    return handle.move(event);
-  },
   stopHandleDragging: function (event) {
     if (!this.dhType)
       this._determineType();
@@ -83,17 +73,12 @@ var SOGoDragHandlesInterface = {
       this.upperBlock.style.height = (this.origUpper + deltaY - delta) + 'px';
     }
  
-    if (window.addEventListener) {
-      window.removeEventListener("mouseup", this.documentStopHandleDragging, true);
-      window.removeEventListener("mousemove", this.documentMove, true);      
-    } else if (document.addEventListener) {
-      document.removeEventListener("mouseup", this.documentStopHandleDragging, true);
-      document.removeEventListener("mousemove", this.documentMove, true);
-    }
+    Event.stopObserving(document.body, "mouseup", this.stopHandleDraggingBound, true);
+    Event.stopObserving(document.body, "mousemove", this.moveBound, true);
+    
     document.body.setAttribute('style', '');
-
+    
     this.move(event);
-    document._currentDragHandle = null;
     event.cancelBubble = true;
 
     return false;
@@ -150,4 +135,3 @@ var SOGoDragHandlesInterface = {
   }
 
 };
-
index ade37a731b7f7e1e0139aaac74c1c7072716c074..92f4c6e57dd2ac875abf4179373f1851fbd4209a 100644 (file)
@@ -297,7 +297,6 @@ DIV#calendarView A
 TABLE#appointmentsList
 { display: block;
   position: relative;
-  height: 100%;
   width: 100%; }
 
 TABLE#appointmentsList td.tbtv_subject_headercell,
index 4c902a36923f954277328916a4660f1e0d6d0e1c..3070c492316b0137b30bc5560fca6ef9e4866548 100644 (file)
@@ -230,7 +230,7 @@ function displayAppointment(event) {
   _editEventId(this.getAttribute("aptCName"),
                this.getAttribute("owner"));
 
-  event.preventDefault();
+  preventDefault(event);
   event.stopPropagation();
   event.cancelBubble = true;
   event.returnValue = false;
@@ -314,8 +314,7 @@ function appointmentsListCallback(http) {
     sortKey = params["sort"];
     sortOrder = params["desc"];
     var list = $("appointmentsList");
-    list.addEventListener("selectionchange",
-                          onAppointmentsSelectionChange, true);
+    Event.observe(list, "selectionchange", onAppointmentsSelectionChange.bindAsEventListener(list), true);
     configureSortableTableHeaders();
   }
   else
@@ -332,8 +331,7 @@ function tasksListCallback(http) {
     var scroll = list.scrollTop;
     div.innerHTML = http.responseText;
     list = $("tasksList");
-    list.addEventListener("selectionchange",
-                          onTasksSelectionChange, true);
+    Event.observe(list, "selectionchange", onTasksSelectionChange.bindAsEventListener(list), true);
     list.scrollTop = scroll;
     if (http.callbackData) {
       var selectedNodesId = http.callbackData;
@@ -471,7 +469,7 @@ function scrollDayView(hour) {
     rowNumber = 8;
 
   var daysView = $("daysView");
-  var hours = daysView.childNodesWithTag("div")[0].childNodesWithTag("div");
+  var hours = $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
   if (hours.length > 0)
     daysView.parentNode.scrollTop = hours[rowNumber + 1].offsetTop;
 }
@@ -486,7 +484,7 @@ function onClickableCellsDblClick(event) {
 function calendarDisplayCallback(http) {
   var div = $("calendarView");
 
-//   log ("calendardisplaycallback: " + div);
+  //log ("calendarDisplayCallback: " + div);
   if (http.readyState == 4
       && http.status == 200) {
     document.dayDisplayAjaxRequest = null;
@@ -503,29 +501,27 @@ function calendarDisplayCallback(http) {
       contentView = $("calendarContent");
     else {
       scrollDayView(hour);
-//       log("cbtest1");
       contentView = $("daysView");
     }
     var appointments = document.getElementsByClassName("appointment", contentView);
     for (var i = 0; i < appointments.length; i++) {
-      appointments[i].addEventListener("mousedown", listRowMouseDownHandler, true);
-      appointments[i].addEventListener("click", onCalendarSelectAppointment, false);
-      appointments[i].addEventListener("dblclick", displayAppointment, true);
+      Event.observe(appointments[i], "mousedown",  listRowMouseDownHandler);
+      Event.observe(appointments[i], "click",  onCalendarSelectAppointment.bindAsEventListener(appointments[i]));
+      Event.observe(appointments[i], "dblclick", displayAppointment.bindAsEventListener(appointments[i]));
     }
     var days = document.getElementsByClassName("day", contentView);
     if (currentView == "monthview")
       for (var i = 0; i < days.length; i++) {
-        days[i].addEventListener("click", onCalendarSelectDay, true);
-        days[i].addEventListener("dblclick", onClickableCellsDblClick, false);
+        Event.observe(days[i], "click",  onCalendarSelectDay.bindAsEventListener(days[i]));
+        Event.observe(days[i], "dblclick",  onClickableCellsDblClick.bindAsEventListener(days[i]));
       }
     else
       for (var i = 0; i < days.length; i++) {
-        days[i].addEventListener("click", onCalendarSelectDay, false);
+        Event.observe(days[i], "click",  onCalendarSelectDay.bindAsEventListener(days[i]));
         var clickableCells = document.getElementsByClassName("clickableHourCell",
                                                              days[i]);
         for (var j = 0; j < clickableCells.length; j++)
-          clickableCells[j].addEventListener("dblclick",
-                                             onClickableCellsDblClick, false);
+          Event.observe(clickableCells[j], "dblclick", onClickableCellsDblClick.bindAsEventListener(clickableCells[j]));
       }
 //     log("cbtest1");
   }
@@ -559,7 +555,7 @@ function onAppointmentContextMenu(event, element) {
 
   var menu = $("appointmentsListMenu");
 
-  menu.addEventListener("hideMenu", onAppointmentContextMenuHide, false);
+  Event.observe(menu, "hideMenu",  onAppointmentContextMenuHide);
   popupMenu(event, "appointmentsListMenu", element);
 
   var topNode = $("appointmentsList");
@@ -631,7 +627,7 @@ function onHeaderClick(event) {
 //   log("onHeaderClick: " + this.link);
   _loadAppointmentHref(this.link);
 
-  event.preventDefault();
+  preventDefault(event);
 }
 
 function refreshAppointments() {
@@ -660,7 +656,8 @@ function onListFilterChange() {
 }
 
 function onAppointmentClick(event) {
-  var node = event.target.getParentWithTagName("tr");
+  var target = getTarget(event);
+  var node = target.getParentWithTagName("tr");
   var day = node.getAttribute("day");
   var hour = node.getAttribute("hour");
 
@@ -861,7 +858,7 @@ function updateCalendarStatus(event) {
 
   var nodes = $("calendarList").childNodesWithTag("li");
   for (var i = 0; i < nodes.length; i++) {
-    var input = nodes[i].childNodesWithTag("input")[0];
+    var input = $(nodes[i]).childNodesWithTag("input")[0];
     if (input.checked) {
        var folderId = nodes[i].getAttribute("id");
        var elems = folderId.split(":");
@@ -924,10 +921,10 @@ function calendarEntryCallback(http) {
       input.disabled = disabled;
       if (disabled) {
         input.checked = false;
-        entry.addClassName("denied");
+        $(entry).addClassName("denied");
       }
       else
-        entry.removeClassName("denied");
+        $(entry).removeClassName("denied");
    }
 }
 
@@ -985,11 +982,9 @@ function browseURL(anchor, event) {
   return false;
 }
 
-function initializeMenus() {
-   menus["menuIds"] = new Array("monthListMenu", "yearListMenu",
-                               "appointmentsListMenu",
-                               "calendarsMenu",
-                               "searchMenu");
+function getMenus() {
+   var menus = {};
+
    var dateMenu = new Array();
    for (var i = 0; i < 12; i++)
       dateMenu.push(onMonthMenuItemClick);
@@ -1009,10 +1004,7 @@ function initializeMenus() {
                                      null, "-", onMenuSharing);
    menus["searchMenu"] = new Array(setSearchCriteria);
 
-   initMenus();
-   var selector = $("calendarSelector");
-   if (selector)
-      selector.attachMenu("calendarsMenu");
+   return menus;
 }
 
 function onMenuSharing(event) {
@@ -1052,21 +1044,20 @@ function initCalendarSelector() {
   var list = $("calendarList").childNodesWithTag("li");
   for (var i = 0; i < list.length; i++) {
     var input = list[i].childNodesWithTag("input")[0];
-    input.addEventListener("change", updateCalendarStatus, false);
-    list[i].addEventListener("mousedown", listRowMouseDownHandler, false);
-    list[i].addEventListener("click", onRowClick, false);
-//     list[i].addEventListener("contextmenu", onContactFoldersContextMenu, false);
+    Event.observe(input, "change", updateCalendarStatus.bindAsEventListener(input));
+    Event.observe(list[i], "mousedown", listRowMouseDownHandler);
+    Event.observe(list[i], "click", onRowClick);
   }
 
   var links = $("calendarSelectorButtons").childNodesWithTag("a");
-  links[0].addEventListener("click", onCalendarAdd, false);
-  links[1].addEventListener("click", onCalendarRemove, false);
+  Event.observe(links[0], "click",  onCalendarAdd);
+  Event.observe(links[1], "click",  onCalendarRemove);
 }
 
 function onCalendarAdd(event) {
    openUserFolderSelector(onFolderSubscribeCB, "calendar");
 
-   event.preventDefault();
+   preventDefault(event);
 }
 
 function appendCalendar(folderName, folder) {
@@ -1076,20 +1067,20 @@ function appendCalendar(folderName, folder) {
    log ("color: " + color);
    var li = document.createElement("li");
    li.setAttribute("id", folder);
-   li.addEventListener("mousedown", listRowMouseDownHandler, false);
-   li.addEventListener("click", onRowClick, false);
+   Event.observe(li, "mousedown",  listRowMouseDownHandler);
+   Event.observe(li, "click",  onRowClick);
    var checkBox = document.createElement("input");
    checkBox.addClassName("checkBox");
    checkBox.type = "checkbox";
-   checkBox.addEventListener("change", updateCalendarStatus, false);
+   Event.observe(checkBox, "change",  updateCalendarStatus);
    li.appendChild(checkBox);
    li.appendChild(document.createTextNode(" "));
    var colorBox = document.createElement("div");
    colorBox.appendChild(document.createTextNode("OO"));
    colorBox.addClassName("colorBox");
    if (color) {
-      colorBox.style.color = color + ";";
-      colorBox.style.backgroundColor = color + ";";
+     colorBox.setStyle({ color: color,
+                        backgroundColor: color });
    }
    li.appendChild(colorBox);
    li.appendChild(document.createTextNode(" " + folderName));
@@ -1130,24 +1121,27 @@ function onCalendarRemove(event) {
      }
   }
 
-  event.preventDefault();
+  preventDefault(event);
 }
 
 function configureSearchField() {
    var searchValue = $("searchValue");
 
-   searchValue.addEventListener("mousedown", onSearchMouseDown, false);
-   searchValue.addEventListener("click", popupSearchMenu, false);
-   searchValue.addEventListener("blur", onSearchBlur, false);
-   searchValue.addEventListener("focus", onSearchFocus, false);
-   searchValue.addEventListener("keydown", onSearchKeyDown, false);
+   Event.observe(searchValue, "mousedown",  onSearchMouseDown.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "click",  popupSearchMenu.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "blur",  onSearchBlur.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "focus",  onSearchFocus.bindAsEventListener(searchValue));
+   Event.observe(searchValue, "keydown",  onSearchKeyDown.bindAsEventListener(searchValue));
 }
 
 function initCalendars() {
    if (!document.body.hasClassName("popup")) {
       initCalendarSelector();
       configureSearchField();
+      var selector = $("calendarSelector");
+      if (selector)
+        selector.attachMenu("calendarsMenu");
    }
 }
 
-window.addEventListener("load", initCalendars, false);
+addEvent(window, 'load', initCalendars);
index 496c68bfd0d81c62aa44a64eb95b3fd66607adcc..9995a1ba723ae00ba35f97b34ffe50f4764a1eb3 100644 (file)
@@ -248,7 +248,7 @@ this.onAdjustEndTime = function(event) {
 this.initTimeWidgets = function (widgets) {
   this.timeWidgets = widgets;
 
-  widgets['start']['date'].addEventListener("change", this.onAdjustEndTime, false);
-  widgets['start']['hour'].addEventListener("change", this.onAdjustEndTime, false);
-  widgets['start']['minute'].addEventListener("change", this.onAdjustEndTime, false);
+  Event.observe(widgets['start']['date'], "change", this.onAdjustEndTime, false);
+  Event.observe(widgets['start']['hour'], "change", this.onAdjustEndTime, false);
+  Event.observe(widgets['start']['minute'], "change", this.onAdjustEndTime, false);
 }
index 2735ebb078d8aeede4fa2159f8fb30c1e4a77fe7..ea67f8e2f2b24a1e1b9d13941729e1f2eff9d6e4 100644 (file)
@@ -22,7 +22,7 @@ function onContactKeydown(event) {
     while (!(row instanceof HTMLTableRowElement))
       row = row.nextSibling;
     this.blur();
-    var input = row.cells[0].childNodesWithTag("input")[0];
+    var input = $(row.cells[0]).childNodesWithTag("input")[0];
     if (input.readOnly)
       newAttendee(null);
     else {
@@ -111,7 +111,7 @@ function resetFreeBusyZone() {
   var table = $("freeBusy");
   var row = table.tHead.rows[2];
   for (var i = 1; i < row.cells.length; i++) {
-    var nodes = row.cells[i].childNodesWithTag("span");
+    var nodes = $(row.cells[i]).childNodesWithTag("span");
     for (var j = 0; j < nodes.length; j++)
       nodes[j].removeClassName("busy");
   }
@@ -165,7 +165,7 @@ function redisplayFreeBusyZone() {
   var currentCellNbr = stHour - 7;
   var currentCell = row.cells[currentCellNbr];
   var currentSpanNbr = stMinute;
-  var spans = currentCell.childNodesWithTag("span");
+  var spans = $(currentCell).childNodesWithTag("span");
   resetFreeBusyZone();
   while (deltaSpans > 0) {
     var currentSpan = spans[currentSpanNbr];
@@ -175,7 +175,7 @@ function redisplayFreeBusyZone() {
       currentSpanNbr = 0;
       currentCellNbr++;
       currentCell = row.cells[currentCellNbr];
-      spans = currentCell.childNodesWithTag("span");
+      spans = $(currentCell).childNodesWithTag("span");
     }
     deltaSpans--;
   }
@@ -185,15 +185,16 @@ function newAttendee(event) {
   var table = $("freeBusy");
   var tbody = table.tBodies[0];
   var model = tbody.rows[tbody.rows.length - 1];
-  var newAttendeeRow = tbody.rows[tbody.rows.length - 2]
+  var newAttendeeRow = tbody.rows[tbody.rows.length - 2];
   var newRow = model.cloneNode(true);
-  var input = newRow.cells[0].childNodesWithTag("input")[0];
-  input.setAttribute("autocomplete", "off");
   newRow.setAttribute("class", "");
   tbody.insertBefore(newRow, newAttendeeRow);
+  //table.tBodies[0].appendChild(newRow);
+  var input = $(newRow.cells[0]).childNodesWithTag("input")[0];
+  input.setAttribute("autocomplete", "off");
   input.serial = "pouet";
-  input.addEventListener("blur", checkAttendee, false);
-  input.addEventListener("keydown", onContactKeydown, false);
+  Event.observe(input, "blur", checkAttendee.bindAsEventListener(input));
+  Event.observe(input, "keydown", onContactKeydown.bindAsEventListener(input));
   input.focus();
   input.focussed = true;
 }
@@ -259,7 +260,7 @@ function setSlot(tds, nbr, status) {
   if (tdnbr > 7 && tdnbr < 19) {
     var i = (days * 11 + tdnbr - 7);
     var td = tds[i];
-    var spans = td.childNodesWithTag("span");
+    var spans = $(td).childNodesWithTag("span");
     if (status == '2')
       spans[spannbr].addClassName("maybe-busy");
     else
@@ -295,11 +296,11 @@ function resetAttendeesValue() {
       currentInput.setAttribute("uid", null);
     }
     currentInput.setAttribute("autocomplete", "off");
-    currentInput.addEventListener("keydown", onContactKeydown, false);
-    currentInput.addEventListener("blur", checkAttendee, false);
+    Event.observe(currentInput, "keydown", onContactKeydown.bindAsEventListener(currentInput), false);
+    Event.observe(currentInput, "blur", checkAttendee.bindAsEventListener(currentInput), false);
   }
   inputs[inputs.length - 2].setAttribute("autocomplete", "off");
-  inputs[inputs.length - 2].addEventListener("click", newAttendee, false);
+  Event.observe(inputs[inputs.length - 2], "click", newAttendee, false);
 }
 
 function resetAllFreeBusys() {
@@ -317,18 +318,18 @@ function initializeWindowButtons() {
    var okButton = $("okButton");
    var cancelButton = $("cancelButton");
 
-   okButton.addEventListener("click", onEditorOkClick, false);
-   cancelButton.addEventListener("click", onEditorCancelClick, false);
+   Event.observe(okButton, "click", onEditorOkClick, false);
+   Event.observe(cancelButton, "click", onEditorCancelClick, false);
 
    var buttons = $("freeBusyViewButtons").childNodesWithTag("a");
    for (var i = 0; i < buttons.length; i++)
-      buttons[i].addEventListener("click", listRowMouseDownHandler, false);
+     Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
    buttons = $("freeBusyZoomButtons").childNodesWithTag("a");
    for (var i = 0; i < buttons.length; i++)
-      buttons[i].addEventListener("click", listRowMouseDownHandler, false);
+     Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
    buttons = $("freeBusyButtons").childNodesWithTag("a");
    for (var i = 0; i < buttons.length; i++)
-      buttons[i].addEventListener("click", listRowMouseDownHandler, false);
+     Event.observe(buttons[i], "click", listRowMouseDownHandler, false);
 }
 
 function onEditorOkClick(event) {
@@ -398,14 +399,13 @@ function initializeTimeWidgets() {
    synchronizeWithParent("startTime", "startTime");
    synchronizeWithParent("endTime", "endTime");
 
-   $("startTime_date").addEventListener("change", onTimeDateWidgetChange, false);
-   $("startTime_time_hour").addEventListener("change", onTimeWidgetChange, false);
-   $("startTime_time_minute").addEventListener("change", onTimeWidgetChange,
-                                              false);
+   Event.observe($("startTime_date"), "change", onTimeDateWidgetChange, false);
+   Event.observe($("startTime_time_hour"), "change", onTimeWidgetChange, false);
+   Event.observe($("startTime_time_minute"), "change", onTimeWidgetChange, false);
 
-   $("endTime_date").addEventListener("change", onTimeDateWidgetChange, false);
-   $("endTime_time_hour").addEventListener("change", onTimeWidgetChange, false);
-   $("endTime_time_minute").addEventListener("change", onTimeWidgetChange, false);
+   Event.observe($("endTime_date"), "change", onTimeDateWidgetChange, false);
+   Event.observe($("endTime_time_hour"), "change", onTimeWidgetChange, false);
+   Event.observe($("endTime_time_minute"), "change", onTimeWidgetChange, false);
 }
 
 function onTimeWidgetChange() {
@@ -462,7 +462,7 @@ function prepareTableHeaders() {
         var header3 = document.createElement("th");
         for (var span = 0; span < 4; span++) {
            var spanElement = document.createElement("span");
-           spanElement.addClassName("freeBusyZoneElement");
+           $(spanElement).addClassName("freeBusyZoneElement");
            header3.appendChild(spanElement);
         }
         rows[2].appendChild(header3);
index beeac618a103905469d10bda89d9be00a677c05a..a490e25adb86c8d34a02c39fa6ca68f151ddfa14 100644 (file)
@@ -25,14 +25,14 @@ function onPopupUrlWindow(event) {
       if (documentHref.childNodes.length > 0) {
         documentHref.childNodes[0].nodeValue = newUrl;
         if (newUrl.length > 0)
-           documentLabel.style.display = "block;";
+           documentLabel.setStyle({ display: "block" });
         else
-           documentLabel.style.display = "none;";
+           documentLabel.setStyle({ display: "none" });
       }
       else {
         documentHref.appendChild(document.createTextNode(newUrl)); 
         if (newUrl.length > 0)
-           documentLabel.style.display = "block;";
+           documentLabel.setStyle({ display: "block" });
       }
       urlInput.value = newUrl;
    }
@@ -88,10 +88,10 @@ function refreshAttendees() {
 
    if (attendeesNames.value.length > 0) {
       attendeesHref.appendChild(document.createTextNode(attendeesNames.value));
-      attendeesLabel.style.display = "block;";
+      attendeesLabel.setStyle({ display: "block" });
    }
    else
-      attendeesLabel.style.display = "none;";
+      attendeesLabel.setStyle({ display: "none" });
 }
 
 function initializeAttendeesHref() {
@@ -101,10 +101,9 @@ function initializeAttendeesHref() {
 
    attendeesHref.addEventListener("click", onPopupAttendeesWindow, false);
    if (attendeesNames.value.length > 0) {
-      attendeesHref.style.textDecoration = "underline;";
-      attendeesHref.style.color = "#00f;";
+      attendeesHref.setStyle({ textDecoration: "underline", color: "#00f" });
       attendeesHref.appendChild(document.createTextNode(attendeesNames.value));
-      attendeesLabel.style.display = "block;";
+      attendeesLabel.setStyle({ display: "block" });
    }
 }
 
@@ -114,11 +113,10 @@ function initializeDocumentHref() {
    var documentUrl = $("url");
 
    documentHref.addEventListener("click", onPopupDocumentWindow, false);
-   documentHref.style.textDecoration = "underline;";
-   documentHref.style.color = "#00f;";
+   documentHref.setStyle({ textDecoration: "underline", color: "#00f" });
    if (documentUrl.value.length > 0) {
       documentHref.appendChild(document.createTextNode(documentUrl.value));
-      documentLabel.style.display = "block;";
+      documentLabel.setStyle({ display: "block" });
    }
 
    var changeUrlButton = $("changeUrlButton");
index 86bec0685edd09f5692c580f270551e268e92c77..7c67eb7bb6f45929872aec69848428f76f3323e0 100644 (file)
@@ -1,6 +1,6 @@
 var contactSelectorAction = 'calendars-contacts';
 
-window.addEventListener("load", onTaskEditorLoad, false);
+addEvent(window, 'DOMContentLoaded', onTaskEditorLoad);
 
 function uixEarlierDate(date1, date2) {
   // can this be done in a sane way?
@@ -249,9 +249,9 @@ this.onAdjustDueTime = function(event) {
 this.initTimeWidgets = function (widgets) {
   this.timeWidgets = widgets;
 
-  widgets['start']['date'].addEventListener("change", this.onAdjustDueTime, false);
-  widgets['start']['hour'].addEventListener("change", this.onAdjustDueTime, false);
-  widgets['start']['minute'].addEventListener("change", this.onAdjustDueTime, false);
+  Event.observe(widgets['start']['date'], "change", this.onAdjustDueTime, false);
+  Event.observe(widgets['start']['hour'], "change", this.onAdjustDueTime, false);
+  Event.observe(widgets['start']['minute'], "change", this.onAdjustDueTime, false);
 }
 
 function onStatusListChange(event) {
@@ -288,7 +288,7 @@ function onStatusListChange(event) {
 
 function initializeStatusLine() {
    var statusList = $("statusList");
-   statusList.addEventListener("mouseup", onStatusListChange, false);
+   Event.observe(statusList, "mouseup", onStatusListChange, false);
 }
 
 function onTaskEditorLoad() {
index 169e990a24b71b23d5c89939556c2e83cdf9954b..4ddee693c0f3ea96ecf6f7507914bf6c32c14b3b 100644 (file)
@@ -68,6 +68,8 @@ function dTree(objName) {
   this.selectedNode = null;
   this.selectedFound = false;
   this.completed = false;
+
+  return this;
 };
 
 // Adds a new node to the node array
index 19c19b1af5f1468710684f470b47790b59b29119..ca630042b2c7409c9edd8e9e82848fa02a5b2a81 100644 (file)
@@ -293,8 +293,7 @@ SPAN.toolbarButton:active
   border-bottom: 1px solid #424142; }
 
 .menu UL
-{ 
-  cursor: default;
+{ cursor: default;
   list-style-type: none;
   list-style-image: none;
   margin: 0px;
@@ -313,7 +312,8 @@ SPAN.toolbarButton:active
   width: auto;
   white-space: nowrap; }
 
-.menu LI.disabled
+.menu LI.disabled,
+.menu LI.disabled:hover
 { color: #999; }
 
 .menu LI IMG
@@ -367,6 +367,9 @@ DIV#logConsole
   right: 0px;
   height: 15em; }
 
+DIV#logConsole > DIV.highlighted
+{ background-color: #333; }
+
 /* content lists */
 td.tbtv_actcell
 { border-width: 1px;
index 7943f2f2a14630690e2e00072de2da8c8c20e553..1b9cf3cc58616ace25ec5568036ae9962f1ab309 100644 (file)
@@ -239,6 +239,7 @@ function triggerAjaxRequest(url, callback, userdata) {
           checkAjaxRequestsState();
           log("AJAX Request, Caught Exception: " + e.name);
           log(e.message);
+         log(backtrace());
         }
       };
     http.url = url;
@@ -255,21 +256,38 @@ function checkAjaxRequestsState() {
     if (activeAjaxRequests > 0
         && !document.busyAnim) {
       var anim = document.createElement("img");
+      anim = $(anim);
       document.busyAnim = anim;
       anim.id = "progressIndicator";
       anim.src = ResourcesURL + "/busy.gif";
-      anim.style.visibility = "hidden;";
+      anim.setStyle({ visibility: "hidden" });
       toolbar.appendChild(anim);
-      anim.style.visibility = "visible;";
+      anim.setStyle({ visibility: "visible" });
     }
     else if (activeAjaxRequests == 0
-            && document.busyAnim) {
+            && document.busyAnim
+            && document.busyAnim.parentNode) {
       document.busyAnim.parentNode.removeChild(document.busyAnim);
       document.busyAnim = null;
     }
   }
 }
 
+function getTarget(event) {
+  event = event || window.event;
+  if (event.target)
+    return event.target; // W3C DOM
+  else
+    return event.srcElement; // IE
+}
+
+function preventDefault(event) {
+  if (event.preventDefault)
+    event.preventDefault(); // W3C DOM
+  else
+    event.returnValue = false; // IE
+}
+
 function resetSelection(win) {
   var t = "";
   if (win && win.getSelection) {
@@ -389,7 +407,7 @@ function acceptMultiSelect(node) {
 }
 
 function onRowClick(event) {
-  var node = event.target;
+  var node = getTarget(event);
 
   if (node.tagName == 'TD')
     node = node.parentNode;
@@ -410,28 +428,33 @@ function onRowClick(event) {
 
   if (startSelection != node.parentNode.getSelectedNodes()) {
     var parentNode = node.parentNode;
-    log("onRowClick " + parentNode.tagName);
     if (parentNode.tagName == 'TBODY')
       parentNode = parentNode.parentNode;
-    var onSelectionChangeEvent = document.createEvent("UIEvents");
-    onSelectionChangeEvent.initEvent("selectionchange", true, true);
-    parentNode.dispatchEvent(onSelectionChangeEvent);
+    log("onRowClick: parentNode = " + parentNode.tagName);
+    if (document.createEvent) {
+      var onSelectionChangeEvent = document.createEvent("UIEvents");
+      onSelectionChangeEvent.initEvent("selectionchange", true, true);
+      parentNode.dispatchEvent(onSelectionChangeEvent);
+    }
+    else if (document.createEventObject) {
+      // TODO: add support for IE
+      //parentNode.fireEvent("change");
+      //parentNode is UL or TABLE
+    }
   }
 }
 
 /* popup menus */
 
-var bodyOnClick = "";
 // var acceptClick = false;
 
 function popupMenu(event, menuId, target) {
    document.menuTarget = target;
 
    if (document.currentPopupMenu)
-      hideMenu(event, document.currentPopupMenu);
-
-   var popup = document.getElementById(menuId);
+       hideMenu(event, document.currentPopupMenu);
 
+   var popup = $(menuId);
    var menuTop = event.pageY;
    var menuLeft = event.pageX;
    var heightDiff = (window.innerHeight
@@ -444,17 +467,14 @@ function popupMenu(event, menuId, target) {
    if (leftDiff < 0)
       menuLeft -= popup.offsetWidth;
 
-   popup.style.top = menuTop + "px;";
-   popup.style.left = menuLeft + "px;";
-   popup.style.visibility = "visible;";
+   popup.setStyle({ top: menuTop + "px",
+                   left: menuLeft + "px",
+                   visibility: "visible" });
 
-   bodyOnClick = "" + document.body.getAttribute("onclick");
-   document.body.setAttribute("onclick", "onBodyClick(event);");
    document.currentPopupMenu = popup;
+   Event.observe(document.body, "click", onBodyClickMenuHandler);
 
-   event.cancelBubble = true;
-   event.returnValue = false;
-   event.preventDefault();
+   preventDefault(event);
 }
 
 function getParentMenu(node) {
@@ -474,12 +494,12 @@ function getParentMenu(node) {
   return menuNode;
 }
 
-function onBodyClick(event) {
+function onBodyClickMenuHandler(event) {
    document.body.menuTarget = null;
    hideMenu(event, document.currentPopupMenu);
-   document.body.setAttribute("onclick", bodyOnClick);
-   
-   return false;
+   Event.stopObserving(document.body, "click", onBodyClickMenuHandler);
+
+   preventDefault(event);
 }
 
 function hideMenu(event, menuNode) {
@@ -491,7 +511,8 @@ function hideMenu(event, menuNode) {
     menuNode.submenu = null;
   }
 
-  menuNode.style.visibility = "hidden";
+  menuNode.setStyle({ visibility: "hidden" });
+  //   menuNode.hide();
   if (menuNode.parentMenuItem) {
     menuNode.parentMenuItem.setAttribute('class', 'submenu');
     menuNode.parentMenuItem = null;
@@ -501,9 +522,14 @@ function hideMenu(event, menuNode) {
     menuNode.parentMenu = null;
   }
 
-  var onhideEvent = document.createEvent("UIEvents");
-  onhideEvent.initEvent("hideMenu", false, true);
-  menuNode.dispatchEvent(onhideEvent);
+  if (document.initEvent) {
+    var onhideEvent = document.createEvent("UIEvents");
+    onhideEvent.initEvent("hideMenu", false, true);
+    menuNode.dispatchEvent(onhideEvent);
+  }
+  else if (document.createEventObject) {
+    // TODO: add support for IE
+  }
 }
 
 function onMenuEntryClick(event) {
@@ -531,21 +557,20 @@ function parseQueryParameters(url) {
 }
 
 function initLogConsole() {
-  var logConsole = $("logConsole");
-  if (logConsole) {
-    Event.observe(logConsole, "dblclick", onLogDblClick, false);
-    logConsole.innerHTML = "";
-    node = document.getElementsByTagName('body')[0];
-    Event.observe(node, "keydown", onBodyKeyDown, true);
-  }
+    var logConsole = $("logConsole");
+    if (logConsole) {
+       logConsole.highlighted = false;
+       Event.observe(logConsole, "dblclick", onLogDblClick, false);
+       logConsole.innerHTML = "";
+       Event.observe(window, "keydown", onBodyKeyDown);
+    }
 }
 
 function onBodyKeyDown(event) {
-  if (event.keyCode == 27) {
-    toggleLogConsole();
-    event.cancelBubble = true;
-    event.returnValue = false;
-  }
+    if (event.keyCode == 27) {
+       toggleLogConsole();
+       preventDefault(event);
+    }
 }
 
 function onLogDblClick(event) {
@@ -561,9 +586,8 @@ function toggleLogConsole(event) {
   } else {
     logConsole.setStyle({ display: '' });
   }
-  event.cancelBubble = true;
-  event.returnValue = false;
-  event.preventDefault();
+  if (event)
+      preventDefault(event);
 }
 
 function log(message) {
@@ -573,13 +597,22 @@ function log(message) {
       logWindow = logWindow.opener;
   }
   var logConsole = logWindow.document.getElementById("logConsole");
-  if (logConsole)
-    logConsole.innerHTML += message.replace("<", "&lt;", "g") + '<br />' + "\n";
+  if (logConsole) {
+      logConsole.highlighted = !logConsole.highlighted;
+      var logMessage = message.replace("<", "&lt;", "g");
+      logMessage = logMessage.replace(" ", "&nbsp;", "g");
+      logMessage = logMessage.replace("\r\n", "<br />\n", "g");
+      logMessage = logMessage.replace("\n", "<br />\n", "g");
+      logMessage += '<br />' + "\n";
+      if (logConsole.highlighted)
+         logMessage = '<div class="highlighted">' + logMessage + '</div>';
+      logConsole.innerHTML += logMessage;
+  }
 }
 
 function backtrace() {
    var func = backtrace.caller;
-   var str = "backtrace:<br/>";
+   var str = "backtrace:\n";
 
    while (func)
    {
@@ -592,7 +625,7 @@ function backtrace() {
       else
          str += "[anonymous]\n";
 
-      str += "<br/>";
+      str += "\n";
       func = func.caller;
    }
    str += "--\n";
@@ -601,36 +634,37 @@ function backtrace() {
 }
 
 function dropDownSubmenu(event) {
-  var node = this;
-  if (this.submenu && this.submenu != "") {
-    var submenuNode = document.getElementById(this.submenu);
-    var parentNode = getParentMenu(node);
-    if (parentNode.submenu)
-      hideMenu(event, parentNode.submenu);
-    submenuNode.parentMenuItem = node;
-    submenuNode.parentMenu = parentNode;
-    parentNode.submenuItem = node;
-    parentNode.submenu = submenuNode;
-    
-    var menuTop = (node.offsetTop - 2);
-    
-    var heightDiff = (window.innerHeight
-                      - (menuTop + submenuNode.offsetHeight));
-    if (heightDiff < 0)
-      menuTop += heightDiff;
-    
-    var menuLeft = parentNode.offsetWidth - 3;
-    if (window.innerWidth
-        < (menuLeft + submenuNode.offsetWidth
-           + parentNode.cascadeLeftOffset()))
-       menuLeft = - submenuNode.offsetWidth + 3;
-    
-    parentNode.setAttribute('onmousemove', 'checkDropDown(event);');
-    node.setAttribute('class', 'submenu-selected');
-    submenuNode.style.top = menuTop + "px;";
-    submenuNode.style.left = menuLeft + "px;";
-    submenuNode.style.visibility = "visible;";
-  }
+   var node = this;
+   if (this.submenu && this.submenu != "") {
+      log ("submenu: " + this.submenu);
+      var submenuNode = $(this.submenu);
+      var parentNode = getParentMenu(node);
+      if (parentNode.submenu)
+        hideMenu(event, parentNode.submenu);
+      submenuNode.parentMenuItem = node;
+      submenuNode.parentMenu = parentNode;
+      parentNode.submenuItem = node;
+      parentNode.submenu = submenuNode;
+      
+      var menuTop = (node.offsetTop - 2);
+      
+      var heightDiff = (window.innerHeight
+                       - (menuTop + submenuNode.offsetHeight));
+      if (heightDiff < 0)
+        menuTop += heightDiff;
+      
+      var menuLeft = parentNode.offsetWidth - 3;
+      if (window.innerWidth
+         < (menuLeft + submenuNode.offsetWidth
+            + parentNode.cascadeLeftOffset()))
+        menuLeft = - submenuNode.offsetWidth + 3;
+      
+      parentNode.setAttribute('onmousemove', 'checkDropDown(event);');
+      node.setAttribute('class', 'submenu-selected');
+      submenuNode.setStyle({ top: menuTop + "px",
+                                    left: menuLeft + "px",
+                                    visibility: "visible" });
+   }
 }
 
 function checkDropDown(event) {
@@ -656,7 +690,7 @@ function checkDropDown(event) {
 
 /* search field */
 function popupSearchMenu(event) {
-  var node = event.target;
+  var node = getTarget(event);
 
   var menuId = this.getAttribute("menuid");
   relX = event.pageX - node.cascadeLeftOffset();
@@ -671,13 +705,12 @@ function popupSearchMenu(event) {
       hideMenu(event, document.currentPopupMenu);
 
     var popup = document.getElementById(menuId);
-    popup.style.top = node.offsetHeight + "px";
-    popup.style.left = (node.offsetLeft + 3) + "px";
-    popup.style.visibility = "visible";
+    popup.setStyle({ top: node.offsetHeight + "px",
+                    left: (node.offsetLeft + 3) + "px",
+                           visibility: "visible" });
   
-    bodyOnClick = "" + document.body.getAttribute("onclick");
-    document.body.setAttribute("onclick", "onBodyClick('" + menuId + "');");
     document.currentPopupMenu = popup;
+    Event.observe(document.body, "click", onBodyClickMenuHandler);
   }
 }
 
@@ -722,7 +755,7 @@ function onSearchFocus() {
     this.select();
   }
 
-  this.style.color = "#000";
+  this.setStyle({ color: "#000" });
 }
 
 function onSearchBlur(event) {
@@ -730,14 +763,14 @@ function onSearchBlur(event) {
 //   log ("search blur: '" + this.value + "'");
   if (!this.value) {
     this.setAttribute("modified", "");
-    this.style.color = "#aaa";
+    this.setStyle({ color: "#aaa" });
     this.value = ghostPhrase;
   } else if (this.value == ghostPhrase) {
     this.setAttribute("modified", "");
-    this.style.color = "#aaa";
+    this.setStyle({ color: "#aaa" });
   } else {
     this.setAttribute("modified", "yes");
-    this.style.color = "#000";
+    this.setStyle({ color: "#000" });
   }
 }
 
@@ -766,7 +799,7 @@ function initCriteria() {
     if (searchValue.value == '') {
       searchValue.value = firstOption.innerHTML;
       searchValue.setAttribute("modified", "");
-      searchValue.style.color = "#aaa";
+      searchValue.setStyle({ color: "#aaa" });
     }
   }
 }
@@ -788,13 +821,12 @@ function popupToolbarMenu(event, menuId) {
       
       var popup = document.getElementById(menuId);
       var top = node.offsetTop + node.offsetHeight - 2;
-      popup.style.top = top + "px";
-      popup.style.left = node.cascadeLeftOffset() + "px";
-      popup.style.visibility = "visible";
-      
-      bodyOnClick = "" + document.body.getAttribute("onclick");
-      document.body.setAttribute("onclick", "onBodyClick('" + menuId + "');");
+      popup.setStyle({ top: top + "px",
+                      left: node.cascadeLeftOffset() + "px",
+                      visibility: "visible" });
+
       document.currentPopupMenu = popup;
+      Event.observe(document.body, "click", onBodyClickMenuHandler);
    }
 }
 
@@ -874,7 +906,8 @@ function unsubscribeFromFolder(folder, refreshCallback, refreshCallbackData) {
 }
 
 function listRowMouseDownHandler(event) {
-  event.preventDefault();
+  preventDefault(event);
+  return false;
 }
 
 /* tabs */
@@ -882,18 +915,27 @@ function initTabs() {
   var containers = document.getElementsByClassName("tabsContainer");
   for (var x = 0; x < containers.length; x++) {
     var container = containers[x];
-    var nodes = container.childNodes[1].childNodes;
-
-    var firstTab;
-    for (var i = 0; i < nodes.length; i++) {
-      if (nodes[i].tagName == 'LI') {
-       if (!firstTab) {
-          firstTab = i;
-        }
-        Event.observe(nodes[i], "mousedown", onTabMouseDown, true);
-       Event.observe(nodes[i], "click", onTabClick, true);
+    var firstTab = null;
+    for (var i = 0; i < container.childNodes.length; i++) {
+      if (container.childNodes[i].tagName == 'UL') {
+       if (!firstTab)
+         firstTab = i;
       }
     }
+    var nodes = container.childNodes[firstTab].childNodes;
+    
+    firstTab = null;
+    for (var i = 0; i < nodes.length; i++) {
+       var currentNode = nodes[i];
+       if (currentNode.tagName == 'LI') {
+           if (!firstTab)
+               firstTab = i;
+           Event.observe(currentNode, "mousedown",
+                         onTabMouseDown.bindAsEventListener(currentNode));
+           Event.observe(currentNode, "click",
+                         onTabClick.bindAsEventListener(currentNode));
+       }
+    }
 
     nodes[firstTab].addClassName("first");
     nodes[firstTab].addClassName("active");
@@ -905,12 +947,13 @@ function initTabs() {
 }
 
 function initMenus() {
-   for (var i = 0; i < menus["menuIds"].length; i++) {
-      var menuId = menus["menuIds"][i];
-      var callbacks = menus[menuId];
-      var menuDIV = $(menuId);
-      if (menuDIV)
-        initMenu(menuDIV, callbacks);
+   var menus = getMenus();
+   if (menus) {
+      for (var menuID in menus) {
+        var menuDIV = $(menuID);
+        if (menuDIV)
+           initMenu(menuDIV, menus[menuID]);
+      }
    }
 }
 
@@ -931,7 +974,8 @@ function initMenu(menuDIV, callbacks) {
            }
         }
         else
-           Event.observe(node, "mouseup", callback);
+           Event.observe(node, "mouseup",
+                         $(callback).bindAsEventListener(node));
       }
       else
         node.addClassName("disabled");
@@ -940,7 +984,7 @@ function initMenu(menuDIV, callbacks) {
 
 function onTabMouseDown(event) {
   event.cancelBubble = true;
-  event.preventDefault();
+  preventDefault(event);
 }
 
 function openExternalLink(anchor) {
@@ -981,7 +1025,7 @@ function getTopWindow() {
 }
 
 function onTabClick(event) {
-  var node = event.target;
+  var node = getTarget(event);
 
   var target = node.getAttribute("target");
 
@@ -1075,30 +1119,35 @@ function indexColor(number) {
   return color;
 }
 
-var onLoadHandler = function (event) {
-  queryParameters = parseQueryParameters('' + window.location);
-  if (!document.body.hasClassName("popup")) {
-    initLogConsole();
-    initCriteria();
-  }
-  initializeMenus();
-  initTabs();
-  configureDragHandles();
-  configureSortableTableHeaders();
-  configureLinkBanner();
-  var progressImage = $("progressIndicator");
-  if (progressImage)
-    progressImage.parentNode.removeChild(progressImage);
+function onLoadHandler(event) {
+    queryParameters = parseQueryParameters('' + window.location);
+    if (!$(document.body).hasClassName("popup")) {
+       initLogConsole();
+       initCriteria();
+    }
+    initMenus();
+    initTabs();
+    configureDragHandles();
+    configureSortableTableHeaders();
+    configureLinkBanner();
+    var progressImage = $("progressIndicator");
+    if (progressImage)
+       progressImage.parentNode.removeChild(progressImage);
+    Event.observe(document.body, "contextmenu", onBodyClickContextMenu);
+}
+
+function onBodyClickContextMenu(event) {
+  preventDefault(event);
 }
 
 function configureSortableTableHeaders() {
   var headers = document.getElementsByClassName("sortableTableHeader");
   for (var i = 0; i < headers.length; i++) {
-    var anchor = headers[i].childNodesWithTag("a")[0];
+    var anchor = $(headers[i]).childNodesWithTag("a")[0];
     if (!anchor.link) {
       anchor.link = anchor.getAttribute("href");
       anchor.href = "#";
-      Event.observe(anchor, "click", onHeaderClick, true);
+      Event.observe(anchor, "click", onHeaderClick.bindAsEventListener(anchor), true);
     }
   }
 }
@@ -1121,19 +1170,19 @@ function configureLinkBanner() {
   }
 }
 
-Event.observe(window, "load", onLoadHandler, false);
+addEvent(window, 'load', onLoadHandler);
 
 /* stubs */
 function configureDragHandles() {
 }
 
-function initializeMenus() {
+function getMenus() {
 }
 
 function onHeaderClick(event) {
-  window.alert("generic headerClick");
+   window.alert("generic headerClick");
 }
 
 function parent$(element) {
-   return window.opener.document.getElementById(element);
+   return this.opener.document.getElementById(element);
 }