]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1243 d1b88da0-ebda-0310...
authorwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 7 Nov 2007 17:42:18 +0000 (17:42 +0000)
committerwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 7 Nov 2007 17:42:18 +0000 (17:42 +0000)
46 files changed:
ChangeLog
SoObjects/Appointments/SOGoAppointmentFolder.h
SoObjects/Appointments/SOGoAppointmentFolder.m
SoObjects/Appointments/SOGoAppointmentObject.m
SoObjects/Appointments/SOGoCalendarComponent.m
SoObjects/Appointments/SOGoFreeBusyObject.h
SoObjects/Appointments/SOGoFreeBusyObject.m
SoObjects/Appointments/product.plist
SoObjects/Contacts/NSObject+CardDAV.m
SoObjects/Contacts/SOGoContactGCSFolder.h
SoObjects/Contacts/SOGoContactLDAPFolder.m
SoObjects/Contacts/product.plist
SoObjects/Mailer/SOGoMailAccount.m
SoObjects/Mailer/SOGoMailAccounts.h
SoObjects/Mailer/SOGoMailAccounts.m
SoObjects/Mailer/product.plist
SoObjects/SOGo/GNUmakefile
SoObjects/SOGo/SOGoContentObject.m
SoObjects/SOGo/SOGoFolder.h
SoObjects/SOGo/SOGoFolder.m
SoObjects/SOGo/SOGoObject.m
SoObjects/SOGo/SOGoParentFolder.h
SoObjects/SOGo/SOGoParentFolder.m
SoObjects/SOGo/SOGoUserFolder.h
SoObjects/SOGo/SOGoUserFolder.m
UI/Common/UIxFolderActions.h
UI/Common/UIxFolderActions.m
UI/Common/product.plist
UI/Contacts/UIxContactEditor.m
UI/Contacts/UIxContactFoldersView.m
UI/Contacts/product.plist
UI/MainUI/product.plist
UI/PreferencesUI/English.lproj/Localizable.strings
UI/PreferencesUI/French.lproj/Localizable.strings
UI/PreferencesUI/German.lproj/Localizable.strings
UI/PreferencesUI/UIxJSONPreferences.m
UI/PreferencesUI/UIxPreferences.h
UI/PreferencesUI/UIxPreferences.m
UI/PreferencesUI/product.plist
UI/Templates/ContactsUI/UIxContactsFilterPanel.wox
UI/Templates/PreferencesUI/UIxPreferences.wox
UI/WebServerResources/ContactsUI.js
UI/WebServerResources/MailerUI.js
UI/WebServerResources/SchedulerUI.js
UI/WebServerResources/generic.css
UI/WebServerResources/generic.js

index a379bb64bc75a1691990de5ee5f87c11ffd9a462..3e2a6bc8121c2eb2a02eb1f8bd87922467e9edd1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-11-07  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * SoObjects/SOGo/SOGoParentFolder.m: no longer a subclass of
+       SOGoObject, but of SOGoFolder instead.
+
+       * SoObjects/SOGo/SOGoUserFolder.m: no longer a subclass of
+       SOGoGCSFolder, but of SOGoFolder instead.
+
+       * SoObjects/Appointments/SOGoAppointmentFolder.m
+       ([SOGoAppointmentFolder -lookupCalendarFolderForUID:uid]): fixed
+       to take the new SOGoParentFolder class into account. Also, create
+       the personal folder if it doesn't exist.
+
+       * SoObjects/SOGo/SOGoFolder.[hm]: new class module implementing
+       the parent of all SOGo containers.
+
+       * SoObjects/SOGo/SOGoGCSFolder.[hm]: SOGoFolder class renamed to
+       SOGoGCSFolder.
+
 2007-11-06  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
 
        * UI/MailerUI/UIxMailToSelection.m ([UIxMailToSelection
index 5f5ee41d6abcc409cd7209274fb0f234ab7d7474..27a24c9adc703ea4690cf8c43f35e137990c4c82 100644 (file)
@@ -36,7 +36,7 @@
   create two different vevent-files with the same uid in the store.
 */
 
-#import "SOGo/SOGoFolder.h"
+#import "SOGo/SOGoGCSFolder.h"
 
 @class NSArray;
 @class NSCalendarDate;
@@ -47,7 +47,7 @@
 @class GCSFolder;
 
 #import <NGCards/iCalEntityObject.h>
-@interface SOGoAppointmentFolder : SOGoFolder
+@interface SOGoAppointmentFolder : SOGoGCSFolder
 {
   NSTimeZone *timeZone;
   NSMutableDictionary *uidToFilename;
index a2306fba6bf1223ac82306d7f5fb9b6c8186cd1c..395d92e804911f2aedfe7a2f9c6c8e37c5580020 100644 (file)
@@ -52,6 +52,7 @@
 #import <SOGo/SOGoUser.h>
 
 #import "SOGoAppointmentObject.h"
+#import "SOGoAppointmentFolders.h"
 #import "SOGoTaskObject.h"
 
 #import "SOGoAppointmentFolder.h"
@@ -1001,20 +1002,29 @@ static NSNumber   *sharedYes = nil;
 
 - (SOGoAppointmentFolder *) lookupCalendarFolderForUID: (NSString *) uid
 {
-  SOGoFolder *upperContainer;
-  SOGoUserFolder *userFolder;
-  SOGoAppointmentFolder *calendarFolder;
-
-  upperContainer = [[self container] container];
-  userFolder = [SOGoUserFolder objectWithName: uid
-                               inContainer: upperContainer];
-  calendarFolder = [SOGoAppointmentFolder objectWithName: @"Calendar"
-                                          inContainer: userFolder];
-  [calendarFolder
-    setOCSPath: [NSString stringWithFormat: @"/Users/%@/Calendar/personal", uid]];
-  [calendarFolder setOwner: uid];
-
-  return calendarFolder;
+  SOGoFolder *currentContainer;
+  SOGoAppointmentFolders *parent;
+  NSException *error;
+
+  currentContainer = [[container container] container];
+  currentContainer = [currentContainer lookupName: uid
+                                      inContext: context
+                                      acquire: NO];
+  parent = [currentContainer lookupName: @"Calendar" inContext: context
+                            acquire: NO];
+  currentContainer = [parent lookupName: @"personal" inContext: context
+                            acquire: NO];
+  if (!currentContainer)
+    {
+      error = [parent newFolderWithName: [parent defaultFolderName]
+                     andNameInContainer: @"personal"];
+      if (!error)
+       currentContainer = [parent lookupName: @"personal"
+                                  inContext: context
+                                  acquire: NO];
+    }
+
+  return (SOGoAppointmentFolder *) currentContainer;
 }
 
 - (NSArray *) lookupCalendarFoldersForUIDs: (NSArray *) _uids
@@ -1041,8 +1051,9 @@ static NSNumber   *sharedYes = nil;
          if (![folder isNotNull])
            [self logWithFormat:@"Note: did not find folder for uid: '%@'", uid];
        }
-    
-      [folders addObject: folder];
+
+      if (folder)
+       [folders addObject: folder];
     }
 
   return folders;
index c4c94371474c1e6bcc8f10ed875fa34ea2fa2d32..59f96d69eecfa6b878cd95928053b33335f21d9d 100644 (file)
   return allErrors;
 }
 
