]> err.no Git - scalable-opengroupware.org/blobdiff - SoObjects/Mailer/SOGoMailAccount.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1243 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SoObjects / Mailer / SOGoMailAccount.m
index 93927275bf710296377670c6c43500f14a58af31..4f2f59110399c4e5804d4d78f4b419e61447b306 100644 (file)
 #import <NGExtensions/NSNull+misc.h>
 #import <NGImap4/NGImap4Connection.h>
 
+#import <SoObjects/SOGo/NSArray+Utilities.h>
+#import <SoObjects/SOGo/SOGoUser.h>
+
+#import "SOGoDraftsFolder.h"
 #import "SOGoMailFolder.h"
 #import "SOGoMailManager.h"
-#import "SOGoDraftsFolder.h"
-#import "SOGoUser+Mail.h"
+#import "SOGoSentFolder.h"
+#import "SOGoTrashFolder.h"
 
 #import "SOGoMailAccount.h"
 
 @implementation SOGoMailAccount
 
-static NSArray  *rootFolderNames      = nil;
-static NSString *inboxFolderName      = @"INBOX";
-static NSString *draftsFolderName     = @"Drafts";
-static NSString *sieveFolderName      = @"Filters";
+static NSArray *rootFolderNames = nil;
+static NSString *inboxFolderName = @"INBOX";
+static NSString *draftsFolderName = @"Drafts";
+static NSString *sieveFolderName = @"Filters";
 static NSString *sentFolderName = nil;
 static NSString *trashFolderName = nil;
-static NSString *sharedFolderName     = @""; // TODO: add English default
+static NSString *sharedFolderName = @""; // TODO: add English default
 static NSString *otherUsersFolderName = @""; // TODO: add English default
-static BOOL     useAltNamespace       = NO;
 
