2 Copyright (C) 2004-2005 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #import <Foundation/NSArray.h>
23 #import <Foundation/NSURL.h>
24 #import <Foundation/NSString.h>
25 #import <Foundation/NSUserDefaults.h>
27 #import <NGObjWeb/NSException+HTTP.h>
28 #import <NGObjWeb/SoHTTPAuthenticator.h>
29 #import <NGObjWeb/WORequest.h>
30 #import <NGObjWeb/WOContext+SoObjects.h>
31 #import <NGExtensions/NSObject+Logs.h>
32 #import <NGExtensions/NSNull+misc.h>
33 #import <NGImap4/NGImap4Connection.h>
35 #import "SOGoMailFolder.h"
36 #import "SOGoMailManager.h"
37 #import "SOGoDraftsFolder.h"
39 #import "SOGoMailAccount.h"
41 @implementation SOGoMailAccount
43 static NSArray *rootFolderNames = nil;
44 static NSString *inboxFolderName = @"INBOX";
45 static NSString *draftsFolderName = @"Drafts";
46 static NSString *sieveFolderName = @"Filters";
47 static NSString *sentFolderName = nil;
48 static NSString *trashFolderName = nil;
49 static NSString *sharedFolderName = @""; // TODO: add English default
50 static NSString *otherUsersFolderName = @""; // TODO: add English default
51 static BOOL useAltNamespace = NO;
55 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
56 NSString *cfgDraftsFolderName;
58 useAltNamespace = [ud boolForKey:@"SOGoSpecialFoldersInRoot"];
60 sharedFolderName = [ud stringForKey:@"SOGoSharedFolderName"];
61 otherUsersFolderName = [ud stringForKey:@"SOGoOtherUsersFolderName"];
62 cfgDraftsFolderName = [ud stringForKey:@"SOGoDraftsFolderName"];
65 sentFolderName = [ud stringForKey: @"SOGoSentFolderName"];
67 sentFolderName = @"Sent";
68 [sentFolderName retain];
72 trashFolderName = [ud stringForKey: @"SOGoTrashFolderName"];
74 trashFolderName = @"Trash";
75 [trashFolderName retain];
77 if ([cfgDraftsFolderName length] > 0)
79 ASSIGN (draftsFolderName, cfgDraftsFolderName);
80 NSLog(@"Note: using drafts folder named: '%@'", draftsFolderName);
83 NSLog(@"Note: using shared-folders name: '%@'", sharedFolderName);
84 NSLog(@"Note: using other-users-folders name: '%@'", otherUsersFolderName);
85 if ([ud boolForKey: @"SOGoEnableSieveFolder"])
86 rootFolderNames = [[NSArray alloc] initWithObjects:
91 rootFolderNames = [[NSArray alloc] initWithObjects:
98 if ((self = [super init]))
111 [inboxFolder release];
112 [draftsFolder release];
113 [sentFolder release];
114 [trashFolder release];
118 /* shared accounts */
120 - (BOOL) isSharedAccount
125 s = [self nameInContainer];
126 r = [s rangeOfString:@"@"];
127 if (r.length == 0) /* regular HTTP logins are never a shared mailbox */
130 s = [s substringToIndex:r.location];
131 return [s rangeOfString:@".-."].length > 0 ? YES : NO;
134 - (NSString *) sharedAccountName
139 /* listing the available folders */
141 - (NSArray *) additionalRootFolderNames
143 return rootFolderNames;
146 - (BOOL) isInDraftsFolder
151 - (NSArray *) toManyRelationshipKeys
153 NSMutableArray *folders;
154 NSArray *imapFolders, *additionalFolders;
156 folders = [NSMutableArray array];
158 imapFolders = [[self imap4Connection] subfoldersForURL: [self imap4URL]];
159 additionalFolders = [self additionalRootFolderNames];
160 if ([imapFolders count] > 0)
161 [folders addObjectsFromArray: imapFolders];
162 if ([additionalFolders count] > 0)
164 [folders removeObjectsInArray: additionalFolders];
165 [folders addObjectsFromArray: additionalFolders];
173 - (SOGoMailAccount *) mailAccountFolder
178 - (NSArray *) allFolderPaths
180 NSMutableArray *newFolders;
181 NSArray *rawFolders, *mainFolders;
183 rawFolders = [[self imap4Connection]
184 allFoldersForURL: [self imap4URL]];
186 mainFolders = [NSArray arrayWithObjects: inboxFolderName, draftsFolderName,
187 sentFolder, trashFolder, nil];
188 newFolders = [NSMutableArray arrayWithArray: rawFolders];
189 [newFolders removeObjectsInArray: mainFolders];
190 [newFolders sortUsingSelector: @selector (caseInsensitiveCompare:)];
191 [newFolders replaceObjectsInRange: NSMakeRange (0, 0)
192 withObjectsFromArray: mainFolders];
204 - (NSString *) imap4LoginFromHTTP
210 rq = [context request];
212 s = [rq headerForKey:@"x-webobjects-remote-user"];
216 if ((s = [rq headerForKey:@"authorization"]) == nil) {
221 creds = [SoHTTPAuthenticator parseCredentials:s];
222 if ([creds count] < 2)
223 /* somehow invalid */
226 return [creds objectAtIndex:0]; /* the user */
229 - (NSMutableString *) imap4URLString
231 /* private, overridden by SOGoSharedMailAccount */
232 NSMutableString *urlString;
235 urlString = [NSMutableString string];
238 [urlString appendString: @"imaps://"];
240 [urlString appendString: @"imap://"];
242 host = [self nameInContainer];
243 if (![host rangeOfString: @"@"].length)
244 [urlString appendFormat: @"%@@", [self imap4LoginFromHTTP]];
245 [urlString appendFormat: @"%@/", host];
250 - (NSString *) imap4Login
252 return [[self imap4URL] user];
257 - (id) lookupFolder: (NSString *) _key
258 ofClassNamed: (NSString *) _cn
262 SOGoMailFolder *folder;
264 if ((clazz = NSClassFromString(_cn)) == Nil)
266 [self logWithFormat:@"ERROR: did not find class '%@' for key: '%@'",
268 return [NSException exceptionWithHTTPStatus:500 /* server error */
269 reason:@"did not find mail folder class!"];
272 folder = [clazz objectWithName: _key inContainer: self];
277 - (id) lookupImap4Folder: (NSString *) _key
282 s = [_key isEqualToString: [self trashFolderNameInContext:_cx]]
283 ? @"SOGoTrashFolder" : @"SOGoMailFolder";
285 return [self lookupFolder:_key ofClassNamed:s inContext:_cx];
288 - (id) lookupDraftsFolder: (NSString *) _key
291 return [self lookupFolder: _key ofClassNamed: @"SOGoDraftsFolder"
295 - (id) lookupFiltersFolder: (NSString *) _key inContext: (id) _ctx
297 return [self lookupFolder:_key ofClassNamed:@"SOGoSieveScriptsFolder"
301 - (id) lookupName: (NSString *) _key
303 acquire: (BOOL) _flag
307 if ([_key hasPrefix: @"folder"])
309 // TODO: those should be product.plist bindings? (can't be class bindings
310 // though because they are 'per-account')
311 if ([_key isEqualToString: [self draftsFolderNameInContext: _ctx]])
312 obj = [self lookupDraftsFolder: _key inContext: _ctx];
313 else if ([_key isEqualToString: [self sieveFolderNameInContext: _ctx]])
314 obj = [self lookupFiltersFolder: _key inContext: _ctx];
316 obj = [self lookupImap4Folder: _key inContext: _ctx];
319 obj = [super lookupName: _key inContext: _ctx acquire: NO];
321 /* return 404 to stop acquisition */
323 obj = [NSException exceptionWithHTTPStatus: 404 /* Not Found */];
328 /* special folders */
330 - (NSString *) inboxFolderNameInContext: (id)_ctx
332 /* cannot be changed in Cyrus ? */
333 return [NSString stringWithFormat: @"folder%@", inboxFolderName];
336 - (NSString *) draftsFolderNameInContext: (id) _ctx
338 /* SOGo managed folder */
339 return [NSString stringWithFormat: @"folder%@", draftsFolderName];
342 - (NSString *) sieveFolderNameInContext: (id) _ctx
344 return [NSString stringWithFormat: @"folder%@", sieveFolderName];
347 - (NSString *) sentFolderNameInContext: (id)_ctx
349 return [NSString stringWithFormat: @"folder%@", sentFolderName];
352 - (NSString *) trashFolderNameInContext: (id)_ctx
354 return [NSString stringWithFormat: @"folder%@", trashFolderName];
357 - (SOGoMailFolder *) inboxFolderInContext: (id) _ctx
359 // TODO: use some profile to determine real location, use a -traverse lookup
362 inboxFolder = [self lookupName: [self inboxFolderNameInContext: _ctx]
363 inContext: _ctx acquire: NO];
364 [inboxFolder retain];
370 - (SOGoDraftsFolder *) draftsFolderInContext: (id) _ctx
372 SOGoMailFolder *lookupFolder;
373 // TODO: use some profile to determine real location, use a -traverse lookup
377 lookupFolder = (useAltNamespace
379 : [self inboxFolderInContext:_ctx]);
380 if (![lookupFolder isKindOfClass: [NSException class]])
382 = [lookupFolder lookupName: [self draftsFolderNameInContext:_ctx]
383 inContext: _ctx acquire: NO];
384 if (![draftsFolder isNotNull])
385 draftsFolder = [NSException exceptionWithHTTPStatus: 404 /* not found */
386 reason: @"did not find Drafts folder!"];
387 [draftsFolder retain];
393 - (SOGoMailFolder *) sentFolderInContext: (id) _ctx
395 SOGoMailFolder *lookupFolder;
396 // TODO: use some profile to determine real location, use a -traverse lookup
400 lookupFolder = (useAltNamespace
402 : [self inboxFolderInContext:_ctx]);
403 if (![lookupFolder isKindOfClass: [NSException class]])
404 sentFolder = [lookupFolder lookupName: [self sentFolderNameInContext:_ctx]
405 inContext: _ctx acquire: NO];
406 if (![sentFolder isNotNull])
407 sentFolder = [NSException exceptionWithHTTPStatus: 404 /* not found */
408 reason: @"did not find Sent folder!"];
415 - (SOGoMailFolder *) trashFolderInContext: (id) _ctx
417 SOGoMailFolder *lookupFolder;
418 // TODO: use some profile to determine real location, use a -traverse lookup
422 lookupFolder = (useAltNamespace
424 : [self inboxFolderInContext:_ctx]);
425 if (![lookupFolder isKindOfClass: [NSException class]])
426 trashFolder = [lookupFolder lookupName: [self trashFolderNameInContext: _ctx]
427 inContext: _ctx acquire: NO];
428 if (![trashFolder isNotNull])
429 trashFolder = [NSException exceptionWithHTTPStatus: 404 /* not found */
430 reason: @"did not find Trash folder!"];
431 [trashFolder retain];
439 - (NSString *) davContentType
441 return @"httpd/unix-directory";
444 - (BOOL) davIsCollection
449 - (NSException *) davCreateCollection: (NSString *) _name
452 return [[self imap4Connection] createMailbox:_name atURL:[self imap4URL]];
455 - (NSString *) shortTitle
457 NSString *s, *login, *host;
460 s = [self nameInContainer];
462 r = [s rangeOfString:@"@"];
464 login = [s substringToIndex:r.location];
465 host = [s substringFromIndex:(r.location + r.length)];
472 r = [host rangeOfString:@"."];
474 host = [host substringToIndex:r.location];
476 if ([login length] == 0)
479 r = [login rangeOfString:@"."];
481 login = [login substringToIndex:r.location];
483 return [NSString stringWithFormat:@"%@@%@", login, host];
486 - (NSString *) davDisplayName
488 return [self shortTitle];
491 - (NSString *) sharedFolderName
493 return sharedFolderName;
496 - (NSString *) otherUsersFolderName
498 return otherUsersFolderName;
501 @end /* SOGoMailAccount */