refactor(preferences): conditionally activate the Sieve script
All the user defaults are now editable through the Preferences module, even if an external Sieve script is enabled. However, the user can disable the external Sieve script and force the activation of the "sogo" Sieve script.pull/281/head
parent
350677bbce
commit
5b3d84ee24
|
@ -80,8 +80,10 @@ typedef enum {
|
|||
|
||||
- (id) getInboxQuota;
|
||||
- (BOOL) updateFilters;
|
||||
- (BOOL) updateFiltersAndForceActivation: (BOOL) forceActivation;
|
||||
- (BOOL) updateFiltersWithUsername: (NSString *) theUsername
|
||||
andPassword: (NSString *) thePassword;
|
||||
andPassword: (NSString *) thePassword
|
||||
forceActivation: (BOOL) forceActivation;
|
||||
|
||||
- (NSArray *) identities;
|
||||
- (NSString *) signature;
|
||||
|
|
|
@ -300,19 +300,32 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
return inboxQuota;
|
||||
}
|
||||
|
||||
- (BOOL) updateFiltersAndForceActivation: (BOOL) forceActivation
|
||||
{
|
||||
return [self updateFiltersWithUsername: nil
|
||||
andPassword: nil
|
||||
forceActivation: forceActivation];
|
||||
}
|
||||
|
||||
- (BOOL) updateFilters
|
||||
{
|
||||
return [self updateFiltersWithUsername: nil andPassword: nil];
|
||||
return [self updateFiltersWithUsername: nil
|
||||
andPassword: nil
|
||||
forceActivation: NO];
|
||||
}
|
||||
|
||||
- (BOOL) updateFiltersWithUsername: (NSString *) theUsername
|
||||
andPassword: (NSString *) thePassword
|
||||
forceActivation: (BOOL) forceActivation
|
||||
{
|
||||
SOGoSieveManager *manager;
|
||||
|
||||
manager = [SOGoSieveManager sieveManagerForUser: [context activeUser]];
|
||||
|
||||
return [manager updateFiltersForAccount: self withUsername: theUsername andPassword: thePassword];
|
||||
return [manager updateFiltersForAccount: self
|
||||
withUsername: theUsername
|
||||
andPassword: thePassword
|
||||
forceActivation: forceActivation];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -50,10 +50,13 @@
|
|||
withUsername: (NSString *) theUsername
|
||||
andPassword: (NSString *) thePassword;
|
||||
|
||||
- (BOOL) hasActiveExternalSieveScripts: (NGSieveClient *) client;
|
||||
|
||||
- (BOOL) updateFiltersForAccount: (SOGoMailAccount *) theAccount;
|
||||
- (BOOL) updateFiltersForAccount: (SOGoMailAccount *) theAccount
|
||||
withUsername: (NSString *) theUsername
|
||||
andPassword: (NSString *) thePassword;
|
||||
andPassword: (NSString *) thePassword
|
||||
forceActivation: (BOOL) forceActivation;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -804,6 +804,24 @@ static NSString *sieveScriptName = @"sogo";
|
|||
return [client autorelease];
|
||||
}
|
||||
|
||||
- (BOOL) hasActiveExternalSieveScripts: (NGSieveClient *) client
|
||||
{
|
||||
NSDictionary *scripts;
|
||||
NSEnumerator *keys;
|
||||
NSString *key;
|
||||
|
||||
scripts = [client listScripts];
|
||||
|
||||
keys = [scripts keyEnumerator];
|
||||
while ((key = [keys nextObject]))
|
||||
{
|
||||
if ([key caseInsensitiveCompare: @"sogo"] != NSOrderedSame &&
|
||||
[[[scripts objectForKey: key] stringValue] length] > 0)
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
|
@ -812,7 +830,8 @@ static NSString *sieveScriptName = @"sogo";
|
|||
{
|
||||
return [self updateFiltersForAccount: theAccount
|
||||
withUsername: nil
|
||||
andPassword: nil];
|
||||
andPassword: nil
|
||||
forceActivation: NO];
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -821,6 +840,7 @@ static NSString *sieveScriptName = @"sogo";
|
|||
- (BOOL) updateFiltersForAccount: (SOGoMailAccount *) theAccount
|
||||
withUsername: (NSString *) theUsername
|
||||
andPassword: (NSString *) thePassword
|
||||
forceActivation: (BOOL) forceActivation
|
||||
{
|
||||
NSString *filterScript, *v, *content;
|
||||
NSMutableArray *req;
|
||||
|
@ -830,7 +850,7 @@ static NSString *sieveScriptName = @"sogo";
|
|||
SOGoDomainDefaults *dd;
|
||||
NGSieveClient *client;
|
||||
NGImap4Client *imapClient;
|
||||
BOOL b, dateCapability;
|
||||
BOOL b, activate, dateCapability;
|
||||
unsigned int now;
|
||||
|
||||
dd = [user domainDefaults];
|
||||
|
@ -844,6 +864,9 @@ static NSString *sieveScriptName = @"sogo";
|
|||
if (!client)
|
||||
return NO;
|
||||
|
||||
// Activate script Sieve when forced or when no external script is enabled
|
||||
activate = forceActivation || ![self hasActiveExternalSieveScripts: client];
|
||||
|
||||
// We adjust the "methodRequirements" based on the server's
|
||||
// capabilities. Cyrus exposes "imapflags" while Dovecot (and
|
||||
// potentially others) expose "imap4flags" as specified in RFC5332
|
||||
|
@ -1094,6 +1117,7 @@ static NSString *sieveScriptName = @"sogo";
|
|||
intoArray: req];
|
||||
[script appendString: @"\n"];
|
||||
[script appendString: v];
|
||||
b = YES;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1102,21 +1126,23 @@ static NSString *sieveScriptName = @"sogo";
|
|||
header = [NSString stringWithFormat: @"require [\"%@\"];\r\n",
|
||||
[[req uniqueObjects] componentsJoinedByString: @"\",\""]];
|
||||
[script insertString: header atIndex: 0];
|
||||
b = YES;
|
||||
}
|
||||
|
||||
|
||||
/* We ensure to deactive the current active script since it could prevent
|
||||
its deletion from the server. */
|
||||
if (activate)
|
||||
result = [client setActiveScript: @""];
|
||||
// We delete the existing Sieve script
|
||||
result = [client deleteScript: sieveScriptName];
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue])
|
||||
[self logWithFormat: @"WARNING: Could not delete Sieve script - continuing...: %@", result];
|
||||
|
||||
/* We put and activate the script only if we actually have a script
|
||||
that does something... */
|
||||
if (b && [script length])
|
||||
{
|
||||
result = [client setActiveScript: @""];
|
||||
// We delete the existing Sieve script
|
||||
result = [client deleteScript: sieveScriptName];
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue])
|
||||
[self logWithFormat: @"WARNING: Could not delete Sieve script - continuing...: %@", result];
|
||||
|
||||
result = [client putScript: sieveScriptName script: script];
|
||||
|
||||
if (![[result valueForKey:@"result"] boolValue])
|
||||
|
@ -1126,12 +1152,15 @@ static NSString *sieveScriptName = @"sogo";
|
|||
return NO;
|
||||
}
|
||||
|
||||
result = [client setActiveScript: sieveScriptName];
|
||||
if (![[result valueForKey:@"result"] boolValue])
|
||||
if (activate)
|
||||
{
|
||||
[self logWithFormat: @"Could not enable Sieve script: %@", result];
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
result = [client setActiveScript: sieveScriptName];
|
||||
if (![[result valueForKey:@"result"] boolValue])
|
||||
{
|
||||
[self logWithFormat: @"Could not enable Sieve script: %@", result];
|
||||
[client closeConnection];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,18 +25,23 @@
|
|||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGImap4/NGSieveClient.h>
|
||||
|
||||
#import <SOPE/NGCards/iCalRecurrenceRule.h>
|
||||
|
||||
#import <SOGo/NSObject+Utilities.h>
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
#import <SOGo/SOGoDomainDefaults.h>
|
||||
#import <SOGo/SOGoSieveManager.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserDefaults.h>
|
||||
#import <SOGo/SOGoUserFolder.h>
|
||||
#import <SOGo/SOGoUserSettings.h>
|
||||
#import <SOGo/SOGoUserProfile.h>
|
||||
#import <SOGo/WOResourceManager+SOGo.h>
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
#import <Mailer/SOGoMailAccount.h>
|
||||
#import <Mailer/SOGoMailAccounts.h>
|
||||
#import <Mailer/SOGoMailLabel.h>
|
||||
|
||||
#import "UIxJSONPreferences.h"
|
||||
|
@ -71,6 +76,27 @@ static SoProduct *preferencesProduct = nil;
|
|||
return labelsDictionary;
|
||||
}
|
||||
|
||||
//
|
||||
// Used internally
|
||||
//
|
||||
- (BOOL) _hasActiveExternalSieveScripts
|
||||
{
|
||||
NGSieveClient *client;
|
||||
SOGoMailAccount *account;
|
||||
SOGoMailAccounts *folder;
|
||||
SOGoSieveManager *manager;
|
||||
|
||||
folder = [[[context activeUser] homeFolderInContext: context] mailAccountsFolder: @"Mail" inContext: context];
|
||||
account = [folder lookupName: @"0" inContext: context acquire: NO];
|
||||
manager = [SOGoSieveManager sieveManagerForUser: [context activeUser]];
|
||||
client = [manager clientForAccount: account];
|
||||
|
||||
if (client)
|
||||
return [manager hasActiveExternalSieveScripts: client];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (WOResponse *) jsonDefaultsAction
|
||||
{
|
||||
return [self responseWithStatus: 200
|
||||
|
@ -401,6 +427,9 @@ static SoProduct *preferencesProduct = nil;
|
|||
[values setObject: vacation forKey: @"Vacation"];
|
||||
}
|
||||
|
||||
// Detect if an external Sieve script is active
|
||||
[values setObject: [NSNumber numberWithBool: [self _hasActiveExternalSieveScripts]] forKey: @"hasActiveExternalSieveScripts"];
|
||||
|
||||
return [values jsonRepresentation];
|
||||
}
|
||||
|
||||
|
|
|
@ -728,25 +728,6 @@ static NSArray *reminderValues = nil;
|
|||
return [[user domainDefaults] sieveScriptsEnabled];
|
||||
}
|
||||
|
||||
- (NSString *) hasActiveExternalSieveScripts
|
||||
{
|
||||
NSDictionary *scripts;
|
||||
NSEnumerator *keys;
|
||||
NSString *key;
|
||||
|
||||
scripts = [[self _sieveClient] listScripts];
|
||||
|
||||
keys = [scripts keyEnumerator];
|
||||
while ((key = [keys nextObject]))
|
||||
{
|
||||
if ([key caseInsensitiveCompare: @"sogo"] != NSOrderedSame &&
|
||||
[[scripts objectForKey: key] boolValue])
|
||||
return @"true";
|
||||
}
|
||||
|
||||
return @"false";
|
||||
}
|
||||
|
||||
//
|
||||
// Used by wox template
|
||||
//
|
||||
|
@ -1645,12 +1626,13 @@ static NSArray *reminderValues = nil;
|
|||
// We check if the Sieve server is available *ONLY* if at least one of the option is enabled
|
||||
if (!([dd sieveScriptsEnabled] || [dd vacationEnabled] || [dd forwardEnabled]) || [self _isSieveServerAvailable])
|
||||
{
|
||||
BOOL forceActivation = ![[v objectForKey: @"hasActiveExternalSieveScripts"] boolValue];
|
||||
|
||||
folder = [[[context activeUser] homeFolderInContext: context] mailAccountsFolder: @"Mail"
|
||||
inContext: context];
|
||||
account = [folder lookupName: @"0" inContext: context acquire: NO];
|
||||
|
||||
if (![account updateFilters])
|
||||
if (![account updateFiltersAndForceActivation: forceActivation])
|
||||
{
|
||||
results = (id <WOActionResults>) [self responseWithStatus: 502
|
||||
andJSONRepresentation: [NSDictionary dictionaryWithObjectsAndKeys: @"Connection error", @"message", nil]];
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
var forwardConstraints = <var:string value="forwardConstraints" const:escapeHTML="NO"/>;
|
||||
var forwardConstraintsDomains = <var:string value="forwardConstraintsDomains" const:escapeHTML="NO"/>;
|
||||
var sieveCapabilities = <var:string value="sieveCapabilities" const:escapeHTML="NO"/>;
|
||||
var hasActiveExternalSieveScripts = <var:string value="hasActiveExternalSieveScripts" const:escapeHTML="NO"/>;
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="preferences.html">
|
||||
|
@ -839,7 +838,12 @@
|
|||
aria-controls="mailFiltersTab-content"
|
||||
label:label="Filters"
|
||||
sg-labels="MailerUI">
|
||||
<md-content role="tabpanel" aria-labelledby="mailFiltersView" ng-hide="app.hasActiveExternalSieveScripts">
|
||||
<md-content class="md-padding"
|
||||
ng-include="'hasActiveExternalSieveScripts.html'"
|
||||
ng-show="app.preferences.defaults.hasActiveExternalSieveScripts">
|
||||
<!-- external Sieve script detected -->
|
||||
</md-content>
|
||||
<md-content role="tabpanel" aria-labelledby="mailFiltersView">
|
||||
<div class="sg-list-sortable"
|
||||
ng-model="app.preferences.defaults.SOGoSieveFilters"
|
||||
as-sortable="{ scrollableContainer: '.sg-list-sortable', containment: '.sg-list-sortable', containerPositioning: 'relative', orderChanged: app.onFiltersOrderChanged(preferencesForm) }">
|
||||
|
@ -885,22 +889,6 @@
|
|||
</md-button>
|
||||
</div>
|
||||
</md-content>
|
||||
<md-content class="md-padding" ng-show="app.hasActiveExternalSieveScripts">
|
||||
<md-card flex="50" flex-xs="100">
|
||||
<md-card-title>
|
||||
<md-card-title-text>
|
||||
<span class="md-headline"><var:string label:value="An external Sieve script is active"/></span>
|
||||
<span class="md-subhead"><var:string label:value="Sieve is a programming language that can be used for email filtering. If you let SOGo handle your filters, vacation and forward settings, your active script will be disabled." /></span>
|
||||
</md-card-title-text>
|
||||
</md-card-title>
|
||||
<md-card-actions layout="row" layout-align="end center">
|
||||
<md-button type="button" class="md-raised md-warn"
|
||||
ng-click="app.hasActiveExternalSieveScripts = false">
|
||||
<var:string label:value="Let SOGo handle everything" />
|
||||
</md-button>
|
||||
</md-card-actions>
|
||||
</md-card>
|
||||
</md-content>
|
||||
</md-tab>
|
||||
</var:if>
|
||||
<!-- END OF MAIL > FILTERS -->
|
||||
|
@ -908,9 +896,13 @@
|
|||
<!-- MAIL > VACATION -->
|
||||
<var:if condition="isVacationEnabled">
|
||||
<md-tab id="mailVacationTab" aria-controls="mailVacationTab-content" label:label="Vacation">
|
||||
<md-content class="md-padding"
|
||||
ng-include="'hasActiveExternalSieveScripts.html'"
|
||||
ng-show="app.preferences.defaults.hasActiveExternalSieveScripts">
|
||||
<!-- external Sieve script detected -->
|
||||
</md-content>
|
||||
<div role="tabpanel" aria-labelledby="mailVacationView"
|
||||
id="mailVacationView-content" class="md-padding"
|
||||
ng-hide="app.hasActiveExternalSieveScripts">
|
||||
id="mailVacationView-content" class="md-padding">
|
||||
|
||||
<md-checkbox
|
||||
ng-model="app.preferences.defaults.Vacation.enabled"
|
||||
|
@ -1056,22 +1048,6 @@
|
|||
|
||||
</div>
|
||||
</div>
|
||||
<md-content class="md-padding" ng-show="app.hasActiveExternalSieveScripts">
|
||||
<md-card flex="50" flex-xs="100">
|
||||
<md-card-title>
|
||||
<md-card-title-text>
|
||||
<span class="md-headline"><var:string label:value="An external Sieve script is active"/></span>
|
||||
<span class="md-subhead"><var:string label:value="Sieve is a programming language that can be used for email filtering. If you let SOGo handle your filters, vacation and forward settings, your active script will be disabled." /></span>
|
||||
</md-card-title-text>
|
||||
</md-card-title>
|
||||
<md-card-actions layout="row" layout-align="end center">
|
||||
<md-button type="button" class="md-raised md-warn"
|
||||
ng-click="app.hasActiveExternalSieveScripts = false">
|
||||
<var:string label:value="Let SOGo handle everything" />
|
||||
</md-button>
|
||||
</md-card-actions>
|
||||
</md-card>
|
||||
</md-content>
|
||||
</md-tab>
|
||||
</var:if>
|
||||
<!-- END OF MAIL > VACATION -->
|
||||
|
@ -1079,9 +1055,13 @@
|
|||
<!-- MAIL > FORWARD -->
|
||||
<var:if condition="isForwardEnabled">
|
||||
<md-tab id="mailForwardTab" aria-controls="mailForwardTab-content" label:label="Forward">
|
||||
<md-content class="md-padding"
|
||||
ng-include="'hasActiveExternalSieveScripts.html'"
|
||||
ng-show="app.preferences.defaults.hasActiveExternalSieveScripts">
|
||||
<!-- external Sieve script detected -->
|
||||
</md-content>
|
||||
<div role="tabpanel" aria-labelledby="mailForwardView"
|
||||
id="mailForwardView-content" class="md-padding"
|
||||
ng-hide="app.hasActiveExternalSieveScripts">
|
||||
id="mailForwardView-content" class="md-padding">
|
||||
|
||||
<md-checkbox
|
||||
ng-model="app.preferences.defaults.Forward.enabled"
|
||||
|
@ -1109,22 +1089,6 @@
|
|||
|
||||
</div>
|
||||
</div>
|
||||
<md-content class="md-padding" ng-show="app.hasActiveExternalSieveScripts">
|
||||
<md-card flex="50" flex-xs="100">
|
||||
<md-card-title>
|
||||
<md-card-title-text>
|
||||
<span class="md-headline"><var:string label:value="An external Sieve script is active"/></span>
|
||||
<span class="md-subhead"><var:string label:value="Sieve is a programming language that can be used for email filtering. If you let SOGo handle your filters, vacation and forward settings, your active script will be disabled." /></span>
|
||||
</md-card-title-text>
|
||||
</md-card-title>
|
||||
<md-card-actions layout="row" layout-align="end center">
|
||||
<md-button type="button" class="md-raised md-warn"
|
||||
ng-click="app.hasActiveExternalSieveScripts = false">
|
||||
<var:string label:value="Let SOGo handle everything" />
|
||||
</md-button>
|
||||
</md-card-actions>
|
||||
</md-card>
|
||||
</md-content>
|
||||
</md-tab>
|
||||
</var:if>
|
||||
<!-- END OF MAIL > FORWARD -->
|
||||
|
@ -1132,5 +1096,22 @@
|
|||
</md-tabs>
|
||||
</var:if>
|
||||
</script>
|
||||
<script type="text/ng-template" id="hasActiveExternalSieveScripts.html">
|
||||
<md-card>
|
||||
<md-card-title>
|
||||
<md-card-title-text>
|
||||
<span class="md-headline"><var:string label:value="An external Sieve script is active"/></span>
|
||||
<span class="md-subhead"><var:string label:value="Sieve is a programming language that can be used for email filtering. If you let SOGo handle your filters, vacation and forward settings, your active script will be disabled." /></span>
|
||||
</md-card-title-text>
|
||||
</md-card-title>
|
||||
<md-card-actions layout="row" layout-align="end center">
|
||||
<md-button type="button" class="md-raised md-warn"
|
||||
ng-click="app.manageSieveScript(preferencesForm)">
|
||||
<var:string label:value="Let SOGo handle everything" />
|
||||
</md-button>
|
||||
</md-card-actions>
|
||||
</md-card>
|
||||
</script>
|
||||
|
||||
|
||||
</var:component>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
this.timeZonesSearchText = '';
|
||||
this.sieveVariablesCapability = ($window.sieveCapabilities.indexOf('variables') >= 0);
|
||||
this.mailLabelKeyRE = new RegExp(/^(?!^_\$)[^(){} %*\"\\\\]*?$/);
|
||||
this.hasActiveExternalSieveScripts = $window.hasActiveExternalSieveScripts;
|
||||
|
||||
// Set alternate avatar in User service
|
||||
if (Preferences.defaults.SOGoAlternateAvatar)
|
||||
|
@ -285,6 +284,11 @@
|
|||
});
|
||||
};
|
||||
|
||||
this.manageSieveScript = function(form) {
|
||||
this.preferences.defaults.hasActiveExternalSieveScripts = false;
|
||||
form.$setDirty();
|
||||
};
|
||||
|
||||
this.confirmChanges = function($event, form) {
|
||||
var target;
|
||||
|
||||
|
|
Loading…
Reference in New Issue