-- (NSException *)deleteInUIDs:(NSArray *)_uids {
+- (NSException *) deleteInUIDs: (NSArray *) _uids
+{
   NSEnumerator *e;
   id folder;
   NSException *allErrors = nil;
+  NSException           *error;
+  SOGoAppointmentObject *apt;
   
   e = [[container lookupCalendarFoldersForUIDs:_uids inContext: context]
        objectEnumerator];
-  while ((folder = [e nextObject])) {
-    NSException           *error;
-    SOGoAppointmentObject *apt;
-    
-    apt = [folder lookupName:[self nameInContainer] inContext: context
-                 acquire:NO];
-    if ([apt isKindOfClass: [NSException class]]) {
-      [self logWithFormat: @"%@", [(NSException *) apt reason]];
-      continue;
-    }
+  while ((folder = [e nextObject]))
+    {
+      apt = [folder lookupName: [self nameInContainer]
+                   inContext: context
+                   acquire:NO];
+      if ([apt isKindOfClass: [NSException class]]) {
+       [self logWithFormat: @"%@", [(NSException *) apt reason]];
+       continue;
+      }
     
-    if ((error = [apt primaryDelete]) != nil) {
-      [self logWithFormat:@"Note: failed to delete in folder: %@", folder];
-      // TODO: make compound
-      allErrors = error;
+      if ((error = [apt primaryDelete]) != nil) {
+       [self logWithFormat:@"Note: failed to delete in folder: %@", folder];
+       // TODO: make compound
+       allErrors = error;
+      }
     }
-  }
+
   return allErrors;
 }
 
index f61b756f4f1196edc01f659edef7cb8a6e715fc1..805de4276ed30b145847ce915861d77bfc1a4278 100644 (file)
@@ -375,8 +375,8 @@ static BOOL sendEMailNotifications = NO;
             recipient = email;
 
          language = [[context activeUser] language];
-#warning this could be optimized in a class hierarchy common with the \
-          SOGoObject's acl notification mechanism
+#warning this could be optimized in a class hierarchy common with the  \
+          SOGoObject acl notification mechanism
           /* create page name */
           // TODO: select user's default language?
           pageName = [NSString stringWithFormat: @"SOGoAptMail%@%@",
index 4b83b9dd8b9ea6d0c3da3f76b8f9b9b6eb828de4..c76a2b494b3e416593f4fa5db3a14da108d02e2b 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef        __Appointments_SOGoFreeBusyObject_H_
 #define        __Appointments_SOGoFreeBusyObject_H_
 
-#include <SOGo/SOGoContentObject.h>
+#include <SOGo/SOGoObject.h>
 
 /*
  SOGoFreeBusyObject
@@ -34,7 +34,7 @@
 
 @class NSArray, NSCalendarDate;
 
-@interface SOGoFreeBusyObject : SOGoContentObject
+@interface SOGoFreeBusyObject : SOGoObject
 {
 }
 
index ef40274dcc4d888d49d86ba37ba8d7b59455d05b..80390a733c7920c3be9158e576d02141f1a5d525 100644 (file)
 
 @implementation SOGoFreeBusyObject
 
-- (NSString *) iCalString
-{
-  // for UI-X appointment viewer
-  return [self contentAsString];
-}
-
 - (NSString *) contentAsString
 {
   NSCalendarDate *today, *startDate, *endDate;
   return infos;
 }
 
+- (NSString *) iCalString
+{
+  // for UI-X appointment viewer
+  return [self contentAsString];
+}
+
 /* Private API */
 - (iCalFreeBusyType) _fbTypeForEventStatus: (NSNumber *) eventStatus
 {
   WOResponse *r;
   NSData     *contentData;
 
-  contentData = [[self contentAsString] dataUsingEncoding: NSUTF8StringEncoding];
+  contentData = [[self contentAsString]
+                 dataUsingEncoding: NSUTF8StringEncoding];
 
   r = [(WOContext *) _ctx response];
   [r setHeader: @"text/calendar" forKey: @"content-type"];
   return @"text/calendar";
 }
 
+- (NSArray *) aclsForUser: (NSString *) uid
+{
+  return nil;
+}
+
 @end
index 1fdd67e882f73df490a68253be07ea0f9b90fab8..f2a5b7fe3f1dc478262d85dfe7c5fcac3c224f43 100644 (file)
@@ -12,7 +12,7 @@
       superclass = "SOGoParentFolder";
     };
     SOGoAppointmentFolder = {
-      superclass = "SOGoFolder";
+      superclass = "SOGoGCSFolder";
       defaultRoles = {
 /*        "FreeBusyLookup" = ( "Owner", "FreeBusy", "AuthorizedSubscriber" );  */
        "ViewWholePublicRecords" = ( "Owner", "PublicResponder", "PublicModifier", "PublicViewer" );
index 1a1df88b0c36bff61451b62aa35c8934f713b68f..2fed99dcb5c55a7023ec282bb1c6b3d26646e294 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
-#import "SOGoContactFolder.h"
-#import "SOGoContactGCSEntry.h"
-
-#import <DOM/DOMProtocols.h>
 #import <Foundation/NSArray.h>
-#import <NGExtensions/NSString+misc.h>
-#import <SaxObjC/SaxObjC.h>
-#import <SaxObjC/XMLNamespaces.h>
+
 #import <NGObjWeb/WOContext.h>
 #import <NGObjWeb/WORequest.h>
 #import <NGObjWeb/WOResponse.h>
+#import <NGExtensions/NSString+misc.h>
+#import <DOM/DOMProtocols.h>
+#import <SaxObjC/SaxObjC.h>
+#import <SaxObjC/XMLNamespaces.h>
+
+#import "SOGoContactFolder.h"
+#import "SOGoContactGCSEntry.h"
 
 @implementation NSObject (CardDAV)
 
@@ -42,7 +43,7 @@
   NSDictionary *currentFilter, *contact;
   NSEnumerator *contacts;
   NSString *baseURL;
-  id<SOGoContactFolder> o;
+  SOGoObject <SOGoContactFolder> *o;
 
   o = (id<SOGoContactFolder>)self;
   baseURL = [o baseURLInContext: context];
index 9ac8fb1fe0f85834f6712e63782b3363c18b6a98..a6f6f0eed14a1ebae1bce08f0e74e9e786935875 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef __Contacts_SOGoContactGCSFolder_H__
 #define __Contacts_SOGoContactGCSFolder_H__
 
-#import <SoObjects/SOGo/SOGoFolder.h>
+#import <SoObjects/SOGo/SOGoGCSFolder.h>
 
 #import "SOGoContactFolder.h"
 #import "NSObject+CardDAV.h"
@@ -30,7 +30,7 @@
 @class NSArray;
 @class NSString;
 
-@interface SOGoContactGCSFolder : SOGoFolder <SOGoContactFolder>
+@interface SOGoContactGCSFolder : SOGoGCSFolder <SOGoContactFolder>
 
 @end
 
index 13772500ef2e74967ee15d21de61f9eeda46ce82..65e4d11c8f0ff6fc50aa44c36990c9f20420168a 100644 (file)
@@ -43,8 +43,6 @@
 
 @class WOContext;
 
-
-
 @implementation SOGoContactLDAPFolder
 
 - (void) appendObject: (NSDictionary *) object
@@ -59,7 +57,8 @@
   componentClass = [SOGoContactLDIFEntry class];
 
   
-  component = [componentClass contactEntryWithName: name  withLDIFEntry: object  inContainer: self];
+  component = [componentClass contactEntryWithName: name
+                             withLDIFEntry: object  inContainer: self];
 
   [r appendContentString: @"  <D:response>\r\n"];
   [r appendContentString: @"    <D:href>"];
index e1557d613524f3cd4da96689b69bac1485c25bb9..f303590298fa174a0141fa446e1e0db4f51d5be8 100644 (file)
       superclass = "SOGoParentFolder";
     };
     SOGoContactGCSFolder = {
-      superclass = "SOGoFolder";
+      superclass = "SOGoGCSFolder";
     };
     SOGoContactGCSEntry = {
       superclass = "SOGoContentObject";
     };
     SOGoContactLDAPFolder = {
-      superclass = "SOGoFolder";
+      superclass = "SOGoGCSFolder";
       protectedBy = "Access Contents Information";
       defaultRoles = {
        "Access Contents Information" = ( "Authenticated" );
index f702e21fbd49ab0470531d06d9a379489621487a..4f2f59110399c4e5804d4d78f4b419e61447b306 100644 (file)
@@ -479,14 +479,16 @@ static NSString *otherUsersFolderName = @""; // TODO: add English default
   s = [self nameInContainer];
   
   r = [s rangeOfString:@"@"];
-  if (r.length > 0) {
-    login = [s substringToIndex:r.location];
-    host  = [s substringFromIndex:(r.location + r.length)];
-  }
-  else {
-    login = nil;
-    host  = s;
-  }
+  if (r.length > 0)
+    {
+      login = [s substringToIndex:r.location];
+      host  = [s substringFromIndex:(r.location + r.length)];
+    }
+  else
+    {
+      login = nil;
+      host  = s;
+    }
   
   r = [host rangeOfString:@"."];
   if (r.length > 0)
index 96475f7ac6f285b3a7206a855e4a23ec32f332cb..623ffcb2f1ad8fc2058479510b31e401b3a05dc2 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef __Mailer_SOGoMailAccounts_H__
 #define __Mailer_SOGoMailAccounts_H__
 
-#import <SOGo/SOGoObject.h>
+#import <SoObjects/SOGo/SOGoFolder.h>
 
 /*
   SOGoMailAccounts
@@ -39,7 +39,7 @@
 
 @class NSArray;
 
-@interface SOGoMailAccounts : SOGoObject
+@interface SOGoMailAccounts : SOGoFolder
 
 @end
 
index 66e2948befa2e6b6628635ff5a3355102e911114..b09e9092b1b3f09111c7c8af041070c840ff18b7 100644 (file)
@@ -127,24 +127,4 @@ static NSString *AgenorShareLoginMarker  = @".-.";
   return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
 }
 
-/* WebDAV */
-
-- (BOOL) davIsCollection
-{
-  return YES;
-}
-
-- (NSString *) davContentType
-{
-  return @"httpd/unix-directory";
-}
-
-/* acls */
-
-- (NSArray *) aclsForUser: (NSString *) uid
-{
-  return nil;
-}
-
-
 @end /* SOGoMailAccounts */
index 9e202f3e76c08ef236a2a15eb8eb17b83957a992..2a93d2b7acd6564278e2e42e0ce4d8864db88247 100644 (file)
@@ -12,7 +12,7 @@
       superclass    = "SOGoObject";
     };
     SOGoMailAccounts = {
-      superclass    = "SOGoMailBaseObject";
+      superclass    = "SOGoFolder";
       defaultRoles = {
         "View"          = ( "Owner", "AuthorizedSubscriber" );
         "Access Contents Information" = ( "Owner", "AuthorizedSubscriber" );
index 7d15b89f568c14f8ec49321b5eb383ce2492d3ed..46c94b95bcefa8e9764b721e2bb9245e5bf9b12e 100644 (file)
@@ -53,6 +53,7 @@ libSOGo_OBJC_FILES = \
        SOGoObject.m                    \
        SOGoContentObject.m             \
        SOGoFolder.m                    \
+       SOGoGCSFolder.m                 \
        SOGoParentFolder.m              \
        SOGoUserFolder.m                \
        SOGoGroupsFolder.m              \
index 00ed0779e7d23628b25babdd713f71db8fc15b10..442513663da7e606aa89c09b9c3df8a566fb2056 100644 (file)
@@ -29,7 +29,7 @@
 #import <NGExtensions/NSObject+Logs.h>
 #import <GDLContentStore/GCSFolder.h>
 
-#import "SOGoFolder.h"
+#import "SOGoGCSFolder.h"
 #import "SOGoUser.h"
 #import "SOGoPermissions.h"
 #import "SOGoContentObject.h"
index c0b492e98a2c7905d96b3c186809cdd7e72fb30c..ee5de48e40784f50ebd670af4eab42d37421cada 100644 (file)
-/*
-  Copyright (C) 2004-2005 SKYRIX Software AG
-
-  This file is part of OpenGroupware.org.
-
-  OGo is free software; you can redistribute it and/or modify it under
-  the terms of the GNU Lesser General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  OGo is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
-
-#ifndef __SOGo_SOGoFolder_H__
-#define __SOGo_SOGoFolder_H__
+/* SOGoFolder.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 SOGOFOLDER_H
+#define SOGOFOLDER_H
 
 #import "SOGoObject.h"
 
-@class NSArray;
-@class NSDictionary;
-@class NSMutableDictionary;
-@class NSString;
-
-@class GCSFolder;
-
-/*
-  SOGoFolder
-  
-  A common superclass for folders stored in GCS. Already deals with all GCS
-  folder specific things.
-  
-  Important: folders should NOT retain the context! Otherwise you might get
-             cyclic references.
-*/
-
 @interface SOGoFolder : SOGoObject
 {
   NSMutableString *displayName;
-  NSString *ocsPath;
-  GCSFolder *ocsFolder;
-  NSMutableDictionary *aclCache;
 }
 
-+ (id) folderWithSubscriptionReference: (NSString *) reference
-                          inContainer: (id) aContainer;
-
-/* accessors */
-
 - (void) setDisplayName: (NSString *) newDisplayName;
 - (NSString *) displayName;
 
-- (void) setOCSPath: (NSString *)_Path;
-- (NSString *) ocsPath;
-
-- (GCSFolder *) ocsFolderForPath: (NSString *)_path;
-- (GCSFolder *) ocsFolder;
-
-/* lower level fetches */
-- (BOOL) nameExistsInFolder: (NSString *) objectName;
-
-- (void) deleteEntriesWithIds: (NSArray *) ids;
-
-- (NSArray *) fetchContentObjectNames;
-- (NSDictionary *) fetchContentStringsAndNamesOfAllObjects;
-
-/* folder type */
-
-- (NSString *) outlookFolderClass;
-
-- (BOOL) folderIsMandatory;
 - (NSString *) folderType;
 
-/* sorting */
-- (NSComparisonResult) compare: (SOGoFolder *) otherFolder;
-
-- (BOOL) create;
-- (NSException *) delete;
-- (void) renameTo: (NSString *) newName;
 /* dav */
 - (NSArray *) davNamespaces;
 
-/* acls as a container */
-- (NSArray *) aclUsersForObjectAtPath: (NSArray *) objectPathArray;
-- (NSArray *) aclsForUser: (NSString *) uid
-          forObjectAtPath: (NSArray *) objectPathArray;
-- (void) setRoles: (NSArray *) roles
-          forUser: (NSString *) uid
-  forObjectAtPath: (NSArray *) objectPathArray;
-- (void) removeAclsForUsers: (NSArray *) users
-            forObjectAtPath: (NSArray *) objectPathArray;
-
-@end
-
-@interface SOGoFolder (GroupDAVExtensions)
-
-- (NSString *) groupDavResourceType;
+/* outlook */
+- (NSString *) outlookFolderClass;
 
 @end
 
-#endif /* __SOGo_SOGoFolder_H__ */
+#endif /* SOGOFOLDER_H */
index 3ff95dae3de885f2a8dee65d38b8a492256ede21..af83275ead92aa560a5b3dd0f4904b399c25e583 100644 (file)
-/*
-  Copyright (C) 2004-2005 SKYRIX Software AG
-
-  This file is part of OpenGroupware.org.
-
-  OGo is free software; you can redistribute it and/or modify it under
-  the terms of the GNU Lesser General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-
-  OGo is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
-  License for more details.
-
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
+/* SOGoFolder.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/NSDate.h>
-#import <Foundation/NSDictionary.h>
-#import <Foundation/NSException.h>
-#import <Foundation/NSKeyValueCoding.h>
+#import <Foundation/NSString.h>
 #import <Foundation/NSURL.h>
 
-#import <NGObjWeb/NSException+HTTP.h>
-#import <NGObjWeb/SoObject.h>
-#import <NGObjWeb/SoObject+SoDAV.h>
 #import <NGObjWeb/SoSelectorInvocation.h>
-#import <NGObjWeb/WOContext+SoObjects.h>
-#import <NGObjWeb/WOApplication.h>
-#import <NGExtensions/NSNull+misc.h>
-#import <NGExtensions/NSObject+Logs.h>
-#import <EOControl/EOQualifier.h>
-#import <GDLAccess/EOAdaptorChannel.h>
-#import <GDLContentStore/GCSChannelManager.h>
-#import <GDLContentStore/GCSFolderManager.h>
-#import <GDLContentStore/GCSFolder.h>
-#import <GDLContentStore/GCSFolderType.h>
-#import <GDLContentStore/NSURL+GCS.h>
-#import <SaxObjC/XMLNamespaces.h>
-#import <UI/SOGoUI/SOGoFolderAdvisory.h>
 
-#import "NSArray+Utilities.h"
 #import "NSString+Utilities.h"
 
-#import "SOGoContentObject.h"
-#import "SOGoPermissions.h"
-#import "SOGoUser.h"
-
 #import "SOGoFolder.h"
 
-static NSString *defaultUserID = @"<default>";
-
 @implementation SOGoFolder
 
-+ (int) version
-{
-  return [super version] + 0 /* v0 */;
-}
-
-+ (void) initialize
-{
-  NSAssert2([super version] == 0,
-            @"invalid superclass (%@) version %i !",
-            NSStringFromClass([self superclass]), [super version]);
-}
-
-+ (id) folderWithSubscriptionReference: (NSString *) reference
-                          inContainer: (id) aContainer
-{
-  id newFolder;
-  NSArray *elements, *pathElements;
-  NSString *ocsPath, *objectPath, *owner, *ocsName, *folderName;
-
-  elements = [reference componentsSeparatedByString: @":"];
-  owner = [elements objectAtIndex: 0];
-  objectPath = [elements objectAtIndex: 1];
-  pathElements = [objectPath componentsSeparatedByString: @"/"];
-  if ([pathElements count] > 1)
-    ocsName = [pathElements objectAtIndex: 1];
-  else
-    ocsName = @"personal";
-
-  ocsPath = [NSString stringWithFormat: @"/Users/%@/%@/%@",
-                     owner, [pathElements objectAtIndex: 0], ocsName];
-  folderName = [NSString stringWithFormat: @"%@_%@", owner, ocsName];
-  newFolder = [[self alloc] initWithName: folderName
-                           inContainer: aContainer];
-  [newFolder setOCSPath: ocsPath];
-  [newFolder setOwner: owner];
-
-  return newFolder;
-}
-
 - (id) init
 {
   if ((self = [super init]))
-    {
-      displayName = nil;
-      ocsPath = nil;
-      ocsFolder = nil;
-      aclCache = [NSMutableDictionary new];
-    }
+    displayName = nil;
 
   return self;
 }
 
 - (void) dealloc
 {
-  [ocsFolder release];
-  [ocsPath release];
-  [aclCache release];
   [displayName release];
   [super dealloc];
 }
 
-/* accessors */
-
-- (BOOL) isFolderish
-{
-  return YES;
-}
-
-- (void) setOCSPath: (NSString *) _path
-{
-  if (![ocsPath isEqualToString:_path])
-    {
-      if (ocsPath)
-       [self warnWithFormat: @"GCS path is already set! '%@'", _path];
-      ASSIGN (ocsPath, _path);
-    }
-}
-
-- (NSString *) ocsPath
-{
-  return ocsPath;
-}
-
-- (GCSFolderManager *) folderManager
-{
-  static GCSFolderManager *folderManager = nil;
-
-  if (!folderManager)
-    folderManager = [GCSFolderManager defaultFolderManager];
-
-  return folderManager;
-}
-
-- (GCSFolder *) ocsFolderForPath: (NSString *) _path
-{
-  return [[self folderManager] folderAtPath: _path];
-}
-
-- (BOOL) folderIsMandatory
-{
-  return [nameInContainer isEqualToString: @"personal"];
-}
-
-- (void) _setDisplayNameFromRow: (NSDictionary *) row
-{
-  NSString *currentLogin, *ownerLogin;
-  NSDictionary *ownerIdentity;
-
-  displayName
-    = [NSMutableString stringWithString: [row objectForKey: @"c_foldername"]];
-  currentLogin = [[context activeUser] login];
-  ownerLogin = [self ownerInContext: context];
-  if (![currentLogin isEqualToString: ownerLogin])
-    {
-      ownerIdentity = [[SOGoUser userWithLogin: ownerLogin roles: nil]
-                       primaryIdentity];
-      [displayName appendFormat: @" (%@ <%@>)",
-                  [ownerIdentity objectForKey: @"fullName"],
-                  [ownerIdentity objectForKey: @"email"]];
-    }
-  [displayName retain];
-}
-
-- (void) _fetchDisplayName
-{
-  GCSChannelManager *cm;
-  EOAdaptorChannel *fc;
-  NSURL *folderLocation;
-  NSString *sql;
-  NSArray *attrs;
-  NSDictionary *row;
-
-  cm = [GCSChannelManager defaultChannelManager];
-  folderLocation
-    = [[GCSFolderManager defaultFolderManager] folderInfoLocation];
-  fc = [cm acquireOpenChannelForURL: folderLocation];
-  if (fc)
-    {
-      sql
-       = [NSString stringWithFormat: (@"SELECT c_foldername FROM %@"
-                                      @" WHERE c_path = '%@'"),
-                   [folderLocation gcsTableName], ocsPath];
-      [fc evaluateExpressionX: sql];
-      attrs = [fc describeResults: NO];
-      row = [fc fetchAttributes: attrs withZone: NULL];
-      if (row)
-       [self _setDisplayNameFromRow: row];
-      [fc cancelFetch];
-      [cm releaseChannel: fc];
-    }
-}
-
 - (void) setDisplayName: (NSString *) newDisplayName
 {
   ASSIGN (displayName, newDisplayName);
@@ -216,468 +53,16 @@ static NSString *defaultUserID = @"<default>";
 
 - (NSString *) displayName
 {
-  if (!displayName)
-    [self _fetchDisplayName];
-
-  return displayName;
-}
-
-- (NSString *) davDisplayName
-{
-  return [self displayName];
-}
-
-- (GCSFolder *) ocsFolder
-{
-  GCSFolder *folder;
-  NSString *userLogin;
-
-  if (!ocsFolder)
-    {
-      ocsFolder = [self ocsFolderForPath: [self ocsPath]];
-      userLogin = [[context activeUser] login];
-      if (!ocsFolder
-/*       && [userLogin isEqualToString: [self ownerInContext: context]] */
-         && [self folderIsMandatory]
-         && [self create])
-       ocsFolder = [self ocsFolderForPath: [self ocsPath]];
-      [ocsFolder retain];
-    }
-
-  if ([ocsFolder isNotNull])
-    folder = ocsFolder;
-  else
-    folder = nil;
-
-  return folder;
+  return ((displayName) ? displayName : nameInContainer);
 }
 
 - (NSString *) folderType
 {
-  return @"";
-}
-
-- (void) sendFolderAdvisoryTemplate: (NSString *) template
-{
-  NSString *pageName;
-  SOGoUser *user;
-  SOGoFolderAdvisory *page;
-
-  user = [context activeUser];
-  pageName = [NSString stringWithFormat: @"SOGoFolder%@%@Advisory",
-                      [user language], template];
-
-  page = [[WOApplication application] pageWithName: pageName
-                                     inContext: context];
-  [page setFolderObject: self];
-  [page setRecipientUID: [user login]];
-  [page send];
-}
-
-
-//   if (!result) [self sendFolderAdvisoryTemplate: @"Addition"];
-
-- (BOOL) create
-{
-  NSException *result;
-
-  result = [[self folderManager] createFolderOfType: [self folderType]
-                                withName: displayName
-                                 atPath: ocsPath];
-
-  return (result == nil);
-}
-
-- (NSException *) delete
-{
-  NSException *error;
-
-  // We just fetch our displayName since our table will use it!
-  [self displayName];
-  
-  if ([nameInContainer isEqualToString: @"personal"])
-    error = [NSException exceptionWithHTTPStatus: 403
-                        reason: @"folder 'personal' cannot be deleted"];
-  else
-    error = [[self folderManager] deleteFolderAtPath: ocsPath];
-
-  return error;
-}
-
-//   if (!error) [self sendFolderAdvisoryTemplate: @"Removal"];
-
-- (void) renameTo: (NSString *) newName
-{
-  GCSChannelManager *cm;
-  EOAdaptorChannel *fc;
-  NSURL *folderLocation;
-  NSString *sql;
-
-  [displayName release];
-  displayName = nil;
-
-  cm = [GCSChannelManager defaultChannelManager];
-  folderLocation
-    = [[GCSFolderManager defaultFolderManager] folderInfoLocation];
-  fc = [cm acquireOpenChannelForURL: folderLocation];
-  if (fc)
-    {
-      sql
-       = [NSString stringWithFormat: (@"UPDATE %@ SET c_foldername = '%@'"
-                                      @" WHERE c_path = '%@'"),
-                   [folderLocation gcsTableName], newName, ocsPath];
-      [fc evaluateExpressionX: sql];
-      [cm releaseChannel: fc];
-//       sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'", 
-//                  uidColumnName, [self uid]];
-    }
-}
-
-- (NSArray *) fetchContentObjectNames
-{
-  NSArray *fields, *records;
-  
-  fields = [NSArray arrayWithObject: @"c_name"];
-  records = [[self ocsFolder] fetchFields:fields matchingQualifier:nil];
-  if (![records isNotNull])
-    {
-      [self errorWithFormat: @"(%s): fetch failed!", __PRETTY_FUNCTION__];
-      return nil;
-    }
-  if ([records isKindOfClass: [NSException class]])
-    return records;
-  return [records objectsForKey: @"c_name"];
-}
-
-- (BOOL) nameExistsInFolder: (NSString *) objectName
-{
-  NSArray *fields, *records;
-  EOQualifier *qualifier;
-
-  qualifier
-    = [EOQualifier qualifierWithQualifierFormat:
-                     [NSString stringWithFormat: @"c_name='%@'", objectName]];
-
-  fields = [NSArray arrayWithObject: @"c_name"];
-  records = [[self ocsFolder] fetchFields: fields
-                              matchingQualifier: qualifier];
-  return (records
-          && ![records isKindOfClass:[NSException class]]
-          && [records count] > 0);
-}
-
-- (void) deleteEntriesWithIds: (NSArray *) ids
-{
-  unsigned int count, max;
-  NSString *currentID;
-  SOGoContentObject *deleteObject;
-
-  max = [ids count];
-  for (count = 0; count < max; count++)
-    {
-      currentID = [ids objectAtIndex: count];
-      deleteObject = [self lookupName: currentID
-                          inContext: context acquire: NO];
-      if (![deleteObject isKindOfClass: [NSException class]])
-       [deleteObject delete];
-    }
-}
-
-- (NSDictionary *) fetchContentStringsAndNamesOfAllObjects
-{
-  NSDictionary *files;
-  
-  files = [[self ocsFolder] fetchContentsOfAllFiles];
-  if (![files isNotNull])
-    {
-      [self errorWithFormat:@"(%s): fetch failed!", __PRETTY_FUNCTION__];
-      return nil;
-    }
-  if ([files isKindOfClass:[NSException class]])
-    return files;
-  return files;
-}
-
-/* reflection */
+  [self subclassResponsibility: _cmd];
 
-- (NSString *) defaultFilenameExtension
-{
-  /* 
-     Override to add an extension to a filename
-     
-     Note: be careful with that, needs to be consistent with object lookup!
-  */
   return nil;
 }
 
-- (NSArray *) davResourceType
-{
-  NSArray *rType, *groupDavCollection;
-
-  if ([self respondsToSelector: @selector (groupDavResourceType)])
-    {
-      groupDavCollection
-       = [NSArray arrayWithObjects: [self groupDavResourceType],
-                  XMLNS_GROUPDAV, nil];
-      rType = [NSArray arrayWithObjects: @"collection", groupDavCollection,
-                      nil];
-    }
-  else
-    rType = [NSArray arrayWithObject: @"collection"];
-
-  return rType;
-}
-
-- (NSString *) davContentType
-{
-  return @"httpd/unix-directory";
-}
-
-- (NSArray *) toOneRelationshipKeys
-{
-  /* toOneRelationshipKeys are the 'files' contained in a folder */
-  NSMutableArray *ma;
-  NSArray  *names;
-  NSString *name, *ext;
-  unsigned i, count;
-  NSRange  r;
-
-  names = [self fetchContentObjectNames];
-  count = [names count];
-  ext = [self defaultFilenameExtension];
-  if (count && [ext length] > 0)
-    {
-      ma = [NSMutableArray arrayWithCapacity: count];
-      for (i = 0; i < count; i++)
-        {
-          name = [names objectAtIndex: i];
-          r = [name rangeOfString: @"."];
-          if (r.length == 0)
-           name = [NSMutableString stringWithFormat: @"%@.%@", name, ext];
-          [ma addObject: name];
-        }
-
-      names = ma;
-    }
-
-  return names;
-}
-
-/* acls as a container */
-
-- (NSArray *) aclUsersForObjectAtPath: (NSArray *) objectPathArray;
-{
-  EOQualifier *qualifier;
-  NSString *qs;
-  NSArray *records;
-
-  qs = [NSString stringWithFormat: @"c_object = '/%@'",
-                [objectPathArray componentsJoinedByString: @"/"]];
-  qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
-  records = [[self ocsFolder] fetchAclMatchingQualifier: qualifier];
-
-  return [records valueForKey: @"c_uid"];
-}
-
-- (NSArray *) _fetchAclsForUser: (NSString *) uid
-               forObjectAtPath: (NSString *) objectPath
-{
-  EOQualifier *qualifier;
-  NSArray *records;
-  NSMutableArray *acls;
-  NSString *qs;
-
-  qs = [NSString stringWithFormat: @"(c_object = '/%@') AND (c_uid = '%@')",
-                objectPath, uid];
-  qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
-  records = [[self ocsFolder] fetchAclMatchingQualifier: qualifier];
-
-  acls = [NSMutableArray array];
-  if ([records count] > 0)
-    {
-      [acls addObject: SOGoRole_AuthorizedSubscriber];
-      [acls addObjectsFromArray: [records valueForKey: @"c_role"]];
-    }
-
-  return acls;
-}
-
-- (void) _cacheRoles: (NSArray *) roles
-            forUser: (NSString *) uid
-     forObjectAtPath: (NSString *) objectPath
-{
-  NSMutableDictionary *aclsForObject;
-
-  aclsForObject = [aclCache objectForKey: objectPath];
-  if (!aclsForObject)
-    {
-      aclsForObject = [NSMutableDictionary dictionary];
-      [aclCache setObject: aclsForObject
-               forKey: objectPath];
-    }
-  if (roles)
-    [aclsForObject setObject: roles forKey: uid];
-  else
-    [aclsForObject removeObjectForKey: uid];
-}
-
-- (NSArray *) aclsForUser: (NSString *) uid
-          forObjectAtPath: (NSArray *) objectPathArray
-{
-  NSArray *acls;
-  NSString *objectPath;
-  NSDictionary *aclsForObject;
-
-  objectPath = [objectPathArray componentsJoinedByString: @"/"];
-  aclsForObject = [aclCache objectForKey: objectPath];
-  if (aclsForObject)
-    acls = [aclsForObject objectForKey: uid];
-  else
-    acls = nil;
-  if (!acls)
-    {
-      acls = [self _fetchAclsForUser: uid forObjectAtPath: objectPath];
-      [self _cacheRoles: acls forUser: uid forObjectAtPath: objectPath];
-    }
-
-  if (!([acls count] || [uid isEqualToString: defaultUserID]))
-    acls = [self aclsForUser: defaultUserID
-                forObjectAtPath: objectPathArray];
-
-  return acls;
-}
-
-- (void) removeAclsForUsers: (NSArray *) users
-            forObjectAtPath: (NSArray *) objectPathArray
-{
-  EOQualifier *qualifier;
-  NSString *uids, *qs, *objectPath;
-  NSMutableDictionary *aclsForObject;
-
-  if ([users count] > 0)
-    {
-      objectPath = [objectPathArray componentsJoinedByString: @"/"];
-      aclsForObject = [aclCache objectForKey: objectPath];
-      if (aclsForObject)
-       [aclsForObject removeObjectsForKeys: users];
-      uids = [users componentsJoinedByString: @"') OR (c_uid = '"];
-      qs = [NSString
-            stringWithFormat: @"(c_object = '/%@') AND ((c_uid = '%@'))",
-            objectPath, uids];
-      qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
-      [[self ocsFolder] deleteAclMatchingQualifier: qualifier];
-    }
-}
-
-- (void) _commitRoles: (NSArray *) roles
-              forUID: (NSString *) uid
-           forObject: (NSString *) objectPath
-{
-  EOAdaptorChannel *channel;
-  GCSFolder *folder;
-  NSEnumerator *userRoles;
-  NSString *SQL, *currentRole;
-
-  folder = [self ocsFolder];
-  channel = [folder acquireAclChannel];
-  userRoles = [roles objectEnumerator];
-  currentRole = [userRoles nextObject];
-  while (currentRole)
-    {
-      SQL = [NSString stringWithFormat: @"INSERT INTO %@"
-                     @" (c_object, c_uid, c_role)"
-                     @" VALUES ('/%@', '%@', '%@')",
-                     [folder aclTableName],
-                     objectPath, uid, currentRole];
-      [channel evaluateExpressionX: SQL];
-      currentRole = [userRoles nextObject];
-    }
-
-  [folder releaseChannel: channel];
-}
-
-- (void) setRoles: (NSArray *) roles
-          forUser: (NSString *) uid
-  forObjectAtPath: (NSArray *) objectPathArray
-{
-  NSString *objectPath;
-  NSMutableArray *newRoles;
-
-  [self removeAclsForUsers: [NSArray arrayWithObject: uid]
-        forObjectAtPath: objectPathArray];
-
-  newRoles = [NSMutableArray arrayWithArray: roles];
-  [newRoles removeObject: SOGoRole_AuthorizedSubscriber];
-  [newRoles removeObject: SOGoRole_None];
-  objectPath = [objectPathArray componentsJoinedByString: @"/"];
-  [self _cacheRoles: newRoles forUser: uid
-       forObjectAtPath: objectPath];
-  if (![newRoles count])
-    [newRoles addObject: SOGoRole_None];
-
-  [self _commitRoles: newRoles forUID: uid forObject: objectPath];
-}
-
-/* acls */
-- (NSArray *) aclUsers
-{
-  return [self aclUsersForObjectAtPath: [self pathArrayToSOGoObject]];
-}
-
-- (NSArray *) aclsForUser: (NSString *) uid
-{
-  NSMutableArray *acls;
-  NSArray *ownAcls, *containerAcls;
-
-  acls = [NSMutableArray array];
-  ownAcls = [self aclsForUser: uid
-                 forObjectAtPath: [self pathArrayToSOGoObject]];
-  [acls addObjectsFromArray: ownAcls];
-  if ([container respondsToSelector: @selector (aclsForUser:)])
-    {
-      containerAcls = [container aclsForUser: uid];
-      if ([containerAcls count] > 0)
-       {
-         if ([containerAcls containsObject: SOGoRole_ObjectReader])
-           [acls addObject: SOGoRole_ObjectViewer];
-#warning this should be checked
-         if ([containerAcls containsObject: SOGoRole_ObjectEraser])
-           [acls addObject: SOGoRole_ObjectEraser];
-       }
-    }
-
-  return acls;
-}
-
-- (void) setRoles: (NSArray *) roles
-          forUser: (NSString *) uid
-{
-  return [self setRoles: roles
-               forUser: uid
-               forObjectAtPath: [self pathArrayToSOGoObject]];
-}
-
-- (void) removeAclsForUsers: (NSArray *) users
-{
-  return [self removeAclsForUsers: users
-               forObjectAtPath: [self pathArrayToSOGoObject]];
-}
-
-- (NSString *) defaultUserID
-{
-  return defaultUserID;
-}
-
-- (NSString *) httpURLForAdvisoryToUser: (NSString *) uid
-{
-  return [[self soURL] absoluteString];
-}
-
-- (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid
-{
-  return [[self davURL] absoluteString];
-}
-
 - (id) lookupName: (NSString *) lookupName
         inContext: (id) localContext
           acquire: (BOOL) acquire
@@ -713,75 +98,19 @@ static NSString *defaultUserID = @"<default>";
   return obj;
 }
 
-- (NSComparisonResult) _compareByOrigin: (SOGoFolder *) otherFolder
+- (BOOL) isFolderish
 {
-  NSArray *thisElements, *otherElements;
-  unsigned thisCount, otherCount;
-  NSComparisonResult comparison;
-
-  thisElements = [nameInContainer componentsSeparatedByString: @"_"];
-  otherElements = [[otherFolder nameInContainer]
-                   componentsSeparatedByString: @"_"];
-  thisCount = [thisElements count];
-  otherCount = [otherElements count];
-  if (thisCount == otherCount)
-    {
-      if (thisCount == 1)
-       comparison = NSOrderedSame;
-      else
-       comparison = [[thisElements objectAtIndex: 0]
-                      compare: [otherElements objectAtIndex: 0]];
-    }
-  else
-    {
-      if (thisCount > otherCount)
-       comparison = NSOrderedDescending;
-      else
-       comparison = NSOrderedAscending;
-    }
-
-  return comparison;
+  return YES;
 }
 
-- (NSComparisonResult) _compareByNameInContainer: (SOGoFolder *) otherFolder
+- (NSString *) httpURLForAdvisoryToUser: (NSString *) uid
 {
-  NSString *otherName;
-  NSComparisonResult comparison;
-
-  otherName = [otherFolder nameInContainer];
-  if ([nameInContainer hasSuffix: @"personal"])
-    {
-      if ([otherName hasSuffix: @"personal"])
-       comparison = [nameInContainer compare: otherName];
-      else
-       comparison = NSOrderedAscending;
-    }
-  else
-    {
-      if ([otherName hasSuffix: @"personal"])
-       comparison = NSOrderedDescending;
-      else
-       comparison = NSOrderedSame;
-    }
-
-  return comparison;
+  return [[self soURL] absoluteString];
 }
 
-- (NSComparisonResult) compare: (SOGoFolder *) otherFolder
+- (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid
 {
-  NSComparisonResult comparison;
-
-  comparison = [self _compareByOrigin: otherFolder];
-  if (comparison == NSOrderedSame)
-    {
-      comparison = [self _compareByNameInContainer: otherFolder];
-      if (comparison == NSOrderedSame)
-       comparison
-         = [[self displayName]
-             localizedCaseInsensitiveCompare: [otherFolder displayName]];
-    }
-
-  return comparison;
+  return [[self davURL] absoluteString];
 }
 
 /* WebDAV */
@@ -796,6 +125,11 @@ static NSString *defaultUserID = @"<default>";
   return [self isFolderish];
 }
 
+- (NSString *) davContentType
+{
+  return @"httpd/unix-directory";
+}
+
 /* folder type */
 
 - (NSString *) outlookFolderClass
@@ -805,20 +139,11 @@ static NSString *defaultUserID = @"<default>";
   return nil;
 }
 
-/* description */
-
-- (void) appendAttributesToDescription: (NSMutableString *) _ms
-{
-  [super appendAttributesToDescription:_ms];
-  
-  [_ms appendFormat:@" ocs=%@", [self ocsPath]];
-}
+/* acls */
 
-- (NSString *) loggingPrefix
+- (NSArray *) aclsForUser: (NSString *) uid
 {
-  return [NSString stringWithFormat:@"<0x%08X[%@]:%@>",
-                  self, NSStringFromClass([self class]),
-                  [self nameInContainer]];
+  return nil;
 }
 
-@end /* SOGoFolder */
+@end
index abb9acb1f9641ccad2538bd8e470716220555f09..18aec4014d07baed2950c851b1aedb662425fa21 100644 (file)
@@ -1017,4 +1017,11 @@ static BOOL kontactGroupDAV = YES;
   return ms;
 }
 
+- (NSString *) loggingPrefix
+{
+  return [NSString stringWithFormat:@"<0x%08X[%@]:%@>",
+                  self, NSStringFromClass([self class]),
+                  [self nameInContainer]];
+}
+
 @end /* SOGoObject */
index c54d08f877d166ee7e55c4bb73de249687f070a2..3001e6b3bfb87463631b5eaea3e187c0184439d3 100644 (file)
 #ifndef SOGOPARENTFOLDERS_H
 #define SOGOPARENTFOLDERS_H
 
-#import "SOGoObject.h"
+#import "SOGoFolder.h"
 
 @class NSMutableDictionary;
 @class NSString;
 @class WOResponse;
 
-@interface SOGoParentFolder : SOGoObject
+@interface SOGoParentFolder : SOGoFolder
 {
   NSMutableDictionary *subFolders;
   NSString *OCSPath;
 + (NSString *) gcsFolderType;
 + (Class) subFolderClass;
 
+- (NSString *) defaultFolderName;
+
 - (void) setBaseOCSPath: (NSString *) newOCSPath;
 
 - (NSArray *) subFolders;
 
+- (NSException *) newFolderWithName: (NSString *) name
+                andNameInContainer: (NSString *) newNameInContainer;
 - (NSException *) newFolderWithName: (NSString *) name
                    nameInContainer: (NSString **) newNameInContainer;
 
index 224fffbafa8fff74f4ad62b11e247c43b9c03efe..a06e39c9cf21a9d849a18f878bc873a5805fb4fd 100644 (file)
@@ -31,7 +31,7 @@
 #import <GDLContentStore/NSURL+GCS.h>
 #import <GDLAccess/EOAdaptorChannel.h>
 
-#import "SOGoFolder.h"
+#import "SOGoGCSFolder.h"
 #import "SOGoUser.h"
 
 #import "SOGoParentFolder.h"
@@ -86,9 +86,9 @@
 {
   NSArray *attrs;
   NSDictionary *row;
-  SOGoFolder *folder;
+  SOGoGCSFolder *folder;
   BOOL hasPersonal;
-  NSString *key, *path, *personalName;
+  NSString *key;
 
   if (!subFolderClass)
     subFolderClass = [[self class] subFolderClass];
       row = [fc fetchAttributes: attrs withZone: NULL];
     }
 
-  if (!hasPersonal)
-    {
-      folder = [subFolderClass objectWithName: @"personal" inContainer: self];
-      personalName = [self labelForKey: [self defaultFolderName]];
-      [folder setDisplayName: personalName];
-      path = [NSString stringWithFormat: @"/Users/%@/%@/personal",
-                      [self ownerInContext: context],
-                      nameInContainer];
-      [folder setOCSPath: path];
-      [subFolders setObject: folder forKey: @"personal"];
-    }
+//   if (!hasPersonal)
+//     {
+//       folder = [subFolderClass objectWithName: @"personal" inContainer: self];
+//       personalName = [self labelForKey: [self defaultFolderName]];
+//       [folder setDisplayName: personalName];
+//       path = [NSString stringWithFormat: @"/Users/%@/%@/personal",
+//                    [self ownerInContext: context],
+//                    nameInContainer];
+//       [folder setOCSPath: path];
+//       [subFolders setObject: folder forKey: @"personal"];
+//     }
 }
 
 - (void) appendPersonalSources
   NSUserDefaults *settings;
   NSEnumerator *allKeys;
   NSString *currentKey;
-  SOGoFolder *subscribedFolder;
+  SOGoGCSFolder *subscribedFolder;
 
   settings = [[context activeUser] userSettings];
   subscribedReferences = [[settings objectForKey: nameInContainer]
 }
 
 - (NSException *) newFolderWithName: (NSString *) name
-                   nameInContainer: (NSString **) newNameInContainer
+                andNameInContainer: (NSString *) newNameInContainer
 {
   NSString *newFolderID;
-  SOGoFolder *newFolder;
+  SOGoGCSFolder *newFolder;
   NSException *error;
 
   if (!subFolderClass)
     subFolderClass = [[self class] subFolderClass];
 
-  *newNameInContainer = nil;
-  newFolderID = [self globallyUniqueObjectId];
   newFolder = [subFolderClass objectWithName: newFolderID inContainer: self];
   if ([newFolder isKindOfClass: [NSException class]])
     error = (NSException *) newFolder;
       [newFolder setOCSPath: [NSString stringWithFormat: @"%@/%@",
                                        OCSPath, newFolderID]];
       if ([newFolder create])
-       {
-         error = nil;
-         *newNameInContainer = newFolderID;
-       }
+       error = nil;
       else
         error = [NSException exceptionWithHTTPStatus: 400
                             reason: @"The new folder could not be created"];
   return error;
 }
 
+- (NSException *) newFolderWithName: (NSString *) name
+                   nameInContainer: (NSString **) newNameInContainer
+{
+  NSString *newFolderID;
+  NSException *error;
+
+  newFolderID = [self globallyUniqueObjectId];
+  error = [self newFolderWithName: name
+               andNameInContainer: newFolderID];
+  if (error)
+    *newNameInContainer = nil;
+  else
+    *newNameInContainer = newFolderID;
+
+  return error;
+}
+
 - (void) initSubFolders
 {
   NSString *login;
           sortedArrayUsingSelector: @selector (compare:)];
 }
 
-/* acls */
-- (NSArray *) aclsForUser: (NSString *) uid
-{
-  return nil;
-}
-
-- (BOOL) davIsCollection
-{
-  return YES;
-}
-
-- (NSString *) davContentType
-{
-  return @"httpd/unix-directory";
-}
-
 @end
index 7f52d41f138f6f08cf43d18aec5c3dfc8fa7b256..970f5e8430bd716e45500849465fc0f2ed56ab45 100644 (file)
 
 - (NSString *) ownerInContext: (WOContext *) _ctx;
 
-/* pathes */
-
-- (NSString *) ocsUserPath;
-- (NSString *) ocsPrivateCalendarPath;
-
 /* TODO: not implemented, bad bad */
 // - (id)lookupFreeBusyObject;
 
index 84297af23ed8f717571871c7e77f176c4c4e992a..5003c54d26f1a8a52783ac5974b412d358443faf 100644 (file)
@@ -68,7 +68,8 @@
 
   if (!children)
     children = [[NSArray alloc] initWithObjects:
-                                 @"Calendar", @"Contacts", @"Mail", nil];
+                                 @"Calendar", @"Contacts", @"Mail",
+                               @"Preferences",  nil];
 
   return children;
 }
 //   return [self lookupName: @"Groups" inContext: nil acquire: NO];
 // }
 
-/* pathes */
-
-- (void) setOCSPath: (NSString *) _path
-{
-  [self warnWithFormat:
-          @"rejected attempt to reset user-folder path: '%@'", _path];
-}
-
-- (NSString *) ocsPath
-{
-  return [NSString stringWithFormat: @"/Users/%@", nameInContainer];
-}
-
-- (NSString *) ocsUserPath
-{
-  return [self ocsPath];
-}
-
-- (BOOL) folderIsMandatory
-{
-  return NO;
-}
-
-- (NSString *) ocsPrivateCalendarPath
-{
-  return [[self ocsUserPath] stringByAppendingString:@"/Calendar"];
-}
-
-- (NSString *) ocsPrivateContactsPath
-{
-  return [[self ocsUserPath] stringByAppendingString:@"/Contacts"];
-}
-
 /* name lookup */
 
 // - (NSString *) permissionForKey: (NSString *) key
   SOGoAppointmentFolders *calendars;
   
   calendars = [$(@"SOGoAppointmentFolders") objectWithName: _key inContainer: self];
-  [calendars setBaseOCSPath: [self ocsPrivateCalendarPath]];
+  [calendars setBaseOCSPath: [NSString stringWithFormat: @"/Users/%@/Calendar",
+                                      nameInContainer]];
 
   return calendars;
 }
   SOGoContactFolders *contacts;
 
   contacts = [$(@"SOGoContactFolders") objectWithName:_key inContainer: self];
