From 98ed9c3b17f22c38a81e1140029cddf5fe2d88fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20J=2E=20Hern=C3=A1ndez=20Blasco?= Date: Fri, 11 Dec 2015 11:22:26 +0100 Subject: [PATCH] oc-mail: Manage multiple CN restriction By ignoring <, =< and = operators and simplifying the following request: MODSEQ >= x || MODSEQ >= y || MODSEQ >= z --> MODSEQ >= min(x, y, z) This hack will reduce the number of current retrieved UID keys from the IMAP server. Current status is to retrieve everything when the multiple CN restriction is sent as the required restriction is too complex and it is not defined by the IMAP spec. The proper implementation for: CN > x_1 & CN < x_2 | CN > y_1 & CN < y_2 | CN > z_1 It will be something like this: set(MODSEQ >= x_1 + 1) - set(MODSEQ >= x_2) U set(MODSEQ >= y_1 + 1) - set(MODSEQ >= y_2) U set(MODSEQ >= z_1) Assuming x_1 <= x_2 <= y_1 <= y_2 <= z_1. --- OpenChange/MAPIStoreMailFolder.m | 67 +++++++++++++++++++++++++- OpenChange/MAPIStoreMailMessageTable.m | 4 +- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/OpenChange/MAPIStoreMailFolder.m b/OpenChange/MAPIStoreMailFolder.m index 6934e7a60..02e25acbd 100644 --- a/OpenChange/MAPIStoreMailFolder.m +++ b/OpenChange/MAPIStoreMailFolder.m @@ -74,6 +74,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK; #include #include #include +#include #include #include @@ -257,6 +258,67 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK; return MAPISTORE_SUCCESS; } +- (EOQualifier *) simplifyQualifier: (EOQualifier *) qualifier +{ + /* Hack: Reduce the number of MODSEQ constraints to a single one as + we assume the difference among MODSEQs will be small enough to + return a small number of UIDs. + + This is the only case we do simplify: + MODSEQ >= x | MODSEQ >= y | MODSEQ >= z => MODSEQ >= min(x,y,z) + */ + if (qualifier && [qualifier isKindOfClass: [EOOrQualifier class]]) + { + EOQualifier *simplifiedQualifier; + NSArray *quals; + NSNumber *minModseq; + NSUInteger i, count; + + quals = [(EOOrQualifier *)qualifier qualifiers]; + count = [quals count]; + if (count < 2) + return qualifier; + + minModseq = [NSNumber numberWithUnsignedLongLong: ULLONG_MAX]; + + for (i = 0; i < count; i++) + { + EOQualifier *subQualifier; + + subQualifier = [quals objectAtIndex: i]; + if ([subQualifier isKindOfClass: [EOAndQualifier class]] + && [[(EOAndQualifier *)subQualifier qualifiers] count] == 1) + subQualifier = [[(EOAndQualifier *)subQualifier qualifiers] objectAtIndex: 0]; + + if ([subQualifier isKindOfClass: [EOKeyValueQualifier class]] + && [[(EOKeyValueQualifier *)subQualifier key] isEqualToString: @"MODSEQ"]) + { + NSNumber *value; + + value = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value]; + if ([minModseq compare: value] == NSOrderedDescending + && [value unsignedLongLongValue] > 0) + minModseq = (NSNumber *)[(EOKeyValueQualifier *)subQualifier value]; + + } + else + return qualifier; + } + + if ([minModseq unsignedLongLongValue] > 0 && [minModseq unsignedLongLongValue] < ULLONG_MAX) + { + simplifiedQualifier = [[EOKeyValueQualifier alloc] + initWithKey: @"MODSEQ" + operatorSelector: EOQualifierOperatorGreaterThanOrEqualTo + value: minModseq]; + [simplifiedQualifier autorelease]; + return simplifiedQualifier; + } + } + + return qualifier; +} + - (EOQualifier *) nonDeletedQualifier { static EOQualifier *nonDeletedQualifier = nil; @@ -281,7 +343,7 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK; andSortOrderings: (NSArray *) sortOrderings { NSArray *uidKeys; - EOQualifier *fetchQualifier; + EOQualifier *fetchQualifier, *simplifiedQualifier; if ([self ensureFolderExists]) { @@ -290,9 +352,10 @@ static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK; if (qualifier) { + simplifiedQualifier = [self simplifyQualifier: qualifier]; fetchQualifier = [[EOAndQualifier alloc] initWithQualifiers: - [self nonDeletedQualifier], qualifier, + [self nonDeletedQualifier], simplifiedQualifier, nil]; [fetchQualifier autorelease]; } diff --git a/OpenChange/MAPIStoreMailMessageTable.m b/OpenChange/MAPIStoreMailMessageTable.m index c71097d63..d315f6527 100644 --- a/OpenChange/MAPIStoreMailMessageTable.m +++ b/OpenChange/MAPIStoreMailMessageTable.m @@ -181,8 +181,8 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK; else { /* Ignore other operations as IMAP only support MODSEQ >= X */ - [self warnWithFormat: @"Ignoring %@ as only supported operators are > and >=", - [self operatorFromRestrictionOperator: res->relop]]; + [self warnWithFormat: @"Ignoring '%@' as only supported operators are > and >=", + NSStringFromSelector ([self operatorFromRestrictionOperator: res->relop])]; rc = MAPIRestrictionStateAlwaysTrue; } }