2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE 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 SOPE 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 SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include "NGImap4DataSource.h"
23 #include <NGStreams/NGSocketExceptions.h>
26 @interface NGImap4DataSource(PrivateMethodes)
27 - (NSArray *)fetchMessages;
30 @interface EOQualifier(IMAPAdditions)
31 - (BOOL)isImap4UnseenQualifier;
34 @implementation NGImap4DataSource
36 static BOOL profileDS = NO;
39 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
41 if ((profileDS = [ud boolForKey:@"ProfileImap4DataSource"]))
42 NSLog(@"NGImap4DataSource: Profiling enabled!");
45 - (NSNotificationCenter *)notificationCenter {
46 static NSNotificationCenter *nc = nil;
47 if (nc == nil) nc = [[NSNotificationCenter defaultCenter] retain];
52 if ((self = [super init])) {
53 NSNotificationCenter *nc = [self notificationCenter];
56 selector:@selector(mailsWereDeleted:)
57 name:@"LSWImapMailWasDeleted"
61 selector:@selector(folderWasMoved:)
62 name:@"LSWImapMailFolderWasDeleted"
66 selector:@selector(flagsWereChanged:)
67 name:@"LSWImapMailFlagsChanged"
72 - (id)initWithFolder:(NGImap4Folder *)_folder {
73 if ((self = [self init])) {
74 [self setFolder:_folder];
80 [[self notificationCenter] removeObserver:self];
81 [self->folder release];
82 [self->fspec release];
83 [self->messages release];
84 [self->oldUnseenMessages release];
90 - (void)folderWasMoved:(id)_obj {
91 [self->folder release]; self->folder = nil;
92 [self->messages release]; self->messages = nil;
93 [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
96 - (void)mailsWereDeleted:(id)_obj {
97 [self->messages release]; self->messages = nil;
98 [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
101 - (void)flagsWereChanged:(id)_obj {
102 [self postDataSourceChangedNotification];
105 - (NSArray *)fetchObjects {
106 NSAutoreleasePool *pool;
109 if (self->messages) {
110 if (profileDS) [self logWithFormat:@"fetchObjects: already fetched."];
111 return self->messages;
114 pool = [[NSAutoreleasePool alloc] init];
116 if (profileDS) [self logWithFormat:@"fetchObjects: fetch ..."];
118 tmp = (self->folder) ? [self fetchMessages] : [NSArray array];
120 if (profileDS) [self logWithFormat:@"fetchObjects: done ..."];
121 ASSIGN(self->messages, tmp);
124 if (profileDS) [self logWithFormat:@"fetchObjects: pool released."];
126 return self->messages;
130 if (profileDS) [self logWithFormat:@"clear: do ..."];
131 [self->messages release];
132 self->messages = nil;
133 if (profileDS) [self logWithFormat:@"clear: done."];
136 - (void)setFolder:(NGImap4Folder *)_folder {
137 ASSIGN(self->folder, _folder);
139 [self->messages release]; self->messages = nil;
140 [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
142 [self postDataSourceChangedNotification];
144 - (NGImap4Folder *)folder {
148 - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec {
149 if ([_fetchSpec isEqual:self->fspec]) return;
151 ASSIGN(self->fspec, _fetchSpec);
152 [self->messages release]; self->messages = nil;
153 [self postDataSourceChangedNotification];
155 - (EOFetchSpecification *)fetchSpecification {
160 return self->oldExists;
163 return self->oldUnseen;
166 /* private methodes */
168 - (NSException *)handleImapException:(NSException *)_exception {
169 if ([_exception isKindOfClass:[NGImap4ResponseException class]]) {
170 NSDictionary *record;
173 record = [[_exception userInfo] objectForKey:@"RawResponse"];
174 record = [record objectForKey:@"ResponseResult"];
175 str = [record objectForKey:@"description"];
176 fprintf(stderr, "%s", [str cString]);
178 else if ([_exception isKindOfClass:[NGIOException class]]) {
179 fprintf(stderr, "%s", [[_exception reason] cString]);
181 else if ([_exception isKindOfClass:[NGImap4Exception class]]) {
182 fprintf(stderr, "%s", [[_exception description] cString]);
185 fprintf(stderr, "\n");
188 fprintf(stderr, "\n");
192 - (NSArray *)_processUnseen:(NSArray *)result {
193 if (profileDS) [self logWithFormat:@"process unseen ..."];
195 if (self->oldUnseenMessages) { // this implies, the folder hasn't changed
196 NSMutableSet *set = nil;
198 set = [[NSMutableSet alloc] initWithArray:result];
199 [set addObjectsFromArray:self->oldUnseenMessages];
200 result = [[[set allObjects] retain] autorelease];
203 [self->oldUnseenMessages release]; self->oldUnseenMessages = nil;
204 ASSIGN(self->oldUnseenMessages, result);
206 if (profileDS) [self logWithFormat:@"process unseen: done."];
209 - (NSArray *)_sortMessages:(NSArray *)result {
210 NSArray *sortOrderings;
212 if ((sortOrderings = [[self fetchSpecification] sortOrderings]) == nil)
215 if (profileDS) [self logWithFormat:@"sort messages ..."];
216 result = [result sortedArrayUsingKeyOrderArray:sortOrderings];
217 if (profileDS) [self logWithFormat:@"sort messages: done."];
221 - (NSArray *)fetchMessages {
222 EOQualifier *qualifier;
223 NSArray *result = nil;
225 if (profileDS) [self logWithFormat:@"fetchMessages: fetch ..."];
227 qualifier = [[self fetchSpecification] qualifier];
230 if (![qualifier isImap4UnseenQualifier]) {
231 [self->oldUnseenMessages release];
232 self->oldUnseenMessages = nil;
235 if (profileDS) [self logWithFormat:@"fetchMessages: exists&unseen ..."];
236 self->oldExists = [self->folder exists];
237 self->oldUnseen = [self->folder unseen];
239 if (profileDS) [self logWithFormat:@"fetchMessages: messages ..."];
240 result = (qualifier == nil)
241 ? [self->folder messages]
242 : [self->folder messagesForQualifier:qualifier];
243 if (profileDS) [self logWithFormat:@"fetchMessages: messages done ..."];
246 [[self handleImapException:localException] raise];
247 result = [NSArray array];
251 if (profileDS) [self logWithFormat:@"fetchMessages: ex handler done ..."];
253 if ([qualifier isImap4UnseenQualifier])
254 result = [self _processUnseen:result];
256 result = [self _sortMessages:result];
257 if (profileDS) [self logWithFormat:@"fetchMessages: done."];
261 @end /* NGImap4DataSource */