feat(core): allow pre/appended Sieve scripts

Allow domain admins to now set Sieve scripts that can be prepended
and appended to all users' scripts. This can now be controller
using the SOGoSieveScriptHeaderTemplateFile and
SOGoSieveScriptFooterTemplateFile domain defaults.
pull/281/head
Ludovic Marcotte 2019-11-06 14:53:30 -05:00
parent c2e7f6a866
commit 4475ac651d
4 changed files with 96 additions and 5 deletions

View File

@ -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

View File

@ -48,6 +48,8 @@
- (BOOL) forceExternalLoginWithEmail;
- (BOOL) externalAvatarsEnabled;
- (BOOL) sieveScriptsEnabled;
- (NSString *) sieveScriptHeaderTemplateFile;
- (NSString *) sieveScriptFooterTemplateFile;
- (BOOL) forwardEnabled;
- (int) forwardConstraints;
- (NSArray *) forwardConstraintsDomains;

View File

@ -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"];

View File

@ -21,6 +21,7 @@
*/
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSCharacterSet.h>
#import <Foundation/NSURL.h>
#import <Foundation/NSValue.h>
@ -32,6 +33,7 @@
#import <SOGo/SOGoTextTemplateFile.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSString+Ext.h>
#import <NGImap4/NGImap4Connection.h>
#import <NGImap4/NGImap4Client.h>
#import <NGImap4/NGSieveClient.h>
@ -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];
}