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 <SoObjects/SOGo/SOGoUser.h>
37 #import "SOGoMailFolder.h"
38 #import "SOGoMailManager.h"
39 #import "SOGoDraftsFolder.h"
41 #import "SOGoMailAccount.h"
43 @implementation SOGoMailAccount
45 static NSArray *rootFolderNames = nil;
46 static NSString *inboxFolderName = @"INBOX";
47 static NSString *draftsFolderName = @"Drafts";
48 static NSString *sieveFolderName = @"Filters";
49 static NSString *sentFolderName = nil;
50 static NSString *trashFolderName = nil;
51 static NSString *sharedFolderName = @""; // TODO: add English default
52 static NSString *otherUsersFolderName = @""; // TODO: add English default
56 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
57 NSString *cfgDraftsFolderName;
59 sharedFolderName = [ud stringForKey:@"SOGoSharedFolderName"];
60 otherUsersFolderName = [ud stringForKey:@"SOGoOtherUsersFolderName"];
61 cfgDraftsFolderName = [ud stringForKey:@"SOGoDraftsFolderName"];
64 sentFolderName = [ud stringForKey: @"SOGoSentFolderName"];
66 sentFolderName = @"Sent";
67 [sentFolderName retain];
71 trashFolderName = [ud stringForKey: @"SOGoTrashFolderName"];
73 trashFolderName = @"Trash";
74 [trashFolderName retain];
76 if ([cfgDraftsFolderName length] > 0)
78 ASSIGN (draftsFolderName, cfgDraftsFolderName);
79 NSLog(@"Note: using drafts folder named: '%@'", draftsFolderName);
82 NSLog(@"Note: using shared-folders name: '%@'", sharedFolderName);
83 NSLog(@"Note: using other-users-folders name: '%@'", otherUsersFolderName);
84 if ([ud boolForKey: @"SOGoEnableSieveFolder"])
85 rootFolderNames = [[NSArray alloc] initWithObjects:
90 rootFolderNames = [[NSArray alloc] initWithObjects:
97 if ((self = [super init]))
110 [inboxFolder release];
111 [draftsFolder release];
112 [sentFolder release];
113 [trashFolder release];
117 /* shared accounts */
119 - (BOOL) isSharedAccount
124 s = [self nameInContainer];
125 r = [s rangeOfString:@"@"];
126 if (r.length == 0) /* regular HTTP logins are never a shared mailbox */
129 s = [s substringToIndex:r.location];
130 return [s rangeOfString:@".-."].length > 0 ? YES : NO;
133 - (NSString *) sharedAccountName
138 /* listing the available folders */
140 - (NSArray *) additionalRootFolderNames
142 return rootFolderNames;
145 - (BOOL) isInDraftsFolder
150 - (NSArray *) toManyRelationshipKeys
152 NSMutableArray *folders;
153 NSArray *imapFolders, *additionalFolders;
155 folders = [NSMutableArray array];
157 imapFolders = [[self imap4Connection] subfoldersForURL: [self imap4URL]];
158 additionalFolders = [self additionalRootFolderNames];
159 if ([imapFolders count] > 0)
160 [folders addObjectsFromArray: imapFolders];
161 if ([additionalFolders count] > 0)
163 [folders removeObjectsInArray: additionalFolders];
164 [folders addObjectsFromArray: additionalFolders];
172 - (SOGoMailAccount *) mailAccountFolder
177 - (NSArray *) allFolderPaths
179 NSMutableArray *newFolders;
180 NSArray *rawFolders, *mainFolders;
182 rawFolders = [[self imap4Connection]
183 allFoldersForURL: [self imap4URL]];
185 #warning FIXME: the folder names should be prefixed
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 *) _userFolderNameWithPurpose: (NSString *) purpose
339 NSMutableDictionary *mailSettings;
340 NSString *folderName;
343 ud = [[context activeUser] userSettings];
344 mailSettings = [ud objectForKey: @"Mail"];
347 = [mailSettings objectForKey: [NSString stringWithFormat: @"%@Folder",
353 - (NSString *) draftsFolderNameInContext: (id) _ctx
355 NSString *folderName;
357 folderName = [self _userFolderNameWithPurpose: @"Drafts"];
359 folderName = draftsFolderName;
361 return [NSString stringWithFormat: @"folder%@", folderName];
364 - (NSString *) sieveFolderNameInContext: (id) _ctx
366 return [NSString stringWithFormat: @"folder%@", sieveFolderName];
369 - (NSString *) sentFolderNameInContext: (id)_ctx
371 NSString *folderName;
373 folderName = [self _userFolderNameWithPurpose: @"Sent"];
375 folderName = sentFolderName;
377 return [NSString stringWithFormat: @"folder%@", folderName];
380 - (NSString *) trashFolderNameInContext: (id)_ctx
382 NSString *folderName;
384 folderName = [self _userFolderNameWithPurpose: @"Trash"];
386 folderName = trashFolderName;
388 return [NSString stringWithFormat: @"folder%@", folderName];
391 - (SOGoMailFolder *) inboxFolderInContext: (id) _ctx
393 // TODO: use some profile to determine real location, use a -traverse lookup
396 inboxFolder = [self lookupName: [self inboxFolderNameInContext: _ctx]
397 inContext: _ctx acquire: NO];
398 [inboxFolder retain];
404 - (SOGoDraftsFolder *) draftsFolderInContext: (id) _ctx
406 // TODO: use some profile to determine real location, use a -traverse lookup
411 = [self lookupName: [self draftsFolderNameInContext:_ctx]
412 inContext: _ctx acquire: NO];
413 // if (![draftsFolder isNotNull])
414 // draftsFolder = [NSException exceptionWithHTTPStatus: 404 /* not found */
415 // reason: @"did not find Drafts folder!"];
416 [draftsFolder retain];
422 - (SOGoMailFolder *) sentFolderInContext: (id) _ctx
424 // TODO: use some profile to determine real location, use a -traverse lookup
428 sentFolder = [self lookupName: [self sentFolderNameInContext:_ctx]
429 inContext: _ctx acquire: NO];
430 // if (![sentFolder isNotNull])
431 // sentFolder = [NSException exceptionWithHTTPStatus: 404 /* not found */
432 // reason: @"did not find Sent folder!"];
439 - (SOGoMailFolder *) trashFolderInContext: (id) _ctx
443 trashFolder = [self lookupName: [self trashFolderNameInContext: _ctx]
444 inContext: _ctx acquire: NO];
445 // if (![trashFolder isNotNull])
446 // trashFolder = [NSException exceptionWithHTTPStatus: 404 /* not found */
447 // reason: @"did not find Trash folder!"];
448 [trashFolder retain];
456 - (NSString *) davContentType
458 return @"httpd/unix-directory";
461 - (BOOL) davIsCollection
466 - (NSException *) davCreateCollection: (NSString *) _name
469 return [[self imap4Connection] createMailbox:_name atURL:[self imap4URL]];
472 - (NSString *) shortTitle
474 NSString *s, *login, *host;
477 s = [self nameInContainer];
479 r = [s rangeOfString:@"@"];
481 login = [s substringToIndex:r.location];
482 host = [s substringFromIndex:(r.location + r.length)];
489 r = [host rangeOfString:@"."];
491 host = [host substringToIndex:r.location];
493 if ([login length] == 0)
496 r = [login rangeOfString:@"."];
498 login = [login substringToIndex:r.location];
500 return [NSString stringWithFormat:@"%@@%@", login, host];
503 - (NSString *) davDisplayName
505 return [self shortTitle];
508 - (NSString *) sharedFolderName
510 return sharedFolderName;
513 - (NSString *) otherUsersFolderName
515 return otherUsersFolderName;
518 @end /* SOGoMailAccount */