+2005-02-12 Helge Hess <helge.hess@opengroupware.org>
+
+ * NGImap4: improved copying, cleaned up sort ordering (v4.5.212)
+
2005-02-08 Helge Hess <helge.hess@opengroupware.org>
* NGImap4: added method to retrieve selected folder (v4.5.211)
+2005-02-12 Helge Hess <helge.hess@opengroupware.org>
+
+ * EOQualifier+IMAPAdditions.m: allow contains: qualifier operator for
+ key searches
+
+ * NGImap4Client.m: moved EOSortOrdering => IMAP4 code to an own
+ category/file
+
+ * NGImap4Client.m: added -copyUids:toFolder: method to perform set copy
+ operations without sequence numbers (uses UID COPY IMAP4 command)
+
2005-02-08 Helge Hess <helge.hess@opengroupware.org>
* NGImap4Client.m: added -selectedFolderName method to retrieve the
if (disjunction)
[search appendString:@" or"];
- while ((qualifier = [quals nextObject])) {
+ while ((qualifier = [quals nextObject]) != nil) {
NSException *error;
if (debugOn)
[search appendString:[lvalue stringValue]];
}
else if ([OtherKeyWords containsObject:lkey]) {
- if (!sel_eq(lselector, EOQualifierOperatorEqual)) {
- [self logWithFormat:@"SELECTOR: got: %@, allowed: %@",
+ // TODO: actually most keywords only allow for contains! Eg "subject abc"
+ // is a contains query, not an equal query!
+ if (!sel_eq(lselector, EOQualifierOperatorEqual) &&
+ !sel_eq(lselector, EOQualifierOperatorContains)) {
+ [self logWithFormat:@"IMAP4 generation: got: %@, allowed: %@",
NSStringFromSelector(lselector),
NSStringFromSelector(EOQualifierOperatorEqual)];
return [self invalidImap4SearchQualifier:
--- /dev/null
+/*
+ Copyright (C) 2000-2005 SKYRIX Software AG
+
+ This file is part of SOPE.
+
+ SOPE is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with SOPE; see the file COPYING. If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include "imCommon.h"
+
+@interface NSObject(IMAPAdditions)
+- (NSString *)imap4SortString;
+@end
+
+@implementation NSString(IMAPAdditions)
+
+- (NSString *)imap4SortString {
+ /* support preformatted sort strings */
+ return self;
+}
+
+@end /* NSString(IMAPAdditions) */
+
+@implementation EOSortOrdering(IMAPAdditions)
+
+static NSArray *AllowedSortKeys = nil;
+
+- (void)_setupAllowedIMAP4SortKeys {
+ if (AllowedSortKeys != nil)
+ return;
+
+ AllowedSortKeys = [[NSArray alloc] initWithObjects:
+ @"ARRIVAL", @"CC", @"DATE", @"FROM",
+ @"SIZE", @"SUBJECT", @"TO", nil];
+}
+
+- (NSString *)imap4SortString {
+ SEL sel;
+ NSString *lkey;
+
+ lkey = [self key];
+ if ([lkey length] == 0)
+ return nil;
+
+ /* check whether key is a valid sort string */
+
+ if (AllowedSortKeys == nil) [self _setupAllowedIMAP4SortKeys];
+ if (![AllowedSortKeys containsObject:[lkey uppercaseString]]) {
+ NSLog(@"ERROR[%s] key %@ is not allowed here!",
+ __PRETTY_FUNCTION__, lkey);
+ return nil;
+ }
+
+ /* check selector */
+
+ sel = [self selector];
+ if (sel_eq(sel, EOCompareDescending) ||
+ sel_eq(sel, EOCompareCaseInsensitiveDescending)) {
+ return [@"REVERSE " stringByAppendingString:lkey];
+ }
+ // TODO: check other selectors whether they make sense instead of silent acc.
+
+ return lkey;
+}
+
+@end /* EOSortOrdering(IMAPAdditions) */
+
+@implementation NSArray(IMAPAdditions)
+
+- (NSString *)imap4SortStringForSortOrderings {
+ /*
+ 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;
+ unsigned i, count;
+
+ if ((count = [self count]) == 0)
+ return nil;
+
+ sortStr = [NSMutableString stringWithCapacity:(count * 24)];
+
+ for (i = 0; i < count; i++) {
+ EOSortOrdering *so;
+ NSString *s;
+
+ so = [self objectAtIndex:i];
+ if (![so isNotNull])
+ continue;
+ if ((s = [so imap4SortString]) == nil)
+ continue;
+
+ if (i > 0) [sortStr appendString:@" "];
+ [sortStr appendString:s];
+ }
+ return [sortStr length] > 0 ? sortStr : nil;
+}
+
+@end /* NSArray(IMAPAdditions) */
NSString+Imap4.m \
NGSieveClient.m \
EOQualifier+IMAPAdditions.m \
+ EOSortOrdering+IMAPAdditions.m \
\
NGImap4MessageGlobalID.m \
NGImap4FolderGlobalID.m \
flags:(NSArray *)_flags;
- (NSDictionary *)storeFrom:(unsigned)_from to:(unsigned)_to
add:(NSNumber *)_add flags:(NSArray *)_flags;
-- (NSDictionary *)copyUid:(unsigned)_uid toFolder:(NSString *)_folder;
+
+- (NSDictionary *)copyUid:(unsigned)_uid toFolder:(NSString *)_folder;
+- (NSDictionary *)copyUids:(NSArray *)_uids toFolder:(NSString *)_folder;
- (NSDictionary *)copyFrom:(unsigned)_from to:(unsigned)_to
toFolder:(NSString *)_folder;
+
- (NSDictionary *)append:(NSData *)_message toFolder:(NSString *)_folder
withFlags:(NSArray *)_flags;
- (NSDictionary *)threadBySubject:(BOOL)_bySubject
- (NSString *)imap4SearchString;
@end
+@interface EOSortOrdering(IMAPAdditions)
+- (NSString *)imap4SortString;
+@end
+
+@interface NSArray(IMAPAdditions)
+- (NSString *)imap4SortStringForSortOrderings;
+@end
+
@interface NGImap4Client(ConnectionRegistration)
- (void)removeFromConnectionRegister;
static int ProfileImapEnabled = -1;
static int LogImapEnabled = -1;
static int PreventExceptions = -1;
-static NSArray *AllowedSortKeys = nil;
static BOOL fetchDebug = NO;
static BOOL ImapDebugEnabled = NO;
}
if (ImapClients == NULL)
ImapClients = calloc(MaxImapClients + 2, sizeof(id));
-
- AllowedSortKeys = [[NSArray alloc] initWithObjects:
- @"ARRIVAL", @"CC", @"DATE", @"FROM",
- @"SIZE", @"SUBJECT", @"TO", nil];
}
/* constructors */
return [self->normer normalizeResponse:[self processCommand:cmd]];
}
+- (NSDictionary *)copyUids:(NSArray *)_uids toFolder:(NSString *)_folder {
+ NSString *cmd;
+
+ if ((_folder = [self _folder2ImapFolder:_folder]) == nil)
+ return nil;
+
+ cmd = [NSString stringWithFormat:@"uid copy %@ \"%@\"",
+ [_uids componentsJoinedByString:@","], _folder];
+
+ return [self->normer normalizeResponse:[self processCommand:cmd]];
+}
- (NSDictionary *)getQuotaRoot:(NSString *)_folder {
NSString *cmd;
}
- (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;
+ // TODO: still called by anything?
+ return [_sortOrdering imap4SortString];
}
-
- (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 *soe;
- EOSortOrdering *so;
- BOOL isFirst = YES;
-
- if ([_sortOrderings count] == 0)
- return nil;
-
- sortStr = [NSMutableString stringWithCapacity:128];
- soe = [_sortOrderings objectEnumerator];
- while ((so = [soe nextObject])) {
- NSString *s;
-
- s = [self _generateIMAP4SortOrdering:so];
- if (s == nil)
- continue;
-
- if (isFirst)
- isFirst = NO;
- else
- [sortStr appendString:@" "];
-
- [sortStr appendString:s];
- }
- return isFirst ? nil : sortStr;
+ return [_sortOrderings imap4SortStringForSortOrderings];
}
- (NSDictionary *)primarySort:(NSString *)_sort
MAJOR_VERSION:=4
MINOR_VERSION:=5
-SUBMINOR_VERSION:=211
+SUBMINOR_VERSION:=212
# v4.2.149 requires libNGStreams v4.2.34