From 5b3d84ee2441c717f1cb7ce8f40a1196f3bad0cb Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Fri, 15 Nov 2019 14:37:35 -0500 Subject: [PATCH] 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. --- SoObjects/Mailer/SOGoMailAccount.h | 4 +- SoObjects/Mailer/SOGoMailAccount.m | 17 +++- SoObjects/SOGo/SOGoSieveManager.h | 5 +- SoObjects/SOGo/SOGoSieveManager.m | 59 ++++++++---- UI/PreferencesUI/UIxJSONPreferences.m | 29 ++++++ UI/PreferencesUI/UIxPreferences.m | 22 +---- UI/Templates/PreferencesUI/UIxPreferences.wox | 89 ++++++++----------- .../js/Preferences/PreferencesController.js | 6 +- 8 files changed, 137 insertions(+), 94 deletions(-) diff --git a/SoObjects/Mailer/SOGoMailAccount.h b/SoObjects/Mailer/SOGoMailAccount.h index 2b6c871a3..66da6f06d 100644 --- a/SoObjects/Mailer/SOGoMailAccount.h +++ b/SoObjects/Mailer/SOGoMailAccount.h @@ -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; diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index f1980e37c..e58539a13 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -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]; } diff --git a/SoObjects/SOGo/SOGoSieveManager.h b/SoObjects/SOGo/SOGoSieveManager.h index 05b9a8fe7..0a179dc65 100644 --- a/SoObjects/SOGo/SOGoSieveManager.h +++ b/SoObjects/SOGo/SOGoSieveManager.h @@ -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 diff --git a/SoObjects/SOGo/SOGoSieveManager.m b/SoObjects/SOGo/SOGoSieveManager.m index a002f8d70..bbc6366af 100644 --- a/SoObjects/SOGo/SOGoSieveManager.m +++ b/SoObjects/SOGo/SOGoSieveManager.m @@ -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; + } } } diff --git a/UI/PreferencesUI/UIxJSONPreferences.m b/UI/PreferencesUI/UIxJSONPreferences.m index 337c2106e..cc157e594 100644 --- a/UI/PreferencesUI/UIxJSONPreferences.m +++ b/UI/PreferencesUI/UIxJSONPreferences.m @@ -25,18 +25,23 @@ #import #import +#import #import #import #import #import +#import #import #import +#import #import #import #import #import +#import +#import #import #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]; } diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m index b2e4f38b2..615e9f734 100644 --- a/UI/PreferencesUI/UIxPreferences.m +++ b/UI/PreferencesUI/UIxPreferences.m @@ -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 ) [self responseWithStatus: 502 andJSONRepresentation: [NSDictionary dictionaryWithObjectsAndKeys: @"Connection error", @"message", nil]]; diff --git a/UI/Templates/PreferencesUI/UIxPreferences.wox b/UI/Templates/PreferencesUI/UIxPreferences.wox index 127a007b9..0ffe6a875 100644 --- a/UI/Templates/PreferencesUI/UIxPreferences.wox +++ b/UI/Templates/PreferencesUI/UIxPreferences.wox @@ -23,7 +23,6 @@ var forwardConstraints = ; var forwardConstraintsDomains = ; var sieveCapabilities = ; - var hasActiveExternalSieveScripts = ; + + diff --git a/UI/WebServerResources/js/Preferences/PreferencesController.js b/UI/WebServerResources/js/Preferences/PreferencesController.js index c964c2616..d23aedc28 100644 --- a/UI/WebServerResources/js/Preferences/PreferencesController.js +++ b/UI/WebServerResources/js/Preferences/PreferencesController.js @@ -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;