-  [contacts setBaseOCSPath: [self ocsPrivateContactsPath]];
+  [contacts setBaseOCSPath: [NSString stringWithFormat: @"/Users/%@/Contacts",
+                                     nameInContainer]];
 
   return contacts;
 }
 //         obj = [self groupsFolder: _key inContext: _ctx];
       else if ([_key isEqualToString: @"Mail"])
         obj = [self mailAccountsFolder: _key inContext: _ctx];
+      else if ([_key isEqualToString: @"Preferences"])
+        obj = [$(@"SOGoPreferencesFolder") objectWithName: _key
+               inContainer: self];
       else if ([_key isEqualToString: @"freebusy.ifb"])
         obj = [self freeBusyObject:_key inContext: _ctx];
       else
index 8794bbeabfe8cb5983b3f10b7c77b056b1461fc0..96b6cbc158647630a9f8c3f8dbf3035a4741a379 100644 (file)
 @class NSMutableDictionary;
 
 @class LDAPUserManager;
-@class SOGoFolder;
+@class SOGoGCSFolder;
 
 @interface UIxFolderActions : WODirectAction
 {
-  SOGoFolder *clientObject;
+  SOGoGCSFolder *clientObject;
   LDAPUserManager *um;
   NSUserDefaults *ud;
   NSString *owner;
index 1c2d59b05e561fea66eb1dfefc2422bb5dd8cffe..44d21f6d3633eb9d62aec1ba0d53dd173032c635 100644 (file)
@@ -35,9 +35,9 @@
 
 #import <SoObjects/SOGo/LDAPUserManager.h>
 #import <SoObjects/SOGo/NSArray+Utilities.h>
-#import <SoObjects/SOGo/SOGoUser.h>
-#import <SoObjects/SOGo/SOGoFolder.h>
+#import <SoObjects/SOGo/SOGoGCSFolder.h>
 #import <SoObjects/SOGo/SOGoPermissions.h>
+#import <SoObjects/SOGo/SOGoUser.h>
 
 #import "WODirectAction+SOGo.h"
 
index b9b6d7e7e1c1d6c94b09316f71cb7b4e584a7539..157e7ace7138b45abc2c9b865ee0c9e389f0fe22 100644 (file)
@@ -71,7 +71,7 @@
        };
       };
     };
