diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index a09ab36b2..6c7914344 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -2138,6 +2138,16 @@ host. Defaults to `NO` when unset. +|D |SOGoSieveScriptHeaderTemplateFile +|Parameter used to set the full path of the Sieve script that will be +automatically prepended to any Sieve scripts a user might define. The file +must be encoded in UTF-8 and it must also respect the RFC5228 syntax. + +|D |SOGoSieveScriptFooterTemplateFile +|Parameter used to set the full path of the Sieve script that will be +automatically appended to any Sieve scripts a user might define. The file +must be encoded in UTF-8 and it must also respect the RFC5228 syntax. + |U |SOGoSieveFilters |Parameter used to define initial Sieve scripts for users. The user can still modify the scripts and the initial values will be written diff --git a/SoObjects/SOGo/SOGoDomainDefaults.h b/SoObjects/SOGo/SOGoDomainDefaults.h index a56c71c5c..fafa07918 100644 --- a/SoObjects/SOGo/SOGoDomainDefaults.h +++ b/SoObjects/SOGo/SOGoDomainDefaults.h @@ -48,6 +48,8 @@ - (BOOL) forceExternalLoginWithEmail; - (BOOL) externalAvatarsEnabled; - (BOOL) sieveScriptsEnabled; +- (NSString *) sieveScriptHeaderTemplateFile; +- (NSString *) sieveScriptFooterTemplateFile; - (BOOL) forwardEnabled; - (int) forwardConstraints; - (NSArray *) forwardConstraintsDomains; diff --git a/SoObjects/SOGo/SOGoDomainDefaults.m b/SoObjects/SOGo/SOGoDomainDefaults.m index df710083e..a8a6c93e0 100644 --- a/SoObjects/SOGo/SOGoDomainDefaults.m +++ b/SoObjects/SOGo/SOGoDomainDefaults.m @@ -196,6 +196,16 @@ return [self boolForKey: @"SOGoSieveScriptsEnabled"]; } +- (NSString *) sieveScriptHeaderTemplateFile +{ + return [self stringForKey: @"SOGoSieveScriptHeaderTemplateFile"]; +} + +- (NSString *) sieveScriptFooterTemplateFile +{ + return [self stringForKey: @"SOGoSieveScriptFooterTemplateFile"]; +} + - (BOOL) forwardEnabled { return [self boolForKey: @"SOGoForwardEnabled"]; diff --git a/SoObjects/SOGo/SOGoSieveManager.m b/SoObjects/SOGo/SOGoSieveManager.m index ee8d81a0b..8f140944c 100644 --- a/SoObjects/SOGo/SOGoSieveManager.m +++ b/SoObjects/SOGo/SOGoSieveManager.m @@ -21,6 +21,7 @@ */ #import +#import #import #import @@ -32,6 +33,7 @@ #import #import +#import #import #import #import @@ -253,6 +255,46 @@ static NSString *sieveScriptName = @"sogo"; return YES; } +- (NSString *) _extractRequirementsFromContent: (NSString *) theContent + intoArray: (NSMutableArray *) theRequirements +{ + NSString *line, *v; + NSArray *lines; + id o; + + int i, count; + + lines = [theContent componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]]; + count = [lines count]; + + for (i = 0; i < count; i++) + { + line = [[lines objectAtIndex: i] stringByTrimmingSpaces]; + if ([line hasPrefix: @"require "]) + { + line = [line substringFromIndex: 8]; + // Handle lines like: require "imapflags"; + if ([line characterAtIndex: 0] == '"') + { + v = [line substringToIndex: [line length]-2]; + [theRequirements addObject: v]; + NSLog(@"require: |%@|", v); + } + // Else handle lines like: require ["imapflags","vacation"]; + else if ([line characterAtIndex: 0] == '[') + { + o = [[line substringToIndex: [line length]-1] objectFromJSONString]; + [theRequirements addObjectsFromArray: o]; + NSLog(@"requires: |%@|", o); + } + } + else + break; + } + + return [[lines subarrayWithRange: NSMakeRange(i, count-i)] componentsJoinedByString: @"\n"]; +} + - (BOOL) _extractRuleField: (NSString **) field fromRule: (NSDictionary *) rule andType: (UIxFilterFieldType *) type @@ -592,7 +634,7 @@ static NSString *sieveScriptName = @"sogo"; sieveScript = [NSMutableString string]; - ASSIGN (requirements, newRequirements); + ASSIGN(requirements, newRequirements); [scriptError release]; scriptError = nil; @@ -613,8 +655,7 @@ static NSString *sieveScriptName = @"sogo"; } [scriptError retain]; - [requirements release]; - requirements = nil; + DESTROY(requirements); if (scriptError) sieveScript = nil; @@ -783,6 +824,7 @@ static NSString *sieveScriptName = @"sogo"; withUsername: (NSString *) theUsername andPassword: (NSString *) thePassword { + NSString *filterScript, *v, *content; NSMutableArray *req; NSMutableString *script, *header; NSDictionary *result, *values; @@ -790,7 +832,6 @@ static NSString *sieveScriptName = @"sogo"; SOGoDomainDefaults *dd; NGSieveClient *client; NGImap4Client *imapClient; - NSString *filterScript, *v; BOOL b, dateCapability; unsigned int now; @@ -1029,10 +1070,38 @@ static NSString *sieveScriptName = @"sogo"; [script appendString: @"keep;\r\n"]; } + // We handle header/footer Sieve scripts + if ((v = [dd sieveScriptHeaderTemplateFile])) + { + content = [NSString stringWithContentsOfFile: v + encoding: NSUTF8StringEncoding + error: NULL]; + if (content) + { + v = [self _extractRequirementsFromContent: content + intoArray: req]; + [script insertString: v atIndex: 0]; + } + } + + if ((v = [dd sieveScriptFooterTemplateFile])) + { + content = [NSString stringWithContentsOfFile: v + encoding: NSUTF8StringEncoding + error: NULL]; + if (content) + { + v = [self _extractRequirementsFromContent: content + intoArray: req]; + [script appendString: @"\n"]; + [script appendString: v]; + } + } + if ([req count]) { header = [NSString stringWithFormat: @"require [\"%@\"];\r\n", - [req componentsJoinedByString: @"\",\""]]; + [[req uniqueObjects] componentsJoinedByString: @"\",\""]]; [script insertString: header atIndex: 0]; }