]> err.no Git - scalable-opengroupware.org/blob - SoObjects/Mailer/SOGoMailManager.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1131 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SoObjects / Mailer / SOGoMailManager.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 #import <Foundation/NSArray.h>
23
24 #import <NGObjWeb/NSException+HTTP.h>
25 #import <NGExtensions/NSNull+misc.h>
26 #import <NGImap4/NGImap4Connection.h>
27 #import <NGImap4/NGImap4ConnectionManager.h>
28
29 #import "SOGoMailManager.h"
30
31 /*
32   Could check read-write state:
33     dict = [[self->context client] select:[self absoluteName]];
34     self->isReadOnly = 
35       [[dict objectForKey:@"access"] isEqualToString:@"READ-WRITE"]
36       ? NoNumber : YesNumber;
37   
38   TODO: to implement copy, use "uid copy" instead of "copy" as used by
39         NGImap4Client.
40 */
41
42 @implementation NGImap4ConnectionManager(SOGoMailManager)
43
44 + (id)defaultMailManager {
45   return [self defaultConnectionManager];
46 }
47
48
49 - (NSException *)errorForMissingEntryAtURL:(NSURL *)_url {
50   // TODO: improve
51   return [NSException exceptionWithHTTPStatus:404 /* Not Found */
52                       reason:@"Did not find mail URL"];
53 }
54
55 /* client object */
56
57
58 /* folder hierarchy */
59
60 - (NSArray *)subfoldersForURL:(NSURL *)_url password:(NSString *)_pwd {
61   NGImap4Connection *entry;
62
63   /* check connection cache */
64   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
65     return nil;
66   
67   return [entry subfoldersForURL:_url];
68 }
69
70 - (NSArray *)allFoldersForURL:(NSURL *)_url password:(NSString *)_pwd {
71   NGImap4Connection *entry;
72   
73   /* check connection cache */
74   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
75     return nil;
76   
77   return [entry allFoldersForURL:_url];
78 }
79
80 /* messages */
81
82 - (NSArray *)fetchUIDsInURL:(NSURL *)_url qualifier:(id)_qualifier
83   sortOrdering:(id)_so password:(NSString *)_pwd
84 {
85   /* 
86      sortOrdering can be an NSString, an EOSortOrdering or an array of EOS.
87   */
88   NGImap4Connection *entry;
89   
90   /* check connection cache */
91   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
92     return nil;
93   
94   return [entry fetchUIDsInURL:_url qualifier:_qualifier sortOrdering:_so];
95 }
96
97 - (NSArray *)fetchUIDs:(NSArray *)_uids inURL:(NSURL *)_url
98   parts:(NSArray *)_parts password:(NSString *)_pwd
99 {
100   // currently returns a dict?!
101   /*
102     Allowed fetch keys:
103       UID
104       BODY.PEEK[<section>]<<partial>>
105       BODY            [this is the bodystructure, supported]
106       BODYSTRUCTURE   [not supported yet!]
107       ENVELOPE        [this is a parsed header, but does not include type]
108       FLAGS
109       INTERNALDATE
110       RFC822
111       RFC822.HEADER
112       RFC822.SIZE
113       RFC822.TEXT
114   */
115   NGImap4Connection *entry;
116   
117   if (_uids == nil)
118     return nil;
119   if ([_uids count] == 0)
120     return nil; // TODO: might break empty folders?! return a dict!
121   
122   /* check connection cache */
123   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
124     return nil;
125   
126   return [entry fetchUIDs:_uids inURL:_url parts:_parts];
127 }
128
129 - (NSException *)expungeAtURL:(NSURL *)_url password:(NSString *)_pwd {
130   NGImap4Connection *entry;
131   
132   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
133     return [self errorForMissingEntryAtURL:_url];
134   
135   return [entry expungeAtURL:_url];
136 }
137
138 - (id)fetchURL:(NSURL *)_url parts:(NSArray *)_parts password:(NSString *)_pwd{
139   NGImap4Connection *entry;
140   
141   if (![_url isNotNull]) return nil;
142   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
143     return [self errorForMissingEntryAtURL:_url];
144   
145   return [entry fetchURL:_url parts:_parts];
146 }
147
148 - (NSData *)fetchContentOfBodyPart:(NSString *)_partId
149   atURL:(NSURL *)_url password:(NSString *)_pwd
150 {
151   NGImap4Connection *entry;
152
153   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
154     return nil; // TODO: improve?
155
156   return [entry fetchContentOfBodyPart:_partId atURL:_url];
157 }
158
159 - (NSException *)addOrRemove:(BOOL)_flag flags:(id)_f
160   toURL:(NSURL *)_url password:(NSString *)_p
161 {
162   NGImap4Connection *entry;
163
164   if ((entry = [self connectionForURL:_url password:_p]) == nil)
165     return [self errorForMissingEntryAtURL:_url];
166
167   return [entry addOrRemove:_flag flags:_f toURL:_url];
168 }
169 - (NSException *)addFlags:(id)_f toURL:(NSURL *)_u password:(NSString *)_p {
170   return [self addOrRemove:YES flags:_f toURL:_u password:_p];
171 }
172 - (NSException *)removeFlags:(id)_f toURL:(NSURL *)_u password:(NSString *)_p {
173   return [self addOrRemove:NO flags:_f toURL:_u password:_p];
174 }
175
176 - (NSException *)markURLDeleted:(NSURL *)_url password:(NSString *)_p {
177   return [self addOrRemove:YES flags:@"Deleted" toURL:_url password:_p];
178 }
179
180 - (NSException *)postData:(NSData *)_data flags:(id)_f
181   toFolderURL:(NSURL *)_url password:(NSString *)_p
182 {
183   NGImap4Connection *entry;
184
185   if (![_url isNotNull]) return nil;
186   
187   if ((entry = [self connectionForURL:_url password:_p]) == nil)
188     return [self errorForMissingEntryAtURL:_url];
189   
190   return [entry postData:_data flags:_f toFolderURL:_url];
191 }
192
193 - (NSException *)copyMailURL:(NSURL *)_srcurl toFolderURL:(NSURL *)_desturl
194   password:(NSString *)_pwd
195 {
196   NGImap4Connection *entry;
197   
198   /* check connection cache */
199   
200   if ((entry = [self connectionForURL:_srcurl password:_pwd]) == nil)
201     return [self errorForMissingEntryAtURL:_srcurl];
202   
203   /* check whether URLs are on different servers */
204   
205   if ([self connectionForURL:_desturl password:_pwd] != entry) {
206     // TODO: find a better error code
207     return [NSException exceptionWithHTTPStatus:502 /* Bad Gateway */
208                         reason:@"source and destination on different servers"];
209   }  
210   
211   return [entry copyMailURL:_srcurl toFolderURL:_desturl];
212 }
213
214 /* managing folders */
215
216 - (BOOL)isPermissionDeniedResult:(id)_result {
217   if ([[_result valueForKey:@"result"] intValue] != 0)
218     return NO;
219   
220   return [[_result valueForKey:@"reason"] 
221                    isEqualToString:@"Permission denied"];
222 }
223
224 - (BOOL)doesMailboxExistAtURL:(NSURL *)_url password:(NSString *)_pwd {
225   NGImap4Connection *entry;
226   
227   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
228     return NO;
229   
230   return [entry doesMailboxExistAtURL:_url];
231 }
232
233 - (id)infoForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd {
234   NGImap4Connection *entry;
235   
236   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
237     return [self errorForMissingEntryAtURL:_url];
238   
239   return [entry infoForMailboxAtURL:_url];
240 }
241
242 - (NSException *)createMailbox:(NSString *)_mailbox atURL:(NSURL *)_url
243   password:(NSString *)_pwd
244 {
245   NGImap4Connection *entry;
246   
247   /* check connection cache */
248   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
249     return [self errorForMissingEntryAtURL:_url];
250
251   return [entry createMailbox:_mailbox atURL:_url];
252 }
253
254 - (NSException *)deleteMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd {
255   NGImap4Connection *entry;
256   
257   /* check connection cache */
258   
259   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
260     return [self errorForMissingEntryAtURL:_url];
261   
262   return [entry deleteMailboxAtURL:_url];
263 }
264
265 - (NSException *)moveMailboxAtURL:(NSURL *)_srcurl toURL:(NSURL *)_desturl
266   password:(NSString *)_pwd
267 {
268   NGImap4Connection *entry;
269   
270   /* check connection cache */
271   
272   if ((entry = [self connectionForURL:_srcurl password:_pwd]) == nil)
273     return [self errorForMissingEntryAtURL:_srcurl];
274   
275   /* check whether URLs are on different servers */
276   
277   if ([self connectionForURL:_desturl password:_pwd] != entry) {
278     // TODO: find a better error code
279     return [NSException exceptionWithHTTPStatus:502 /* Bad Gateway */
280                         reason:@"source and destination on different servers"];
281   }  
282   
283   return [entry moveMailboxAtURL:_srcurl toURL:_desturl];
284 }
285
286 - (NSDictionary *)aclForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd {
287   /*
288     Returns a mapping of uid => permission strings, eg:
289       guizmo.g = lrs;
290       root     = lrswipcda;
291   */
292   NGImap4Connection *entry;
293   
294   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
295     return (id)[self errorForMissingEntryAtURL:_url];
296   
297   return [entry aclForMailboxAtURL:_url];
298 }
299
300 - (NSString *)myRightsForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd {
301   NGImap4Connection *entry;
302   
303   if ((entry = [self connectionForURL:_url password:_pwd]) == nil)
304     return (id)[self errorForMissingEntryAtURL:_url];
305
306   return [entry myRightsForMailboxAtURL:_url];
307 }
308
309 /* bulk flag adding (eg used for empty/trash) */
310
311 - (NSException *)addFlags:(id)_f toAllMessagesInURL:(NSURL *)_url
312   password:(NSString *)_p
313 {
314   NGImap4Connection *entry;
315   
316   if (![_url isNotNull]) return nil;
317   if (![_f   isNotNull]) return nil;
318   
319   if ((entry = [self connectionForURL:_url password:_p]) == nil)
320     return [self errorForMissingEntryAtURL:_url];
321   
322   return [entry addFlags:_f toAllMessagesInURL:_url];
323 }
324
325 @end /* NGImap4ConnectionManager(SOGoMailManager) */