-+ (void)initialize {
++ (void) initialize
+{
   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
   NSString *cfgDraftsFolderName;
 
-  useAltNamespace = [ud boolForKey:@"SOGoSpecialFoldersInRoot"];
-  
   sharedFolderName = [ud stringForKey:@"SOGoSharedFolderName"];
   otherUsersFolderName = [ud stringForKey:@"SOGoOtherUsersFolderName"];
   cfgDraftsFolderName = [ud stringForKey:@"SOGoDraftsFolderName"];
@@ -82,22 +84,43 @@ static BOOL     useAltNamespace       = NO;
 
   NSLog(@"Note: using shared-folders name:      '%@'", sharedFolderName);
   NSLog(@"Note: using other-users-folders name: '%@'", otherUsersFolderName);
-  if ([ud boolForKey:@"SOGoEnableSieveFolder"]) {
+  if ([ud boolForKey: @"SOGoEnableSieveFolder"])
     rootFolderNames = [[NSArray alloc] initWithObjects:
                                        draftsFolderName, 
                                        sieveFolderName, 
                                      nil];
-  }
-  else {
+  else
     rootFolderNames = [[NSArray alloc] initWithObjects:
                                        draftsFolderName, 
                                      nil];
-  }
+}
+
+- (id) init
+{
+  if ((self = [super init]))
+    {
+      inboxFolder = nil;
+      draftsFolder = nil;
+      sentFolder = nil;
+      trashFolder = nil;
+    }
+
+  return self;
+}
+
+- (void) dealloc
+{
+  [inboxFolder release];
+  [draftsFolder release];
+  [sentFolder release];
+  [trashFolder release];
+  [super dealloc];  
 }
 
 /* shared accounts */
 
-- (BOOL)isSharedAccount {
+- (BOOL) isSharedAccount
+{
   NSString *s;
   NSRange  r;
   
@@ -110,23 +133,29 @@ static BOOL     useAltNamespace       = NO;
   return [s rangeOfString:@".-."].length > 0 ? YES : NO;
 }
 
-- (NSString *)sharedAccountName {
+- (NSString *) sharedAccountName
+{
   return nil;
 }
 
 /* listing the available folders */
 
-- (NSArray *)additionalRootFolderNames {
+- (NSArray *) additionalRootFolderNames
+{
   return rootFolderNames;
 }
 
+- (BOOL) isInDraftsFolder
+{
+  return NO;
+}
+
 - (NSArray *) toManyRelationshipKeys
 {
   NSMutableArray *folders;
   NSArray *imapFolders, *additionalFolders;
 
-  folders = [NSMutableArray new];
-  [folders autorelease];
+  folders = [NSMutableArray array];
 
   imapFolders = [[self imap4Connection] subfoldersForURL: [self imap4URL]];
   additionalFolders = [self additionalRootFolderNames];
@@ -137,49 +166,49 @@ static BOOL     useAltNamespace       = NO;
       [folders removeObjectsInArray: additionalFolders];
       [folders addObjectsFromArray: additionalFolders];
     }
-
+  
   return folders;
 }
 
-/* identity */
-
-- (SOGoMailIdentity *)preferredIdentity {
-  return [[context activeUser] primaryMailIdentityForAccount:
-                                [self nameInContainer]];
-}
-
 /* hierarchy */
 
-- (SOGoMailAccount *)mailAccountFolder {
+- (SOGoMailAccount *) mailAccountFolder
+{
   return self;
 }
 
 - (NSArray *) allFolderPaths
 {
-  NSMutableArray *newFolders;
+  NSMutableArray *folderPaths;
   NSArray *rawFolders, *mainFolders;
 
-  rawFolders = [[self imap4Connection]
-                allFoldersForURL: [self imap4URL]];
+  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];
+  mainFolders = [[NSArray arrayWithObjects:
+                           [self inboxFolderNameInContext: context],
+                         [self draftsFolderNameInContext: context],
+                         [self sentFolderNameInContext: context],
+                         [self trashFolderNameInContext: context],
+                         nil] stringsWithFormat: @"/%@"];
+  folderPaths = [NSMutableArray arrayWithArray: rawFolders];
+  [folderPaths removeObjectsInArray: mainFolders];
+  [folderPaths
+    sortUsingSelector: @selector (localizedCaseInsensitiveCompare:)];
+  [folderPaths replaceObjectsInRange: NSMakeRange (0, 0)
+              withObjectsFromArray: mainFolders];
 
-  return newFolders;
+  return folderPaths;
 }
 
 /* IMAP4 */
 
-- (BOOL)useSSL {
+- (BOOL) useSSL
+{
   return NO;
 }
 
-- (NSString *)imap4LoginFromHTTP {
+- (NSString *) imap4LoginFromHTTP
+{
   WORequest *rq;
   NSString  *s;
   NSArray   *creds;
@@ -224,61 +253,44 @@ static BOOL     useAltNamespace       = NO;
   return urlString;
 }
 
-- (NSString *) imap4Login
+- (NSMutableString *) traversalFromMailAccount
 {
-  return [[self imap4URL] user];
+  return [NSMutableString string];
 }
 
-/* name lookup */
-
-- (id)lookupFolder:(NSString *)_key ofClassNamed:(NSString *)_cn
-  inContext:(id)_cx
+- (NSString *) imap4Login
 {
-  Class clazz;
-
-  if ((clazz = NSClassFromString(_cn)) == Nil) {
-    [self logWithFormat:@"ERROR: did not find class '%@' for key: '%@'", 
-           _cn, _key];
-    return [NSException exceptionWithHTTPStatus:500 /* server error */
-                       reason:@"did not find mail folder class!"];
-  }
-  return [[[clazz alloc] initWithName:_key inContainer:self] autorelease];
-}
-
-- (id)lookupImap4Folder:(NSString *)_key inContext:(id)_cx {
-  NSString *s;
-
-  s = [_key isEqualToString: [self trashFolderNameInContext:_cx]]
-    ? @"SOGoTrashFolder" : @"SOGoMailFolder";
-  
-  return [self lookupFolder:_key ofClassNamed:s inContext:_cx];
+  return [[self imap4URL] user];
 }
 
-- (id)lookupDraftsFolder:(NSString *)_key inContext:(id)_ctx {
-  return [self lookupFolder:_key ofClassNamed:@"SOGoDraftsFolder" 
-              inContext:_ctx];
-}
-- (id)lookupFiltersFolder:(NSString *)_key inContext:(id)_ctx {
-  return [self lookupFolder:_key ofClassNamed:@"SOGoSieveScriptsFolder" 
-              inContext:_ctx];
-}
+/* name lookup */
 
 - (id) lookupName: (NSString *) _key
        inContext: (id)_ctx
          acquire: (BOOL) _flag
 {
+  NSString *folderName;
+  Class klazz;
   id obj;
 
   if ([_key hasPrefix: @"folder"])
     {
-  // TODO: those should be product.plist bindings? (can't be class bindings
-  //       though because they are 'per-account')
-      if ([_key isEqualToString: [self draftsFolderNameInContext: _ctx]])
-       obj = [self lookupDraftsFolder: _key inContext: _ctx];
-      else if ([_key isEqualToString: [self sieveFolderNameInContext: _ctx]])
-       obj = [self lookupFiltersFolder: _key inContext: _ctx];
+      folderName = [_key substringFromIndex: 6];
+      if ([folderName
+           isEqualToString: [self sentFolderNameInContext: _ctx]])
+       klazz = [SOGoSentFolder class];
+      else if ([folderName
+                isEqualToString: [self draftsFolderNameInContext: _ctx]])
+       klazz = [SOGoDraftsFolder class];
+      else if ([folderName
+                isEqualToString: [self trashFolderNameInContext: _ctx]])
+       klazz = [SOGoTrashFolder class];
+/*       else if ([folderName isEqualToString: [self sieveFolderNameInContext: _ctx]])
+        obj = [self lookupFiltersFolder: _key inContext: _ctx]; */
       else
-       obj = [self lookupImap4Folder: _key inContext: _ctx];
+       klazz = [SOGoMailFolder class];
+
+      obj = [klazz objectWithName: _key inContainer: self];
     }
   else
     obj = [super lookupName: _key inContext: _ctx acquire: NO];
@@ -295,28 +307,93 @@ static BOOL     useAltNamespace       = NO;
 - (NSString *) inboxFolderNameInContext: (id)_ctx
 {
   /* cannot be changed in Cyrus ? */
-  return [NSString stringWithFormat: @"folder%@", inboxFolderName];
+  return inboxFolderName;
 }
 
-- (NSString *) draftsFolderNameInContext: (id) _ctx
+- (NSString *) _userFolderNameWithPurpose: (NSString *) purpose
 {
-  /* SOGo managed folder */
-  return [NSString stringWithFormat: @"folder%@", draftsFolderName];
+  NSUserDefaults *ud;
+  NSMutableDictionary *mailSettings;
+  NSString *folderName;
+
+  folderName = nil;
+  ud = [[context activeUser] userSettings];
+  mailSettings = [ud objectForKey: @"Mail"];
+  if (mailSettings)
+    folderName
+      = [mailSettings objectForKey: [NSString stringWithFormat: @"%@Folder",
+                                             purpose]];
+
+  return folderName;
 }
 
-- (NSString *) sieveFolderNameInContext: (id) _ctx
+- (NSString *) draftsFolderNameInContext: (id) _ctx
 {
-  return [NSString stringWithFormat: @"folder%@", sieveFolderName];
+  NSString *folderName;
+
+  folderName = [self _userFolderNameWithPurpose: @"Drafts"];
+  if (!folderName)
+    folderName = draftsFolderName;
+
+  return folderName;
 }
 
+// - (NSString *) sieveFolderNameInContext: (id) _ctx
+// {
+//   return sieveFolderName;
+// }
+
 - (NSString *) sentFolderNameInContext: (id)_ctx
 {
-  return [NSString stringWithFormat: @"folder%@", sentFolderName];
+  NSString *folderName;
+
+  folderName = [self _userFolderNameWithPurpose: @"Sent"];
+  if (!folderName)
+    folderName = sentFolderName;
+
+  return folderName;
 }
 
 - (NSString *) trashFolderNameInContext: (id)_ctx
 {
-  return [NSString stringWithFormat: @"folder%@", trashFolderName];
+  NSString *folderName;
+
+  folderName = [self _userFolderNameWithPurpose: @"Trash"];
+  if (!folderName)
+    folderName = trashFolderName;
+
+  return folderName;
+}
+
+- (id) folderWithTraversal: (NSString *) traversal
+             andClassName: (NSString *) className
+{
+  NSArray *paths;
+  NSString *currentName;
+  id currentContainer;
+  unsigned int count, max;
+  Class clazz;
+
+  currentContainer = self;
+  paths = [traversal componentsSeparatedByString: @"/"];
+
+  if (!className)
+    clazz = [SOGoMailFolder class];
+  else
+    clazz = NSClassFromString (className);
+
+  max = [paths count];
+  for (count = 0; count < max - 1; count++)
+    {
+      currentName = [NSString stringWithFormat: @"folder%@",
+                             [paths objectAtIndex: count]];
+      currentContainer = [SOGoMailFolder objectWithName: currentName
+                                        inContainer: currentContainer];
+    }
+  currentName = [NSString stringWithFormat: @"folder%@",
+                         [paths objectAtIndex: max - 1]];
+
+  return [clazz objectWithName: currentName inContainer: currentContainer];
 }
 
 - (SOGoMailFolder *) inboxFolderInContext: (id) _ctx
@@ -324,52 +401,52 @@ static BOOL     useAltNamespace       = NO;
   // TODO: use some profile to determine real location, use a -traverse lookup
   if (!inboxFolder)
     {
-      inboxFolder = [self lookupName: [self inboxFolderNameInContext: _ctx]
-                         inContext: _ctx acquire: NO];
+      inboxFolder
+       = [self folderWithTraversal: [self inboxFolderNameInContext: _ctx]
+               andClassName: nil];
       [inboxFolder retain];
     }
 
   return inboxFolder;
 }
 
-- (SOGoMailFolder *) sentFolderInContext: (id) _ctx
+- (SOGoDraftsFolder *) draftsFolderInContext: (id) _ctx
+{
+  // TODO: use some profile to determine real location, use a -traverse lookup
+
+  if (!draftsFolder)
+    {
+      draftsFolder
+       = [self folderWithTraversal: [self draftsFolderNameInContext: _ctx]
+               andClassName: @"SOGoDraftsFolder"];
+      [draftsFolder retain];
+    }
+
+  return draftsFolder;
+}
+
+- (SOGoSentFolder *) sentFolderInContext: (id) _ctx
 {
-  SOGoMailFolder *lookupFolder;
   // TODO: use some profile to determine real location, use a -traverse lookup
 
   if (!sentFolder)
     {
-      lookupFolder = (useAltNamespace
-                     ? (id) self
-                     : [self inboxFolderInContext:_ctx]);
-      if (![lookupFolder isKindOfClass: [NSException class]])
-       sentFolder = [lookupFolder lookupName: [self sentFolderNameInContext:_ctx]
-                                  inContext: _ctx acquire: NO];
-      if (![sentFolder isNotNull])
-       sentFolder = [NSException exceptionWithHTTPStatus: 404 /* not found */
-                                 reason: @"did not find Sent folder!"];
+      sentFolder
+       = [self folderWithTraversal: [self sentFolderNameInContext: _ctx]
+               andClassName: @"SOGoSentFolder"];
       [sentFolder retain];
     }
 
   return sentFolder;
 }
 
-- (SOGoMailFolder *) trashFolderInContext: (id) _ctx
+- (SOGoTrashFolder *) trashFolderInContext: (id) _ctx
 {
-  SOGoMailFolder *lookupFolder;
-  // TODO: use some profile to determine real location, use a -traverse lookup
-
   if (!trashFolder)
     {
-      lookupFolder = (useAltNamespace
-                     ? (id) self
-                     : [self inboxFolderInContext:_ctx]);
-      if (![lookupFolder isKindOfClass: [NSException class]])
-       trashFolder = [lookupFolder lookupName: [self trashFolderNameInContext: _ctx]
-                                   inContext: _ctx acquire: NO];
-      if (![trashFolder isNotNull])
-       trashFolder = [NSException exceptionWithHTTPStatus: 404 /* not found */
-                                 reason: @"did not find Trash folder!"];
+      trashFolder
+       = [self folderWithTraversal: [self trashFolderNameInContext: _ctx]
+               andClassName: @"SOGoTrashFolder"];
       [trashFolder retain];
     }
 
@@ -402,14 +479,16 @@ static BOOL     useAltNamespace       = NO;
   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)