]> err.no Git - scalable-opengroupware.org/blob - SOGo/SoObjects/Mailer/SOGoMailAccount.m
minor tree improvements
[scalable-opengroupware.org] / SOGo / SoObjects / Mailer / SOGoMailAccount.m
1 /*
2   Copyright (C) 2004-2005 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21
22 #include "SOGoMailAccount.h"
23 #include "SOGoMailFolder.h"
24 #include "SOGoMailManager.h"
25 #include "SOGoDraftsFolder.h"
26 #include <NGObjWeb/SoHTTPAuthenticator.h>
27 #include "common.h"
28
29 @implementation SOGoMailAccount
30
31 static NSArray  *rootFolderNames  = nil;
32 static NSString *inboxFolderName  = @"INBOX";
33 static NSString *draftsFolderName = @"Drafts";
34 static NSString *sieveFolderName  = @"Filters";
35
36 + (void)initialize {
37   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
38
39   if ([ud boolForKey:@"SOGoEnableSieveFolder"]) {
40     rootFolderNames = [[NSArray alloc] initWithObjects:
41                                         inboxFolderName, 
42                                         draftsFolderName, 
43                                         sieveFolderName, 
44                                       nil];
45   }
46   else {
47     rootFolderNames = [[NSArray alloc] initWithObjects:
48                                         inboxFolderName, 
49                                         draftsFolderName, 
50                                       nil];
51   }
52 }
53
54 /* listing the available folders */
55
56 - (NSArray *)toManyRelationshipKeys {
57   // TODO: hardcoded, if we want to support shared fldrs, this needs to change
58   return rootFolderNames;
59 }
60
61 /* hierarchy */
62
63 - (SOGoMailAccount *)mailAccountFolder {
64   return self;
65 }
66
67 - (NSArray *)allFolderPathes {
68   NSArray *pathes;
69   
70   pathes = [[self mailManager] allFoldersForURL:[self imap4URL] 
71                                password:[self imap4Password]];
72   pathes = [pathes sortedArrayUsingSelector:@selector(compare:)];
73   return pathes;
74 }
75
76 /* IMAP4 */
77
78 - (BOOL)useSSL {
79   return NO;
80 }
81
82 - (NSString *)imap4LoginFromHTTP {
83   WORequest *rq;
84   NSString  *s;
85   NSArray   *creds;
86   
87   rq = [[(WOApplication *)[WOApplication application] context] request];
88   
89   s = [rq headerForKey:@"x-webobjects-remote-user"];
90   if ([s length] > 0)
91     return s;
92   
93   if ((s = [rq headerForKey:@"authorization"]) == nil) {
94     /* no basic auth */
95     return nil;
96   }
97   
98   creds = [SoHTTPAuthenticator parseCredentials:s];
99   if ([creds count] < 2)
100     /* somehow invalid */
101     return nil;
102   
103   return [creds objectAtIndex:0]; /* the user */
104 }
105
106 - (NSURL *)imap4URL {
107   /* imap://agenortest@mail.opengroupware.org/INBOX/withsubdirs/subdir1 */
108   NSString *s;
109   NSRange  r;
110   
111   if (self->imap4URL != nil)
112     return self->imap4URL;
113   
114   s = [self nameInContainer];
115   r = [s rangeOfString:@"@"];
116   if (r.length == 0) {
117     NSString *u;
118     
119     u = [self imap4LoginFromHTTP];
120     if ([u length] == 0) {
121       [self errorWithFormat:@"missing login in account folder name: %@", s];
122       return nil;
123     }
124     s = [[u stringByAppendingString:@"@"] stringByAppendingString:s];
125   }
126   if ([s hasSuffix:@":80"]) { // HACK
127     [self logWithFormat:@"WARNING: incorrect value for IMAP4 URL: '%@'", s];
128     s = [s substringToIndex:([s length] - 3)];
129   }
130   
131   s = [([self useSSL] ? @"imaps://" : @"imap://") stringByAppendingString:s];
132   s = [s stringByAppendingString:@"/"];
133   
134   self->imap4URL = [[NSURL alloc] initWithString:s];
135   return self->imap4URL;
136 }
137
138 - (NSString *)imap4Login {
139   return [[self imap4URL] user];
140 }
141
142 /* name lookup */
143
144 - (id)lookupFolder:(NSString *)_key ofClassNamed:(NSString *)_cn
145   inContext:(id)_cx
146 {
147   Class clazz;
148
149   if ((clazz = NSClassFromString(_cn)) == Nil) {
150     [self logWithFormat:@"ERROR: did not find class '%@' for key: '%@'", 
151             _cn, _key];
152     return [NSException exceptionWithHTTPStatus:500 /* server error */
153                         reason:@"did not find mail folder class!"];
154   }
155   return [[[clazz alloc] initWithName:_key inContainer:self] autorelease];
156 }
157
158 - (id)lookupImap4Folder:(NSString *)_key inContext:(id)_cx {
159   return [self lookupFolder:_key ofClassNamed:@"SOGoMailFolder" inContext:_cx];
160 }
161 - (id)lookupDraftsFolder:(NSString *)_key inContext:(id)_ctx {
162   return [self lookupFolder:_key ofClassNamed:@"SOGoDraftsFolder" 
163                inContext:_ctx];
164 }
165 - (id)lookupFiltersFolder:(NSString *)_key inContext:(id)_ctx {
166   return [self lookupFolder:_key ofClassNamed:@"SOGoSieveScriptsFolder" 
167                inContext:_ctx];
168 }
169
170 - (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
171   id obj;
172   
173   /* first check attributes directly bound to the application */
174   if ((obj = [super lookupName:_key inContext:_ctx acquire:NO]) != nil)
175     return obj;
176   
177   // TODO: those should be product.plist bindings? (can't be class bindings
178   //       though because they are 'per-account')
179   if ([_key isEqualToString:draftsFolderName]) {
180     if ((obj = [self lookupDraftsFolder:_key inContext:_ctx]) != nil)
181       return obj;
182   }
183   if ([_key isEqualToString:sieveFolderName]) {
184     if ((obj = [self lookupFiltersFolder:_key inContext:_ctx]) != nil)
185       return obj;
186   }
187   
188   if ((obj = [self lookupImap4Folder:_key inContext:_ctx]) != nil)
189     return obj;
190   
191   /* return 404 to stop acquisition */
192   return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
193 }
194
195 /* special folders */
196
197 - (NSString *)inboxFolderNameInContext:(id)_ctx {
198   return inboxFolderName; /* cannot be changed in Cyrus ? */
199 }
200 - (NSString *)draftsFolderNameInContext:(id)_ctx {
201   return draftsFolderName; /* SOGo managed folder */
202 }
203 - (NSString *)sieveFolderNameInContext:(id)_ctx {
204   return sieveFolderName;  /* SOGo managed folder */
205 }
206 - (NSString *)sentFolderNameInContext:(id)_ctx {
207   /* OGo issue #1225 */
208   static NSString *s = nil;
209   
210   if (s == nil) {
211     NSUserDefaults *ud;
212     
213     ud = [NSUserDefaults standardUserDefaults];
214     s = [[ud stringForKey:@"SOGoSentFolderName"] copy];
215     if ([s length] == 0) s = @"Sent";
216     NSLog(@"Note: using SOGoSentFolderName: '%@'", s);
217   }
218   return s;
219 }
220 - (NSString *)trashFolderNameInContext:(id)_ctx {
221   /* OGo issue #1225 */
222   static NSString *s = nil;
223   
224   if (s == nil) {
225     NSUserDefaults *ud;
226     
227     ud = [NSUserDefaults standardUserDefaults];
228     s = [[ud stringForKey:@"SOGoTrashFolderName"] copy];
229     if ([s length] == 0) s = @"Trash";
230     NSLog(@"Note: using SOGoTrashFolderName: '%@'", s);
231   }
232   return s;
233 }
234
235 - (SOGoMailFolder *)inboxFolderInContext:(id)_ctx {
236   // TODO: use some profile to determine real location, use a -traverse lookup
237   SOGoMailFolder *folder;
238   
239   if (self->inboxFolder != nil)
240     return self->inboxFolder;
241   
242   folder = [self lookupName:[self inboxFolderNameInContext:_ctx]
243                  inContext:_ctx acquire:NO];
244   if ([folder isKindOfClass:[NSException class]]) return folder;
245   
246   return ((self->inboxFolder = [folder retain]));
247 }
248
249 - (SOGoMailFolder *)sentFolderInContext:(id)_ctx {
250   // TODO: use some profile to determine real location, use a -traverse lookup
251   SOGoMailFolder *folder;
252   
253   if (self->sentFolder != nil)
254     return self->sentFolder;
255   
256   folder = [self inboxFolderInContext:_ctx];
257   if ([folder isKindOfClass:[NSException class]]) return folder;
258   
259   folder = [folder lookupName:[self sentFolderNameInContext:_ctx]
260                    inContext:_ctx acquire:NO];
261   if ([folder isKindOfClass:[NSException class]]) return folder;
262   
263   if (![folder isNotNull]) {
264     return [NSException exceptionWithHTTPStatus:404 /* not found */
265                         reason:@"did not find Sent folder!"];
266   }
267   
268   return ((self->sentFolder = [folder retain]));
269 }
270
271 - (SOGoMailFolder *)trashFolderInContext:(id)_ctx {
272   // TODO: use some profile to determine real location
273   SOGoMailFolder *folder;
274   
275   if (self->trashFolder != nil)
276     return self->trashFolder;
277
278   folder = [self inboxFolderInContext:_ctx];
279   if ([folder isKindOfClass:[NSException class]]) return folder;
280   
281   folder = [folder lookupName:[self trashFolderNameInContext:_ctx]
282                    inContext:_ctx acquire:NO];
283   if ([folder isKindOfClass:[NSException class]]) return folder;
284   
285   if (![folder isNotNull]) {
286     return [NSException exceptionWithHTTPStatus:404 /* not found */
287                         reason:@"did not find Trash folder!"];
288   }
289   
290   return ((self->trashFolder = [folder retain]));
291 }
292
293 /* WebDAV */
294
295 - (BOOL)davIsCollection {
296   return YES;
297 }
298
299 - (NSString *)shortTitle {
300   NSString *s, *login, *host;
301   NSRange r;
302
303   s = [self nameInContainer];
304   
305   r = [s rangeOfString:@"@"];
306   if (r.length > 0) {
307     login = [s substringToIndex:r.location];
308     host  = [s substringFromIndex:(r.location + r.length)];
309   }
310   else {
311     login = nil;
312     host  = s;
313   }
314   
315   r = [host rangeOfString:@"."];
316   if (r.length > 0)
317     host = [host substringToIndex:r.location];
318   
319   if ([login length] == 0)
320     return host;
321
322   r = [login rangeOfString:@"."];
323   if (r.length > 0)
324     login = [login substringToIndex:r.location];
325   
326   return [NSString stringWithFormat:@"%@@%@", login, host];
327 }
328
329 - (NSString *)davDisplayName {
330   return [self shortTitle];
331 }
332
333 @end /* SOGoMailAccount */