From c27d8c707189bcb24f6e72c81a36ed5e589ef12e Mon Sep 17 00:00:00 2001 From: helge Date: Thu, 30 Sep 2004 23:12:09 +0000 Subject: [PATCH] improvements in NGImap4Client git-svn-id: http://svn.opengroupware.org/SOPE/trunk@206 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-mime/ChangeLog | 4 + sope-mime/NGImap4/ChangeLog | 9 ++ sope-mime/NGImap4/NGImap4Client.h | 13 +- sope-mime/NGImap4/NGImap4Client.m | 218 ++++++++++++++++++++++-------- sope-mime/NGImap4/NGImap4Folder.m | 23 ++-- sope-mime/Version | 2 +- 6 files changed, 202 insertions(+), 67 deletions(-) diff --git a/sope-mime/ChangeLog b/sope-mime/ChangeLog index b0b2b16a..39566f10 100644 --- a/sope-mime/ChangeLog +++ b/sope-mime/ChangeLog @@ -1,3 +1,7 @@ +2004-10-01 Helge Hess + + * NGImap4: NGImap4Client improvements (v4.3.183) + 2004-09-30 Helge Hess * NGMime: fixed OGo buf #936 (v4.3.182) diff --git a/sope-mime/NGImap4/ChangeLog b/sope-mime/NGImap4/ChangeLog index b65e3a66..5e87e179 100644 --- a/sope-mime/NGImap4/ChangeLog +++ b/sope-mime/NGImap4/ChangeLog @@ -1,3 +1,12 @@ +2004-09-30 Helge Hess + + * v4.3.183 + + * NGImap4Folder.m: use new sort API + + * NGImap4Client.m: deprecated -sort:qualifier: in favor of + -sort:qualifier:encoding:, code cleanups + 2004-09-29 Helge Hess * NGImap4Client.m: improved -description (v4.3.181) diff --git a/sope-mime/NGImap4/NGImap4Client.h b/sope-mime/NGImap4/NGImap4Client.h index 0d7f0120..baee1390 100644 --- a/sope-mime/NGImap4/NGImap4Client.h +++ b/sope-mime/NGImap4/NGImap4Client.h @@ -127,9 +127,10 @@ typedef enum { - (NSDictionary *)expunge; - (NSDictionary *)sort:(NSArray *)_sortOrderings - qualifier:(EOQualifier *)_qual; + qualifier:(EOQualifier *)_qual + encoding:(NSString *)_encoding; - (NSDictionary *)fetchUids:(NSArray *)_uids parts:(NSArray *)_parts; -- (NSDictionary *)fetchUid:(unsigned)_uid parts:(NSArray *)_parts; +- (NSDictionary *)fetchUid:(unsigned)_uid parts:(NSArray *)_parts; - (NSDictionary *)fetchFrom:(unsigned)_from to:(unsigned)_to parts:(NSArray *)_parts; - (NSDictionary *)storeUid:(unsigned)_uid add:(NSNumber *)_add @@ -147,9 +148,17 @@ typedef enum { - (NSDictionary *)searchWithQualifier:(EOQualifier *)_qualifier; +/* context accessors (DEPRECATED) */ + - (void)setContext:(NGImap4Context *)_ctx; - (NGImap4Context *)context; +/* raw methods */ + +- (NSDictionary *)primarySort:(NSString *)_sortString + qualifierString:(NSString *)_qualString + encoding:(NSString *)_encoding; + @end #endif /* __SOPE_NGImap4_NGImap4Client_H__ */ diff --git a/sope-mime/NGImap4/NGImap4Client.m b/sope-mime/NGImap4/NGImap4Client.m index 24710326..0511a259 100644 --- a/sope-mime/NGImap4/NGImap4Client.m +++ b/sope-mime/NGImap4/NGImap4Client.m @@ -593,6 +593,19 @@ static BOOL ImapDebugEnabled = NO; } - (NSDictionary *)select:(NSString *)_folder { + /* + Select a folder (required for a lot of methods). + eg: 'SELECT "INBOX"' + + The result dict contains the following keys: + 'result' - a boolean + 'access' - string (eg "READ-WRITE") + 'exists' - number? (eg 1) + 'recent' - number? (eg 0) + 'expunge' - array (of what?) + 'flags' - array of strings (eg (answered,flagged,draft,seen); + 'RawResponse' - the raw IMAP4 response + */ NSString *s; id tmp; @@ -911,6 +924,12 @@ static BOOL ImapDebugEnabled = NO; } - (NSString *)_searchExprForQual:(EOQualifier *)_qualifier { + /* + samples: + ' ALL' + ' SINCE 1-Feb-1994' + ' TEXT "why SOPE rocks"' + */ id result; if (_qualifier == nil) @@ -925,91 +944,182 @@ static BOOL ImapDebugEnabled = NO; return result; } -/* siehe draft-ietf-imapext-thread-12.txt - returns an array of uids in sort order */ - - (NSDictionary *)threadBySubject:(BOOL)_bySubject charset:(NSString *)_charSet { - NSString *threadStr; - NSString *threadAlg; + /* + http://www.ietf.org/proceedings/03mar/I-D/draft-ietf-imapext-thread-12.txt - if (_bySubject) - threadAlg = @"REFERENCES"; - else - threadAlg = @"ORDEREDSUBJECT"; + Returns an array of uids in sort order. + + Parameters: + _bySubject - if yes, use "REFERENCES" else "ORDEREDSUBJECT" (TODO: ?!) + _charSet - default: "UTF-8" + Generates: + UID THREAD REFERENCES|ORDEREDSUBJECT UTF-8 ALL + */ + NSString *threadStr; + NSString *threadAlg; + + threadAlg = (_bySubject) + ? @"REFERENCES" + : @"ORDEREDSUBJECT"; - if (![_charSet length]) + if ([_charSet length] == 0) _charSet = @"UTF-8"; - + threadStr = [NSString stringWithFormat:@"UID THREAD %@ %@ ALL", threadAlg, _charSet]; - + return [self->normer normalizeThreadResponse: [self processCommand:threadStr]]; } -- (NSDictionary *)sort:(NSArray *)_sortOrderings - qualifier:(EOQualifier *)_qual -{ - /* siehe draft-ietf-imapext-sort */ - /* returns an array of uids in sort order */ +- (NSString *)_generateIMAP4SortOrdering:(EOSortOrdering *)_sortOrdering { + SEL sel; + NSString *key; + + key = [_sortOrdering key]; + if ([key length] == 0) + return nil; + + if (![AllowedSortKeys containsObject:[key uppercaseString]]) { + [self logWithFormat:@"ERROR[%s] key %@ is not allowed here!", + __PRETTY_FUNCTION__, key]; + return nil; + } + + sel = [_sortOrdering selector]; + if (sel_eq(sel, EOCompareDescending) || + sel_eq(sel, EOCompareCaseInsensitiveDescending)) { + return [@"REVERSE " stringByAppendingString:key]; + } + // TODO: check other selectors whether they make sense instead of silent acc. + + return key; +} + +- (NSString *)_generateIMAP4SortOrderings:(NSArray *)_sortOrderings { + /* + turn EOSortOrdering into an IMAP4 value for "SORT()" + + eg: "DATE REVERSE SUBJECT" + + It also checks a set of allowed sort-keys (don't know why) + */ NSMutableString *sortStr; - NSEnumerator *enumerator; + NSEnumerator *soe; EOSortOrdering *so; BOOL isFirst = YES; - - sortStr = [NSMutableString stringWithCapacity:128]; if ([_sortOrderings count] == 0) - return [NSDictionary dictionaryWithObjectsAndKeys:@"result", NoNumber,nil]; - - enumerator = [_sortOrderings objectEnumerator]; - - [sortStr appendString:@"UID SORT ("]; + return nil; - while ((so = [enumerator nextObject])) { - SEL sel; - NSString *key; - - key = [[so key] uppercaseString]; - - if ([key length] == 0) - continue; + sortStr = [NSMutableString stringWithCapacity:128]; + soe = [_sortOrderings objectEnumerator]; + while ((so = [soe nextObject])) { + NSString *s; - if (![AllowedSortKeys containsObject:key]) { - [self logWithFormat:@"ERROR[%s] key %@ is not allowed here!", - __PRETTY_FUNCTION__, key]; + s = [self _generateIMAP4SortOrdering:so]; + if (s == nil) continue; - } + if (isFirst) isFirst = NO; else [sortStr appendString:@" "]; - sel = [so selector]; - - if (sel_eq(sel, EOCompareDescending) || - sel_eq(sel, EOCompareCaseInsensitiveDescending)) { - [sortStr appendString:@"REVERSE "]; - } - [sortStr appendString:[so key]]; - } - if (isFirst) { /* found no valid key use date sorting */ - [sortStr appendString:@"DATE"]; -#if 0 - return [NSDictionary dictionaryWithObjectsAndKeys: - NoNumber, @"result", nil]; -#endif + + [sortStr appendString:s]; } + return isFirst ? nil : sortStr; +} + +- (NSDictionary *)primarySort:(NSString *)_sort + qualifierString:(NSString *)_qualString + encoding:(NSString *)_encoding +{ + /* + http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-17.txt + + The result dict contains the following keys: + 'result' - a boolean + 'expunge' - array (of what?) + 'sort' - array of uids in sort order + 'RawResponse' - the raw IMAP4 response + + Eg: UID SORT ( DATE REVERSE SUBJECT ) UTF-8 TODO + */ + NSMutableString *sortStr; + + if (![_encoding isNotNull]) _encoding = @"UTF-8"; + if (![_qualString isNotNull]) _qualString = @" ALL"; + + sortStr = [NSMutableString stringWithCapacity:128]; + + [sortStr appendString:@"UID SORT ("]; + if (_sort != nil) [sortStr appendString:_sort]; [sortStr appendString:@") "]; - // TODO: make that the other way around! should be an ivar in the client - [sortStr appendString:[[self context] sortEncoding]]; - [sortStr appendString:[self _searchExprForQual:_qual]]; + + [sortStr appendString:_encoding]; /* eg 'UTF-8' */ + + /* Note: this is _space sensitive_! to many spaces lead to error! */ + [sortStr appendString:_qualString]; /* eg ' ALL' or ' TEXT "abc"' */ return [self->normer normalizeSortResponse:[self processCommand:sortStr]]; } +- (NSDictionary *)sort:(id)_sortSpec + qualifier:(EOQualifier *)_qual + encoding:(NSString *)_encoding +{ + /* + http://www.ietf.org/internet-drafts/draft-ietf-imapext-sort-17.txt + + The _sortSpec can be: + - a simple 'raw' IMAP4 sort string + - an EOSortOrdering + - an array of EOSortOrderings + + The result dict contains the following keys: + 'result' - a boolean + 'expunge' - array (of what?) + 'sort' - array of uids in sort order + 'RawResponse' - the raw IMAP4 response + + If no sortable key was found, the sort will run against 'DATE'. + => TODO: this is inconsistent. If none are passed in, false will be + returned + + Eg: UID SORT ( DATE REVERSE SUBJECT ) UTF-8 TODO + */ + NSString *tmp; + + if ([_sortSpec isKindOfClass:[NSArray class]]) + tmp = [self _generateIMAP4SortOrderings:_sortSpec]; + else if ([_sortSpec isKindOfClass:[EOSortOrdering class]]) + tmp = [self _generateIMAP4SortOrdering:_sortSpec]; + else + tmp = [_sortSpec stringValue]; + + if ([tmp length] == 0) { /* found no valid key use date sorting */ + [self logWithFormat:@"Note: no key found for sorting, using 'DATE': %@", + _sortSpec]; + tmp = @"DATE"; + } + + return [self primarySort:tmp + qualifierString:[self _searchExprForQual:_qual] + encoding:_encoding]; +} +- (NSDictionary *)sort:(NSArray *)_sortOrderings + qualifier:(EOQualifier *)_qual +{ + // DEPRECATED, should not use context! + return [self sort:_sortOrderings qualifier:_qual + encoding:[[self context] sortEncoding]]; +} + - (NSDictionary *)searchWithQualifier:(EOQualifier *)_qualifier { NSString *s; diff --git a/sope-mime/NGImap4/NGImap4Folder.m b/sope-mime/NGImap4/NGImap4Folder.m index b96b1ad3..75fd1741 100644 --- a/sope-mime/NGImap4/NGImap4Folder.m +++ b/sope-mime/NGImap4/NGImap4Folder.m @@ -18,7 +18,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// $Id$ +// $Id: NGImap4Folder.m 1 2004-08-20 10:08:27Z znek $ #include "NGImap4Folder.h" #include "NGImap4Context.h" @@ -716,10 +716,11 @@ static int FetchNewUnseenMessagesInSubFoldersOnDemand = -1; qual2 = UnseenQual; } - - if (qual1) { - dict = [[self->context client] sort:DateSo qualifier:qual1]; - + + if (qual1 != nil) { + dict = [[self->context client] sort:DateSo qualifier:qual1 + encoding:[self->context sortEncoding]]; + if (![[dict objectForKey:@"result"] boolValue]) { [self logWithFormat:@"ERROR[%s](1): sort failed (sortOrderings %@, " @"qual1 %@)", __PRETTY_FUNCTION__, DateSo, qual1]; @@ -727,9 +728,10 @@ static int FetchNewUnseenMessagesInSubFoldersOnDemand = -1; } [muids addObjectsFromArray:[dict objectForKey:@"sort"]]; } - if (qual2) { - dict = [[self->context client] sort:DateSo qualifier:qual2]; - + if (qual2 != nil) { + dict = [[self->context client] sort:DateSo qualifier:qual2 + encoding:[self->context sortEncoding]]; + if (![[dict objectForKey:@"result"] boolValue]) { [self logWithFormat:@"ERROR[%s](2): sort failed (sortOrderings %@, " @"qual2 %@ ", __PRETTY_FUNCTION__, DateSo, qual2]; @@ -764,8 +766,9 @@ static int FetchNewUnseenMessagesInSubFoldersOnDemand = -1; [self resetLastException]; - dict = [[self->context client] sort:_so qualifier:qual]; - + dict = [[self->context client] sort:_so qualifier:qual + encoding:[self->context sortEncoding]]; + if (![self _checkResult:dict cmd:__PRETTY_FUNCTION__]) return nil; diff --git a/sope-mime/Version b/sope-mime/Version index 627cb44f..5f3604ff 100644 --- a/sope-mime/Version +++ b/sope-mime/Version @@ -2,6 +2,6 @@ MAJOR_VERSION:=4 MINOR_VERSION:=3 -SUBMINOR_VERSION:=182 +SUBMINOR_VERSION:=183 # v4.2.149 requires libNGStreams v4.2.34 -- 2.39.5