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 "NGImap4ServerRoot.h"
24 #include "NGImap4Context.h"
25 #include "NGImap4Client.h"
26 #include "NGImap4Message.h"
27 #include "NGImap4Functions.h"
28 #include "NGImap4Folder.h"
31 @interface NGImap4ServerRoot(Private)
32 - (void)initializeSubFolders;
35 @implementation NGImap4ServerRoot
37 static int ShowNonExistentFolder = -1;
38 static int FetchNewUnseenMessagesInSubFoldersOnDemand = -1;
41 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
43 // TODO: document the meaning!
44 ShowNonExistentFolder =
45 [ud boolForKey:@"ShowNonExistentFolder"] ? 1 : 0;
46 FetchNewUnseenMessagesInSubFoldersOnDemand =
47 [ud boolForKey:@"FetchNewUnseenMessagesInSubFoldersOnDemand"] ? 1 : 0;
50 + (id)serverRootWithContext:(NGImap4Context *)_context {
51 return [[[self alloc] initServerRootWithContext:_context] autorelease];
56 [self doesNotRecognizeSelector:_cmd];
60 - (id)initServerRootWithContext:(NGImap4Context *)_context {
61 if ((self = [super init])) {
62 self->context = [_context retain];
63 self->name = [[_context host] copy];
64 self->subFolders = nil;
66 self->noinferiors = ([[_context serverKind] isEqualToString:@"courier"])
73 [self->context resetSpecialFolders];
74 [self->context release];
76 [self->subFolders makeObjectsPerformSelector:@selector(clearParentFolder)];
77 [self->subFolders release];
81 - (NSException *)lastException {
82 return [self->context lastException];
84 - (void)resetLastException {
85 [self->context resetLastException];
88 - (BOOL)isEqual:(id)_obj {
91 if ([_obj isKindOfClass:[NGImap4ServerRoot class]])
92 return [self isEqualToServerRoot:_obj];
96 - (BOOL)isEqualToServerRoot:(NGImap4ServerRoot *)_root {
99 if ([_root context] == self->context)
106 - (NGImap4Context *)context {
107 return self->context;
114 - (NSString *)absoluteName {
118 - (NSArray *)messages {
122 - (NSArray *)messagesForQualifier:(EOQualifier *)_qualifier {
126 - (NSArray *)messagesForQualifier:(EOQualifier *)_q maxCount:(int)_cnt {
130 - (NSArray *)fetchSortedMessages:(NSArray *)_so {
134 - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange {
137 - (void)bulkFetchHeadersFor:(NSArray *)_array inRange:(NSRange)_aRange
138 withAllUnread:(BOOL)_unread
142 - (NSArray *)messageFlags {
146 - (NSArray *)subFolders {
147 if (self->subFolders == nil)
148 [self initializeSubFolders];
149 return self->subFolders;
152 - (NGImap4Folder *)subFolderWithName:(NSString *)_name
153 caseInsensitive:(BOOL)_caseIns
155 return _subFolderWithName(self, _name, _caseIns);
158 - (id<NGImap4Folder>)parentFolder {
166 - (BOOL)noinferiors {
167 return self->noinferiors;
174 - (BOOL)nonexistent {
177 - (BOOL)haschildren {
180 - (BOOL)hasnochildren {
210 - (BOOL)isOverQuota {
214 - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv fetchOnDemand:(BOOL)_fetch {
216 return _hasNewMessagesInSubFolder(self, _fetch);
220 - (BOOL)hasNewMessagesSearchRecursiv:(BOOL)_recursiv {
223 return _hasNewMessagesInSubFolder(self,
224 FetchNewUnseenMessagesInSubFoldersOnDemand);
227 - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_recursiv
228 fetchOnDemand:(BOOL)_fetch
231 return _hasUnseenMessagesInSubFolder(self, _fetch);
235 - (BOOL)hasUnseenMessagesSearchRecursiv:(BOOL)_recursiv {
237 return _hasUnseenMessagesInSubFolder(self,
238 FetchNewUnseenMessagesInSubFoldersOnDemand);
246 ** Should only happens if folder is rootfolder
249 - (void)initializeSubFolders {
250 NSEnumerator *folders;
256 if (self->subFolders != nil) {
257 [self resetSubFolders];
260 if ([self->context showOnlySubscribedInRoot]) {
261 res = [[self->context client] lsub:@"" pattern:@"%"];
264 res = [[self->context client] list:@"" pattern:@"%"];
267 if (!_checkResult(self->context, res, __PRETTY_FUNCTION__))
270 res = [res objectForKey:@"list"];
272 objs = calloc([res count] + 2, sizeof(id));
276 names = [res allKeys];
277 names = [names sortedArrayUsingSelector:
278 @selector(caseInsensitiveCompare:)];
279 folders = [names objectEnumerator];
284 while ((folder = [folders nextObject])) {
287 f = [res objectForKey:folder];
289 if (!ShowNonExistentFolder) {
290 if ([f containsObject:@"nonexistent"])
294 objs[cnt] = [[[NGImap4Folder alloc] initWithContext:self->context
295 name:folder flags:f parentFolder:self]
299 if ([[folder lowercaseString] isEqualToString:@"/inbox"])
302 if (!gotInbox && [self->context showOnlySubscribedInRoot]) {
303 /* try unsubscribed */
304 res = [[[self->context client] list:@"" pattern:@"%"] objectForKey:@"list"];
309 names = [res allKeys];
310 names = [names sortedArrayUsingSelector:
311 @selector(caseInsensitiveCompare:)];
312 folders = [names objectEnumerator];
314 while ((folder = [folders nextObject])) {
315 if ([[folder lowercaseString] isEqualToString:@"/inbox"]) {
316 objs[cnt] = [[[NGImap4Folder alloc] initWithContext:self->context
318 flags:[res objectForKey:folder]
326 self->subFolders = [[NSArray alloc] initWithObjects:objs count:cnt];
327 if (objs) free(objs); objs = NULL;
338 - (void)resetFolder {
341 - (void)resetStatus {
344 - (void)resetSubFolders {
345 [self->context resetSpecialFolders];
346 [self->subFolders release]; self->subFolders = nil;
349 - (BOOL)renameTo:(NSString *)_name {
355 - (BOOL)deleteSubFolder:(NGImap4Folder *)_folder {
356 return _deleteSubFolder(self, _folder);
359 - (BOOL)copySubFolder:(NGImap4Folder *)_f to:(id<NGImap4Folder>)_folder {
360 return _copySubFolder(self, _f, _folder);
363 - (BOOL)moveSubFolder:(NGImap4Folder *)_f to:(id<NGImap4Folder>)_folder {
364 return _moveSubFolder(self, _f, _folder);
367 - (BOOL)createSubFolderWithName:(NSString *)_name {
368 return _createSubFolderWithName(self, _name, NO);
374 - (BOOL)addFlag:(NSString *)_flag toMessages:(NSArray *)_messages {
378 - (BOOL)removeFlag:(NSString *)_flag fromMessages:(NSArray *)_messages {
382 - (BOOL)flag:(NSString *)_flag toMessages:(NSArray *)_messages
388 - (BOOL)flagToAllMessages:(NSString *)_flag add:(NSNumber *)_add {
392 - (BOOL)deleteAllMessages {
396 - (BOOL)deleteMessages:(NSArray *)_messages {
400 - (BOOL)moveMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder {
404 - (BOOL)copyMessages:(NSArray *)_messages toFolder:(NGImap4Folder *)_folder {
408 - (BOOL)appendMessage:(NSData *)_msg {
416 - (NSString *)description {
420 ms = [NSMutableString stringWithCapacity:64];
422 [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
424 if ((tmp = [self name]))
425 [ms appendFormat:@" name=%@", tmp];
426 if ((tmp = [self absoluteName]))
427 [ms appendFormat:@" absolute=%@", tmp];
429 [ms appendString:@">"];
435 NSEnumerator *enumerator;
438 enumerator = [[self subFolders] objectEnumerator];
440 while ((folder = [enumerator nextObject])) {
445 @end /* NGImap4ServerRoot */