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 #include "SOGoMailAccount.h"
23 #include "SOGoMailFolder.h"
24 #include "SOGoMailManager.h"
25 #include "SOGoDraftsFolder.h"
26 #include <NGObjWeb/SoHTTPAuthenticator.h>
29 @implementation SOGoMailAccount
31 static NSArray *rootFolderNames = nil;
32 static NSString *inboxFolderName = @"INBOX";
33 static NSString *draftsFolderName = @"Drafts";
34 static NSString *sieveFolderName = @"Filters";
35 static BOOL useAltNamespace = NO;
38 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
40 useAltNamespace = [ud boolForKey:@"SOGoSpecialFoldersInRoot"];
42 if ([ud boolForKey:@"SOGoEnableSieveFolder"]) {
43 rootFolderNames = [[NSArray alloc] initWithObjects:
49 rootFolderNames = [[NSArray alloc] initWithObjects:
55 /* listing the available folders */
57 - (NSArray *)toManyRelationshipKeys {
62 b = [[self mailManager] subfoldersForURL:[self imap4URL]
63 password:[self imap4Password]];
64 return [b count] > 0 ? [b arrayByAddingObjectsFromArray:a] : a;
69 - (SOGoMailAccount *)mailAccountFolder {
73 - (NSArray *)allFolderPathes {
76 pathes = [[self mailManager] allFoldersForURL:[self imap4URL]
77 password:[self imap4Password]];
78 pathes = [pathes sortedArrayUsingSelector:@selector(compare:)];
88 - (NSString *)imap4LoginFromHTTP {
93 rq = [[(WOApplication *)[WOApplication application] context] request];
95 s = [rq headerForKey:@"x-webobjects-remote-user"];
99 if ((s = [rq headerForKey:@"authorization"]) == nil) {
104 creds = [SoHTTPAuthenticator parseCredentials:s];
105 if ([creds count] < 2)
106 /* somehow invalid */
109 return [creds objectAtIndex:0]; /* the user */
112 - (NSURL *)imap4URL {
113 /* imap://agenortest@mail.opengroupware.org/INBOX/withsubdirs/subdir1 */
117 if (self->imap4URL != nil)
118 return self->imap4URL;
120 s = [self nameInContainer];
121 r = [s rangeOfString:@"@"];
125 u = [self imap4LoginFromHTTP];
126 if ([u length] == 0) {
127 [self errorWithFormat:@"missing login in account folder name: %@", s];
130 s = [[u stringByAppendingString:@"@"] stringByAppendingString:s];
132 if ([s hasSuffix:@":80"]) { // HACK
133 [self logWithFormat:@"WARNING: incorrect value for IMAP4 URL: '%@'", s];
134 s = [s substringToIndex:([s length] - 3)];
137 s = [([self useSSL] ? @"imaps://" : @"imap://") stringByAppendingString:s];
138 s = [s stringByAppendingString:@"/"];
140 self->imap4URL = [[NSURL alloc] initWithString:s];
141 return self->imap4URL;
144 - (NSString *)imap4Login {
145 return [[self imap4URL] user];
150 - (id)lookupFolder:(NSString *)_key ofClassNamed:(NSString *)_cn
155 if ((clazz = NSClassFromString(_cn)) == Nil) {
156 [self logWithFormat:@"ERROR: did not find class '%@' for key: '%@'",
158 return [NSException exceptionWithHTTPStatus:500 /* server error */
159 reason:@"did not find mail folder class!"];
161 return [[[clazz alloc] initWithName:_key inContainer:self] autorelease];
164 - (id)lookupImap4Folder:(NSString *)_key inContext:(id)_cx {
165 return [self lookupFolder:_key ofClassNamed:@"SOGoMailFolder" inContext:_cx];
167 - (id)lookupDraftsFolder:(NSString *)_key inContext:(id)_ctx {
168 return [self lookupFolder:_key ofClassNamed:@"SOGoDraftsFolder"
171 - (id)lookupFiltersFolder:(NSString *)_key inContext:(id)_ctx {
172 return [self lookupFolder:_key ofClassNamed:@"SOGoSieveScriptsFolder"
176 - (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
179 /* first check attributes directly bound to the application */
180 if ((obj = [super lookupName:_key inContext:_ctx acquire:NO]) != nil)
183 // TODO: those should be product.plist bindings? (can't be class bindings
184 // though because they are 'per-account')
185 if ([_key isEqualToString:draftsFolderName]) {
186 if ((obj = [self lookupDraftsFolder:_key inContext:_ctx]) != nil)
189 if ([_key isEqualToString:sieveFolderName]) {
190 if ((obj = [self lookupFiltersFolder:_key inContext:_ctx]) != nil)
194 if ((obj = [self lookupImap4Folder:_key inContext:_ctx]) != nil)
197 /* return 404 to stop acquisition */
198 return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
201 /* special folders */
203 - (NSString *)inboxFolderNameInContext:(id)_ctx {
204 return inboxFolderName; /* cannot be changed in Cyrus ? */
206 - (NSString *)draftsFolderNameInContext:(id)_ctx {
207 return draftsFolderName; /* SOGo managed folder */
209 - (NSString *)sieveFolderNameInContext:(id)_ctx {
210 return sieveFolderName; /* SOGo managed folder */
212 - (NSString *)sentFolderNameInContext:(id)_ctx {
213 /* OGo issue #1225 */
214 static NSString *s = nil;
219 ud = [NSUserDefaults standardUserDefaults];
220 s = [[ud stringForKey:@"SOGoSentFolderName"] copy];
221 if ([s length] == 0) s = @"Sent";
222 NSLog(@"Note: using SOGoSentFolderName: '%@'", s);
226 - (NSString *)trashFolderNameInContext:(id)_ctx {
227 /* OGo issue #1225 */
228 static NSString *s = nil;
233 ud = [NSUserDefaults standardUserDefaults];
234 s = [[ud stringForKey:@"SOGoTrashFolderName"] copy];
235 if ([s length] == 0) s = @"Trash";
236 NSLog(@"Note: using SOGoTrashFolderName: '%@'", s);
241 - (SOGoMailFolder *)inboxFolderInContext:(id)_ctx {
242 // TODO: use some profile to determine real location, use a -traverse lookup
243 SOGoMailFolder *folder;
245 if (self->inboxFolder != nil)
246 return self->inboxFolder;
248 folder = [self lookupName:[self inboxFolderNameInContext:_ctx]
249 inContext:_ctx acquire:NO];
250 if ([folder isKindOfClass:[NSException class]]) return folder;
252 return ((self->inboxFolder = [folder retain]));
255 - (SOGoMailFolder *)sentFolderInContext:(id)_ctx {
256 // TODO: use some profile to determine real location, use a -traverse lookup
257 SOGoMailFolder *folder;
259 if (self->sentFolder != nil)
260 return self->sentFolder;
262 folder = useAltNamespace ? (id)self : [self inboxFolderInContext:_ctx];
263 if ([folder isKindOfClass:[NSException class]]) return folder;
265 folder = [folder lookupName:[self sentFolderNameInContext:_ctx]
266 inContext:_ctx acquire:NO];
267 if ([folder isKindOfClass:[NSException class]]) return folder;
269 if (![folder isNotNull]) {
270 return [NSException exceptionWithHTTPStatus:404 /* not found */
271 reason:@"did not find Sent folder!"];
274 return ((self->sentFolder = [folder retain]));
277 - (SOGoMailFolder *)trashFolderInContext:(id)_ctx {
278 // TODO: use some profile to determine real location
279 SOGoMailFolder *folder;
281 if (self->trashFolder != nil)
282 return self->trashFolder;
284 folder = useAltNamespace ? (id)self : [self inboxFolderInContext:_ctx];
285 if ([folder isKindOfClass:[NSException class]]) return folder;
287 folder = [folder lookupName:[self trashFolderNameInContext:_ctx]
288 inContext:_ctx acquire:NO];
289 if ([folder isKindOfClass:[NSException class]]) return folder;
291 if (![folder isNotNull]) {
292 return [NSException exceptionWithHTTPStatus:404 /* not found */
293 reason:@"did not find Trash folder!"];
296 return ((self->trashFolder = [folder retain]));
301 - (BOOL)davIsCollection {
305 - (NSException *)davCreateCollection:(NSString *)_name inContext:(id)_ctx {
306 return [[self mailManager] createMailbox:_name atURL:[self imap4URL]
307 password:[self imap4Password]];
310 - (NSString *)shortTitle {
311 NSString *s, *login, *host;
314 s = [self nameInContainer];
316 r = [s rangeOfString:@"@"];
318 login = [s substringToIndex:r.location];
319 host = [s substringFromIndex:(r.location + r.length)];
326 r = [host rangeOfString:@"."];
328 host = [host substringToIndex:r.location];
330 if ([login length] == 0)
333 r = [login rangeOfString:@"."];
335 login = [login substringToIndex:r.location];
337 return [NSString stringWithFormat:@"%@@%@", login, host];
340 - (NSString *)davDisplayName {
341 return [self shortTitle];
344 @end /* SOGoMailAccount */