]> err.no Git - sope/blob - sope-mime/NGImap4/NGImap4DataSource.m
new Xcode projects
[sope] / sope-mime / NGImap4 / NGImap4DataSource.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OGo
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 //$Id$
22
23 #include "NGImap4DataSource.h"
24 #include <NGStreams/NGSocketExceptions.h>
25 #include "imCommon.h"
26
27 @interface NGImap4DataSource(PrivateMethodes)
28 - (NSArray *)fetchMessages;
29 @end
30
31 @interface EOQualifier(IMAPAdditions)
32 - (BOOL)isImap4UnseenQualifier;
33 @end
34
35 @implementation NGImap4DataSource
36
37 static BOOL profileDS = NO;
38
39 + (void)initialize {
40   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
41   
42   if ((profileDS = [ud boolForKey:@"ProfileImap4DataSource"]))
43     NSLog(@"NGImap4DataSource: Profiling enabled!");
44 }
45
46 - (NSNotificationCenter *)notificationCenter {
47   static NSNotificationCenter *nc = nil;
48   if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain];
49   return nc;
50 }
51
52 - (id)init {
53   if ((self = [super init])) {
54     NSNotificationCenter *nc = [self notificationCenter];
55     
56     [nc addObserver:self
57         selector:@selector(mailsWereDeleted:)
58         name:@"LSWImapMailWasDeleted"
59         object:nil];
60
61     [nc addObserver:self
62         selector:@selector(folderWasMoved:)
63         name:@"LSWImapMailFolderWasDeleted"
64         object:nil];
65     
66     [nc addObserver:self
67         selector:@selector(flagsWereChanged:)
68         name:@"LSWImapMailFlagsChanged"
69         object:nil];
70   }
71   return self;
72 }
73 - (id)initWithFolder:(NGImap4Folder *)_folder {
74   if ((self = [self init])) {
75     [self setFolder:_folder];
76   }
77   return self;
78 }
79
80 - (void)dealloc {
81   [[self notificationCenter] removeObserver:self];
82   [self->folder   release];
83   [self->fspec    release];
84   [self->messages release];
85   [self->oldUnseenMessages release];
86   [super dealloc];
87 }
88
89 /* operations */
90
91 - (void)folderWasMoved:(id)_obj {
92   [self->folder   release]; self->folder   = nil;
93   [self->messages release]; self->messages = nil;
94   [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
95 }
96
97 - (void)mailsWereDeleted:(id)_obj {
98   [self->messages          release]; self->messages          = nil;
99   [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
100 }
101
102 - (void)flagsWereChanged:(id)_obj {
103   [self postDataSourceChangedNotification];
104 }
105
106 - (NSArray *)fetchObjects {
107   NSAutoreleasePool *pool;
108   NSArray *tmp;
109   
110   if (self->messages) {
111     if (profileDS) [self logWithFormat:@"fetchObjects: already fetched."];
112     return self->messages;
113   }
114     
115   pool = [[NSAutoreleasePool alloc] init];
116   {  
117     if (profileDS) [self logWithFormat:@"fetchObjects: fetch ..."];
118     
119     tmp = (self->folder) ? [self fetchMessages] : [NSArray array];
120     
121     if (profileDS) [self logWithFormat:@"fetchObjects:   done ..."];
122     ASSIGN(self->messages, tmp);
123   }
124   [pool release];
125   if (profileDS) [self logWithFormat:@"fetchObjects:   pool released."];
126   
127   return self->messages;
128 }
129
130 - (void)clear {
131   if (profileDS) [self logWithFormat:@"clear: do ..."];
132   [self->messages release];
133   self->messages = nil;
134   if (profileDS) [self logWithFormat:@"clear: done."];
135 }
136
137 - (void)setFolder:(NGImap4Folder *)_folder {
138   ASSIGN(self->folder, _folder);
139   
140   [self->messages          release]; self->messages          = nil;
141   [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
142   
143   [self postDataSourceChangedNotification];
144 }
145 - (NGImap4Folder *)folder {
146   return self->folder;
147 }
148
149 - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec {
150   if ([_fetchSpec isEqual:self->fspec]) return;
151   
152   ASSIGN(self->fspec, _fetchSpec);
153   [self->messages release]; self->messages = nil;
154   [self postDataSourceChangedNotification];
155 }
156 - (EOFetchSpecification *)fetchSpecification {
157   return self->fspec;
158 }
159
160 - (int)oldExists {
161   return self->oldExists;
162 }
163 - (int)oldUnseen {
164   return self->oldUnseen;
165 }
166
167 /* private methodes */
168
169 - (NSException *)handleImapException:(NSException *)_exception {
170   if ([_exception isKindOfClass:[NGImap4ResponseException class]]) {
171     NSDictionary *record;
172     NSString *str;
173     
174     record = [[_exception userInfo] objectForKey:@"RawResponse"];
175     record = [record objectForKey:@"ResponseResult"];
176     str    = [record objectForKey:@"description"];
177     fprintf(stderr, "%s", [str cString]);
178   }    
179   else if ([_exception isKindOfClass:[NGIOException class]]) {
180     fprintf(stderr, "%s", [[_exception reason] cString]);
181   }
182   else if ([_exception isKindOfClass:[NGImap4Exception class]]) {
183     fprintf(stderr, "%s", [[_exception description] cString]);
184   }
185   else {
186     fprintf(stderr, "\n");
187     return _exception;
188   }
189   fprintf(stderr, "\n");
190   return nil;
191 }
192
193 - (NSArray *)_processUnseen:(NSArray *)result {
194   if (profileDS) [self logWithFormat:@"process unseen ..."];
195     
196   if (self->oldUnseenMessages) { // this implies, the folder hasn't changed
197       NSMutableSet *set = nil;
198       
199       set = [[NSMutableSet alloc] initWithArray:result];
200       [set addObjectsFromArray:self->oldUnseenMessages];
201       result = [[[set allObjects] retain] autorelease];
202       [set release];
203   }
204   [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
205   ASSIGN(self->oldUnseenMessages, result);
206     
207   if (profileDS) [self logWithFormat:@"process unseen: done."];
208   return result;
209 }
210 - (NSArray *)_sortMessages:(NSArray *)result {
211   NSArray *sortOrderings;
212
213   if ((sortOrderings = [[self fetchSpecification] sortOrderings]) == nil)
214     return result;
215   
216   if (profileDS) [self logWithFormat:@"sort messages ..."];
217   result = [result sortedArrayUsingKeyOrderArray:sortOrderings];
218   if (profileDS) [self logWithFormat:@"sort messages: done."];
219   return result;
220 }
221
222 - (NSArray *)fetchMessages {
223   EOQualifier *qualifier;
224   NSArray     *result  = nil;
225
226   if (profileDS) [self logWithFormat:@"fetchMessages: fetch ..."];
227   
228   qualifier = [[self fetchSpecification] qualifier];
229   
230   NS_DURING {
231     if (![qualifier isImap4UnseenQualifier]) {
232       [self->oldUnseenMessages release];
233       self->oldUnseenMessages = nil;
234     }
235     
236     if (profileDS) [self logWithFormat:@"fetchMessages:   exists&unseen ..."];
237     self->oldExists = [self->folder exists];
238     self->oldUnseen = [self->folder unseen];
239     
240     if (profileDS) [self logWithFormat:@"fetchMessages:   messages ..."];
241     result = (qualifier == nil)
242       ? [self->folder messages]
243       : [self->folder messagesForQualifier:qualifier];
244     if (profileDS) [self logWithFormat:@"fetchMessages:   messages done ..."];
245   }
246   NS_HANDLER {
247     [[self handleImapException:localException] raise];
248     result = [NSArray array];
249   }
250   NS_ENDHANDLER;
251   
252   if (profileDS) [self logWithFormat:@"fetchMessages:   ex handler done ..."];
253   
254   if ([qualifier isImap4UnseenQualifier])
255     result = [self _processUnseen:result];
256   
257   result = [self _sortMessages:result];
258   if (profileDS) [self logWithFormat:@"fetchMessages: done."];
259   return result;
260 }
261
262 @end /* NGImap4DataSource */