-    SOGoFolder = {
+    SOGoGCSFolder = {
       methods = {
        subscribe = {
          protectedBy = "<public>";
index 6f395411204dca8ff4115475fdc02863bd45104c..40842b648495d1fa76f7290cb8ba618991e54142 100644 (file)
           Update: remember that there are group folders as well.
   */
   NSString *uri, *objectId, *nextMethod;
-  id <SOGoContactFolder> co;
+  SOGoObject <SOGoContactFolder> *co;
 
   co = [self clientObject];
   if ([co respondsToSelector: @selector (globallyUniqueObjectId)])
index fa43d81097a2976d302d30970ab4c367248d85de..8adba727cc027cca601e0ecaeed7a2dc27c6d6d3 100644 (file)
 {
   NSMutableArray *folders;
   NSEnumerator *subfolders;
-  SOGoFolder *currentFolder;
+  SOGoGCSFolder *currentFolder;
   NSString *folderName;
   NSMutableDictionary *currentDictionary;
   SoSecurityManager *securityManager;
index 3602be7ae0561a544a7a4797da30870c3a315a86..1168ddcf25f954b2ffcb0bd8880f9b405b50a1fe 100644 (file)
               actionName  = "delete";
            };
            edit = {
-              protectedBy = "Change Images And Files";
+              protectedBy = "Access Contents Information";
               pageName    = "UIxContactEditor";
            };
            save = {
              protectedBy = "<public>";
               pageName    = "UIxContactView";
            };
-           delete = {
+/*           delete = {
               protectedBy = "View";
               pageName    = "UIxContactView";
               actionName  = "delete";
-           };
+           }; */
            edit = {
-              protectedBy = "View";
+              protectedBy = "Access Contents Information";
               pageName    = "UIxContactEditor";
            };
-           save = {
+/*           save = {
               protectedBy = "View";
               pageName    = "UIxContactEditor";
               actionName  = "save";
               protectedBy = "View";
               pageName    = "UIxContactEditor";
               actionName  = "write";
-           };
+           }; */
         };
      };
   };
index 9c0bba206c94bf5050f0de0f326b9f35c3411f63..664e4cf52e899820ef66f741909f67c93d33d0a1 100644 (file)
@@ -49,7 +49,7 @@
       };
     };
     SOGoParentFolder = {
-      superclass = "SOGoObject";
+      superclass = "SOGoFolder";
       protectedBy = "Access Contents Information";
       defaultRoles = {
        "Access Contents Information" = ( "Authenticated" );
index d216c0fe6bdff64e98a47086cef66ef39cddc111..b9f0e76107edbc9b417561d5e2ddc00e3728cb05 100644 (file)
@@ -6,6 +6,7 @@
 "General" = "General";
 "Calendar Options" = "Calendar Options";
 "Mail Options" = "Mail Options";
+"Identities" = "Identities";
 "Password" = "Password";
 
 /* ooo */
@@ -82,6 +83,9 @@
 "messageforward_inline" = "Inline";
 "messageforward_attached" = "As Attachment";
 
+"Default identity:" = "Default identity:";
+"Manage identities..." = "Manage identities...";
+
 /* password */
 "New password:" = "New password:";
 "Confirmation:" = "Confirmation:";
index 99d333873e5618b8f460d380275a8131c4f50b6f..4fe9850ed2a77ebd39f9eb3410e95a7d474c050a 100644 (file)
@@ -6,6 +6,7 @@
 "General" = "Général";
 "Calendar Options" = "Calendrier";
 "Mail Options" = "Courrier";
+"Identities" = "Identités";
 "Password" = "Mot de passe";
 
 /* ooo */
 "messageforward_inline" = "intégrés";
 "messageforward_attached" = "en pièces jointes";
 
+/* Identities */
+"Default identity:" = "Identité par défaut :";
+"Manage identities..." = "Gérer les identitiés...";
+
 /* password */
 "New password:" = "Nouveau mot de passe :";
 "Confirmation:" = "Confirmation :";
index e25c85fb068837f9fe07a40ee302a64e4da7a79e..63da5cd621819e42d775fe089434f56775a7d92a 100644 (file)
@@ -6,6 +6,7 @@
 "General" = "Allgemein";
 "Calendar Options" = "Kalender";
 "Mail Options" = "E-Mail";
+"Identities" = "Identities";
 "Password" = "Passwort";
 
 /* ooo */
@@ -79,6 +80,9 @@
 "messageforward_inline" = "Eingebunden";
 "messageforward_attached" = "Als Anhang";
 
+"Default identity:" = "Default identity:";
+"Manage identities..." = "Manage identities...";
+
 /* password */
 "New password:" = "Neues Passwort:";
 "Confirmation:" = "Bestätigung:";
index 0b18a97b889d63dc9e1b4a378f352e23e3f1726b..de9055939ddeeb701e06fefffea22221930b9c68 100644 (file)
 
 @implementation UIxJSONPreferences
 
-- (WOResponse *) _makeResponse: (NSString *) jsonText
+- (WOResponse *) _makeResponse: (NSUserDefaults *) defaults
 {
   WOResponse *response;
 
   response = [context response];
   [response setHeader: @"text/plain; charset=utf-8"
            forKey: @"content-type"];
-  [response appendContentString: jsonText];
+  [response appendContentString: [defaults jsonRepresentation]];
 
   return response;
 }
@@ -51,7 +51,7 @@
 
   defaults = [[context activeUser] userDefaults];
 
-  return [self _makeResponse: [defaults jsonRepresentation]];
+  return [self _makeResponse: defaults];
 }
 
 - (WOResponse *) jsonSettingsAction
@@ -60,7 +60,7 @@
 
   settings = [[context activeUser] userSettings];
 
-  return [self _makeResponse: [settings jsonRepresentation]];
+  return [self _makeResponse: settings];
 }
 
 @end
index 5570fbc7e49615da23ad7d0a26aac5be7f0a0837..c97889248f6784c78bbb05a87fa02af38cca40ba 100644 (file)
@@ -32,7 +32,7 @@
 
 @interface UIxPreferences : UIxComponent
 {
-  NSString *item;
+  id item;
   SOGoUser *user;
   NSUserDefaults *userDefaults;
   NSCalendarDate *today;
index 0a6c33ef17938cc175468afed210ea384df4a54a..958675336d3381bc37ee272fdb42e99a6be7e8b0 100644 (file)
@@ -28,6 +28,7 @@
 #import <NGObjWeb/WOContext.h>
 #import <NGObjWeb/WORequest.h>
 
+#import <SoObjects/SOGo/NSDictionary+Utilities.h>
 #import <SoObjects/SOGo/SOGoUser.h>
 
 #import "UIxPreferences.h"
@@ -466,6 +467,35 @@ static BOOL shouldDisplayPasswordChange = NO;
   [userDefaults setObject: newMessageForwarding forKey: @"MessageForwarding"];
 }
 
+//     <label><var:string label:value="Default identity:"/>
+//       <var:popup list="identitiesList" item="item"
+//         string="itemIdentityText" selection="defaultIdentity"/></label>
+- (NSArray *) identitiesList
+{
+  return [user allIdentities];
+}
+
+- (NSString *) itemIdentityText
+{
+  return [item keysWithFormat: @"%{fullName} <%{email}>"];
+}
+
+- (NSDictionary *) defaultIdentity
+{
+  NSDictionary *currentIdentity, *defaultIdentity;
+  NSEnumerator *identities;
+
+  defaultIdentity = nil;
+
+  identities = [[user allIdentities] objectEnumerator];
+  while (!defaultIdentity
+        && (currentIdentity = [identities nextObject]))
+    if ([[currentIdentity objectForKey: @"isDefault"] boolValue])
+      defaultIdentity = currentIdentity;
+
+  return defaultIdentity;
+}
+
 - (id <WOActionResults>) defaultAction
 {
   id <WOActionResults> results;
index de4a1d90d6d867e45f79d98f589b3023b46a0789..2891bffa12c5667d3cb9dd7e3e7e1e6095b0f445 100644 (file)
              protectedBy = "View";
              pageName = "UIxPreferences";
           };
+          identities = {
+             protectedBy = "View";
+             pageName = "UIxIdentities";
+          };
           jsonDefaults = {
              protectedBy = "View";
              actionClass = "UIxJSONPreferences";
index 8f771dedab9d5a0a934a8aa1077a18dc4cfc8a5c..046ae8599c00f40dcd3ae2c55f8e67c1220ceccd 100644 (file)
@@ -5,6 +5,9 @@
     xmlns:const="http://www.skyrix.com/od/constant"
     xmlns:label="OGo:label"
     >
+    <span id="toolbar">
+    </span>
+
     <div class="menu" id="searchMenu">
       <ul id="searchOptions" class="choiceMenu">
         <li id="name_or_address"><var:string
index dd0ca1af288797e61485180443903964bbbdfd4a..3bf8804b587f0cb0804ead2bc916a2e744cd44a8 100644 (file)
@@ -19,6 +19,8 @@
            label:value="Calendar Options"/></li>
        <li target="mailOptionsView"><var:string
            label:value="Mail Options"/></li>
+<!--   <li target="identitiesView"><var:string
+           label:value="Identities"/></li> -->
        <var:if condition="shouldDisplayPasswordChange">
          <li target="passwordView"><var:string label:value="Password"/></li>
        </var:if>
        <textarea const:name="autoReplyText" var:value="autoReplyText"/>
       </label> -->
       </div>
+      <div id="identitiesView" class="tab">
+       <var:multiselection id="identitiesList" item="item"
+         string="itemIdentityText" selection="defaultIdentity">
+       </var:multiselection>
+       <br/>
+      </div>
       <var:if condition="shouldDisplayPasswordChange">
        <div id="passwordView" class="tab">
          <label><var:string label:value="New password:"
index dc2a9a021c79529335115fa8bf1d720489ad1b63..e5c3d160cf5a2ae14c4e6b6385da844d1b762636 100644 (file)
@@ -333,6 +333,9 @@ function onToolbarWriteToSelectedContacts(event) {
   var rows = contactsList.getSelectedRowsId();
   var rowsWithEmail = 0;
 
+  if (rows.length == 0)
+    return false;
+
   for (var i = 0; i < rows.length; i++) {
     var emailCell = $(rows[i]).down('td', 1);
     if (emailCell.firstChild) { // .nodeValue is the contact email address
@@ -341,7 +344,7 @@ function onToolbarWriteToSelectedContacts(event) {
                            + "/" + rows[i] + "/write");
     }
   }
-  
+
   if (rowsWithEmail == 0) {
     window.alert(labels["The selected contact has no email address."]);
   }
index 9bb9fcccd8cbedb1e803e938ca0d5d35773bd219..cc844680598a626f11ca09890333e740b2f9743e 100644 (file)
@@ -470,10 +470,13 @@ function messageListCallback(http) {
     if (table) {
       // Update table
       var thead = table.tHead;
+      var addressHeaderCell = thead.rows[0].cells[3];
       var tbody = table.tBodies[0];
       var tmp = document.createElement('div');
       $(tmp).update(http.responseText);
       thead.rows[1].parentNode.replaceChild(tmp.firstChild.tHead.rows[1], thead.rows[1]);
+      addressHeaderCell.replaceChild(tmp.firstChild.tHead.rows[0].cells[3].lastChild, 
+                                    addressHeaderCell.lastChild);
       table.replaceChild(tmp.firstChild.tBodies[0], tbody);
     }
     else {
@@ -1173,7 +1176,7 @@ function initMailboxTree() {
   mailboxTree.pendingRequests = mailAccounts.length;
   activeAjaxRequests += mailAccounts.length;
   for (var i = 0; i < mailAccounts.length; i++) {
-    var url = ApplicationBaseURL + "/" + mailAccounts[i] + "/mailboxes";
+    var url = ApplicationBaseURL + mailAccounts[i] + "/mailboxes";
     triggerAjaxRequest(url, onLoadMailboxesCallback, mailAccounts[i]);
   }
 }
index 361c0708dd8a4a8d6d0e2927f50180a342344ee2..15f575847498c7c6e92726b574f321b83b7ddc22 100644 (file)
@@ -383,7 +383,8 @@ function tasksListCallback(http) {
        list.appendChild(listItem);
        Event.observe(listItem, "mousedown", listRowMouseDownHandler);
        Event.observe(listItem, "click", onRowClick);
-       Event.observe(listItem, "dblclick", editDoubleClickedEvent.bindAsEventListener(listItem));
+       Event.observe(listItem, "dblclick",
+                     editDoubleClickedEvent.bindAsEventListener(listItem));
        listItem.setAttribute("id", data[i][0]);
        $(listItem).addClassName(data[i][5]);
        listItem.calendar = data[i][1];
@@ -470,16 +471,16 @@ function changeDateSelectorDisplay(day, keepCurrentDay) {
   }
 }
 
-function changeCalendarDisplay(time, newView) {
+function changeCalendarDisplay(data, newView) {
   var url = ApplicationBaseURL + "/" + ((newView) ? newView : currentView);
 
   selectedCalendarCell = null;
 
   var day = null;
-  var hour = null;
-  if (time) {
-    day = time['day'];
-    hour = time['hour'];
+  var scrollEvent = null;
+  if (data) {
+    day = data['day'];
+    scrollEvent = data['scrollEvent'];
   }
 
   if (!day)
@@ -498,7 +499,9 @@ function changeCalendarDisplay(time, newView) {
   }
   document.dayDisplayAjaxRequest
      = triggerAjaxRequest(url, calendarDisplayCallback,
-                         { "view": newView, "day": day, "hour": hour });
+                         { "view": newView,
+                           "day": day,
+                           "scrollEvent": scrollEvent });
 
   return false;
 }
@@ -526,25 +529,26 @@ function onMonthOverview() {
   return _ensureView("monthview");
 }
 
-function scrollDayView(hour) {
-  var rowNumber;
-  if (hour) {
-    if (hour.length == 3)
-      rowNumber = parseInt(hour.substr(0, 1));
-    else {
-      if (hour.substr(0, 1) == "0")
-        rowNumber = parseInt(hour.substr(1, 1));
-      else
-        rowNumber = parseInt(hour.substr(0, 2));
-    }
-  } else
-    rowNumber = 8;
-
+function scrollDayView(scrollEvent) {
+  var offset = 0;
   var daysView = $("daysView");
   var hours =
-     $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
-  if (hours.length > 0)
-    daysView.scrollTop = hours[rowNumber].offsetTop;
+    $(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
+
+  if (scrollEvent && scrollEvent.siblings) {
+    var classes = scrollEvent.siblings[0].getAttribute("class").split(" ");
+    for (var i = 0; i < classes.length; i++) {
+      if (classes[i].startsWith("starts")) {
+       var starts = parseInt(classes[i].substr(6)) / 4;
+       offset = hours[starts].offsetTop;
+      }
+    }
+  }
+  else {
+    offset = hours[8].offsetTop;
+  }
+
+  daysView.scrollTop = offset - 5;
 }
 
 function onClickableCellsDblClick(event) {
@@ -633,8 +637,6 @@ function drawCalendarEvent(eventData, sd, ed) {
 
    var days = startDate.daysUpTo(endDate);
 
-   var divs = new Array();
-
    var title;
    if (currentView == "monthview"
        && (eventData[7] == 0))
@@ -721,8 +723,12 @@ function drawCalendarEvent(eventData, sd, ed) {
            }
         }
         if (parentDiv)
-           parentDiv.appendChild(eventDiv);
+          parentDiv.appendChild(eventDiv);
       }
+
+   var eventTR = $(eventData[0]);
+   if (eventTR)
+     eventTR.siblings = siblings;
 }
 
 function newEventDIV(cname, calendar, starts, lasts,
@@ -785,22 +791,22 @@ function calendarDisplayCallback(http) {
     if (http.callbackData["day"])
       currentDay = http.callbackData["day"];
 
-    var hour = null;
-    if (http.callbackData["hour"])
-      hour = http.callbackData["hour"];
     var contentView;
     if (currentView == "monthview")
       contentView = $("calendarContent");
     else {
-      scrollDayView(hour);
+      var scrollEvent = http.callbackData.scrollEvent;
+      scrollDayView($(scrollEvent));
       contentView = $("daysView");
     }
     refreshCalendarEvents();
     var days = document.getElementsByClassName("day", contentView);
     if (currentView == "monthview")
       for (var i = 0; i < days.length; i++) {
-        Event.observe(days[i], "click",  onCalendarSelectDay.bindAsEventListener(days[i]));
-        Event.observe(days[i], "dblclick",  onClickableCellsDblClick.bindAsEventListener(days[i]));
+        Event.observe(days[i], "click",
+                     onCalendarSelectDay.bindAsEventListener(days[i]));
+        Event.observe(days[i], "dblclick",
+                     onClickableCellsDblClick.bindAsEventListener(days[i]));
       }
     else {
        var headerDivs = $("calendarHeader").childNodesWithTag("div"); 
@@ -966,12 +972,10 @@ function onListFilterChange() {
   return refreshEvents();
 }
 
-function onEventClick(event) { log ("onEventClick");
-  var day = this.day;
-  var hour = this.hour;
-
-  changeCalendarDisplay( { "day": day, "hour": hour} );
-  changeDateSelectorDisplay(day);
+function onEventClick(event) {
+  changeCalendarDisplay( { "day": this.day,
+                          "scrollEvent": this.getAttribute("id") } );
+  changeDateSelectorDisplay(this.day);
 
   return onRowClick(event);
 }
@@ -1485,28 +1489,23 @@ function appendCalendar(folderName, folderPath) {
     
     // Update CSS for events color
     if (!document.styleSheets) return;
-    var theRules = new Array();
-    var lastSheet = document.styleSheets[document.styleSheets.length - 1];
-    if (lastSheet.insertRule) { // Mozilla
-      lastSheet.insertRule('.calendarFolder' + folderPath.substr(1) + ' {'
-                          + ' background-color: '
-                          + color
-                          + ' !important; }', 0);
-      lastSheet.insertRule('div.colorBox.calendarFolder' + folderPath.substr(1) + ' {'
-                          + ' color: '
-                          + color
-                          + ' !important; }', 0);
-    }
-    else { // IE
-      lastSheet.addRule('.calendarFolder' + folderPath.substr(1),
-                       ' background-color: '
-                       + color
-                       + ' !important; }');
-      lastSheet.addRule('div.colorBox.calendarFolder' + folderPath.substr(1),
-                       ' color: '
-                       + color
-                       + ' !important; }');
-    }
+    
+    var styleElement = document.createElement("style");
+    styleElement.type = "text/css";
+    var selectors = [
+                    '.calendarFolder' + folderPath.substr(1),
+                    'div.colorBox.calendarFolder' + folderPath.substr(1)
+                    ];
+    var rules = [
+                ' { background-color: ' + color + ' !important; }',
+                ' { color: ' + color + ' !important; }'
+                ];
+    for (var i = 0; i < rules.length; i++)
+      if (styleElement.styleSheet && styleElement.styleSheet.addRule)
+       styleElement.styleSheet.addRule(selectors[i], rules[i]); // IE
+      else
+       styleElement.appendChild(document.createTextNode(selectors[i] + rules[i])); // Mozilla _+ Safari
+    document.getElementsByTagName("head")[0].appendChild(styleElement);
   }
 }
 
index 39dc38ddb0548e2dadd57630395f5a89b12f7581..2f742cacf60e4cab31b437d22d5aa3ad2b8091c4 100644 (file)
@@ -33,6 +33,9 @@ IMG#progressIndicator
   margin-top: 1.5em;
   margin-right: 1em; }
 
+SPAN#toolbar IMG#progressIndicator
+{ margin-top: 0.75em; }
+
 DIV#pageContent
 { clear: both; }
 
index 78298291e065321b38446fab681e13e08b7a03c8..47c0975313fcc64cb3d2b8cd9abbd1b0ed7601f2 100644 (file)
@@ -150,7 +150,8 @@ function URLForFolderID(folderID) {
   var url;
   if (folderInfos.length > 1) {
     url = UserFolderURL + "../" + folderInfos[0];
-    if (!folderInfos[1].startsWith('/'))
+    if (!(folderInfos[0].endsWith('/')
+         || folderInfos[1].startsWith('/')))
       url += '/';
     url += folderInfos[1];
   }
@@ -292,7 +293,7 @@ function triggerAjaxRequest(url, callback, userdata) {
   var http = createHTTPClient();
 
   activeAjaxRequests += 1;
-  document.animTimer = setTimeout("checkAjaxRequestsState();", 200);
+  document.animTimer = setTimeout("checkAjaxRequestsState();", 50);
   //url = appendDifferentiator(url);
 
   if (http) {