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