2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OGo
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
23 #include "NGImap4DataSource.h"
24 #include <NGStreams/NGSocketExceptions.h>
27 @interface NGImap4DataSource(PrivateMethodes)
28 - (NSArray *)fetchMessages;
31 @interface EOQualifier(IMAPAdditions)
32 - (BOOL)isImap4UnseenQualifier;
35 @implementation NGImap4DataSource
37 static BOOL profileDS = NO;
40 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
42 if ((profileDS = [ud boolForKey:@"ProfileImap4DataSource"]))
43 NSLog(@"NGImap4DataSource: Profiling enabled!");
46 - (NSNotificationCenter *)notificationCenter {
47 static NSNotificationCenter *nc = nil;
48 if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain];
53 if ((self = [super init])) {
54 NSNotificationCenter *nc = [self notificationCenter];
57 selector:@selector(mailsWereDeleted:)
58 name:@"LSWImapMailWasDeleted"
62 selector:@selector(folderWasMoved:)
63 name:@"LSWImapMailFolderWasDeleted"
67 selector:@selector(flagsWereChanged:)
68 name:@"LSWImapMailFlagsChanged"
73 - (id)initWithFolder:(NGImap4Folder *)_folder {
74 if ((self = [self init])) {
75 [self setFolder:_folder];
81 [[self notificationCenter] removeObserver:self];
82 [self->folder release];
83 [self->fspec release];
84 [self->messages release];
85 [self->oldUnseenMessages release];
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;
97 - (void)mailsWereDeleted:(id)_obj {
98 [self->messages release]; self->messages = nil;
99 [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
102 - (void)flagsWereChanged:(id)_obj {
103 [self postDataSourceChangedNotification];
106 - (NSArray *)fetchObjects {
107 NSAutoreleasePool *pool;
110 if (self->messages) {
111 if (profileDS) [self logWithFormat:@"fetchObjects: already fetched."];
112 return self->messages;
115 pool = [[NSAutoreleasePool alloc] init];
117 if (profileDS) [self logWithFormat:@"fetchObjects: fetch ..."];
119 tmp = (self->folder) ? [self fetchMessages] : [NSArray array];
121 if (profileDS) [self logWithFormat:@"fetchObjects: done ..."];
122 ASSIGN(self->messages, tmp);
125 if (profileDS) [self logWithFormat:@"fetchObjects: pool released."];
127 return self->messages;
131 if (profileDS) [self logWithFormat:@"clear: do ..."];
132 [self->messages release];
133 self->messages = nil;
134 if (profileDS) [self logWithFormat:@"clear: done."];
137 - (void)setFolder:(NGImap4Folder *)_folder {
138 ASSIGN(self->folder, _folder);
140 [self->messages release]; self->messages = nil;
141 [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
143 [self postDataSourceChangedNotification];
145 - (NGImap4Folder *)folder {
149 - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec {
150 if ([_fetchSpec isEqual:self->fspec]) return;
152 ASSIGN(self->fspec, _fetchSpec);
153 [self->messages release]; self->messages = nil;
154 [self postDataSourceChangedNotification];
156 - (EOFetchSpecification *)fetchSpecification {
161 return self->oldExists;
164 return self->oldUnseen;
167 /* private methodes */
169 - (NSException *)handleImapException:(NSException *)_exception {
170 if ([_exception isKindOfClass:[NGImap4ResponseException class]]) {
171 NSDictionary *record;
174 record = [[_exception userInfo] objectForKey:@"RawResponse"];
175 record = [record objectForKey:@"ResponseResult"];
176 str = [record objectForKey:@"description"];
177 fprintf(stderr, "%s", [str cString]);
179 else if ([_exception isKindOfClass:[NGIOException class]]) {
180 fprintf(stderr, "%s", [[_exception reason] cString]);
182 else if ([_exception isKindOfClass:[NGImap4Exception class]]) {
183 fprintf(stderr, "%s", [[_exception description] cString]);
186 fprintf(stderr, "\n");
189 fprintf(stderr, "\n");
193 - (NSArray *)_processUnseen:(NSArray *)result {
194 if (profileDS) [self logWithFormat:@"process unseen ..."];
196 if (self->oldUnseenMessages) { // this implies, the folder hasn't changed
197 NSMutableSet *set = nil;
199 set = [[NSMutableSet alloc] initWithArray:result];
200 [set addObjectsFromArray:self->oldUnseenMessages];
201 result = [[[set allObjects] retain] autorelease];
204 [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
205 ASSIGN(self->oldUnseenMessages, result);
207 if (profileDS) [self logWithFormat:@"process unseen: done."];
210 - (NSArray *)_sortMessages:(NSArray *)result {
211 NSArray *sortOrderings;
213 if ((sortOrderings = [[self fetchSpecification] sortOrderings]) == nil)
216 if (profileDS) [self logWithFormat:@"sort messages ..."];
217 result = [result sortedArrayUsingKeyOrderArray:sortOrderings];
218 if (profileDS) [self logWithFormat:@"sort messages: done."];
222 - (NSArray *)fetchMessages {
223 EOQualifier *qualifier;
224 NSArray *result = nil;
226 if (profileDS) [self logWithFormat:@"fetchMessages: fetch ..."];
228 qualifier = [[self fetchSpecification] qualifier];
231 if (![qualifier isImap4UnseenQualifier]) {
232 [self->oldUnseenMessages release];
233 self->oldUnseenMessages = nil;
236 if (profileDS) [self logWithFormat:@"fetchMessages: exists&unseen ..."];
237 self->oldExists = [self->folder exists];
238 self->oldUnseen = [self->folder unseen];
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 ..."];
247 [[self handleImapException:localException] raise];
248 result = [NSArray array];
252 if (profileDS) [self logWithFormat:@"fetchMessages: ex handler done ..."];
254 if ([qualifier isImap4UnseenQualifier])
255 result = [self _processUnseen:result];
257 result = [self _sortMessages:result];
258 if (profileDS) [self logWithFormat:@"fetchMessages: done."];
262 @end /* NGImap4DataSource */