From 7773d7f973f0c0de957dcbfcd7ae5f7e943379b7 Mon Sep 17 00:00:00 2001 From: Patrick Simpson Date: Mon, 27 Feb 2017 12:36:04 +0100 Subject: [PATCH 1/5] [KOE-51] Added tracking of changed names. To this end, the flag "TrackShareName" (=2) has been added. If this is set, and the name does not match the original folder's name, the name will be updated. The flag is set automatically when shares are applied and the share name matches the original name. Note that this flag does not cause the apply button to become enabled, to prevent having changes on existing shares. --- .../SharedFolders/SharedFoldersDialog.cs | 17 +++++++++++ .../Features/SharedFolders/StoreTreeNode.cs | 12 ++++---- .../API/SharedFolders/AvailableFolder.cs | 14 +++++++++ .../ZPush/API/SharedFolders/SharedFolder.cs | 29 +++++++++++++++++-- .../ZPush/API/SharedFolders/Types.cs | 15 ++++++++++ .../ZPush/Connect/Soap/SoapSerializer.cs | 18 +++++++++++- .../ZPush/Connect/ZPushConnection.cs | 11 ++++--- 7 files changed, 103 insertions(+), 13 deletions(-) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs index 193ded5..79c941b 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/SharedFoldersDialog.cs @@ -301,6 +301,17 @@ namespace Acacia.Features.SharedFolders textName.Text = value ?? ""; } } + private bool? OptionTrackName + { + get { return textName.Visible ? !_labelName.Enabled : (bool?)null; } + set + { + if (value != null) + { + _labelName.Enabled = !value.Value; + } + } + } private FolderTreeNode _optionNameNode; private CheckState? OptionSendAs @@ -367,6 +378,7 @@ namespace Acacia.Features.SharedFolders _optionSendAsInitial.Clear(); _optionPermissionNodes.Clear(); OptionName = null; + OptionTrackName = null; OptionSendAs = null; OptionPermissions = null; @@ -406,6 +418,7 @@ namespace Acacia.Features.SharedFolders if (_optionNameNode != null && nodes.Length == 1) { OptionName = _optionNameNode.SharedFolder.Name; + OptionTrackName = _optionNameNode.SharedFolder.FlagUpdateShareName; } else { @@ -461,6 +474,10 @@ namespace Acacia.Features.SharedFolders if (_optionNameNode != null) { _optionNameNode.SharedFolder = _optionNameNode.SharedFolder.WithName(textName.Text); + + // If the share name matches the folder name, track update + bool track = _optionNameNode.SharedFolder.Name == _optionNameNode.AvailableFolder.DefaultName; + _optionNameNode.SharedFolder = _optionNameNode.SharedFolder.WithFlagUpdateShareName(track); } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs index e478ab0..088e5e0 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SharedFolders/StoreTreeNode.cs @@ -85,7 +85,7 @@ namespace Acacia.Features.SharedFolders internal SharedFolder AddShare(AvailableFolder folder, SharedFolder state) { state = state ?? CreateDefaultShare(folder); - _currentShares[folder.BackendId] = state; + _currentShares[folder.BackendId] = state.PatchInformation(folder); CheckDirty(); return state; } @@ -98,10 +98,6 @@ namespace Acacia.Features.SharedFolders if (folder.IsMailFolder) share = share.WithFlagSendAsOwner(true); - // Default include the store name in root folders - if (folder.ParentId.IsNone) - share = share.WithName(folder.Name + " - " + folder.Store.UserName); - return share; } @@ -118,6 +114,12 @@ namespace Acacia.Features.SharedFolders SharedFolder state; if (_initialShares.TryGetValue(folder.BackendId, out state)) { + // If the folder has been renamed, update if we're tracing it. + if (state.Name != folder.DefaultName) + { + if (state.FlagUpdateShareName) + state = state.WithName(folder.DefaultName); + } return state; } return null; diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/AvailableFolder.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/AvailableFolder.cs index aec344b..c3411a6 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/AvailableFolder.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/AvailableFolder.cs @@ -73,9 +73,23 @@ namespace Acacia.ZPush.API.SharedFolders public SyncId ServerId { get { return _data.ServerId; } } public SyncId ParentId { get { return _data.ParentId; } } + public BackendId ParentIdAsBackend { get { return Parent?.BackendId ?? BackendId.NONE; } } public BackendId BackendId { get { return _data.BackendId; } } public string Name { get { return _data.DisplayName; } } + + public string DefaultName + { + get + { + // Default include the store name in root folders + if (ParentId.IsNone) + return Name + " - " + Store.UserName; + else + return Name; + } + } + public OutlookConstants.SyncType Type { get { return _data.Type; } } public GABUser Store { get; private set; } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/SharedFolder.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/SharedFolder.cs index b4e2235..3b15cc3 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/SharedFolder.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/SharedFolder.cs @@ -55,13 +55,16 @@ namespace Acacia.ZPush.API.SharedFolders return false; SoapData rhs = (SoapData)o; + // TODO: this isn't really a full equality test, as flags is masked. This is because Equals is only used + // to test if there are changes that need to be applied. It would be nicer to rename this, and + // equals in SharedFolder to something like NeedsApply. return store == rhs.store && folderid == rhs.folderid && parentid == rhs.parentid && name == rhs.name && type == rhs.type && - flags == rhs.flags; + (flags & ShareFlags.Mask_Apply) == (rhs.flags & ShareFlags.Mask_Apply); } public override int GetHashCode() @@ -86,6 +89,17 @@ namespace Acacia.ZPush.API.SharedFolders return _data; } + /// + /// Patches in any information that is available on AvailableFolder, but not SharedFolder. This is specifically the parent id. + /// + public SharedFolder PatchInformation(AvailableFolder folder) + { + if (folder.ParentIdAsBackend != _data.parentid) + { + _data.parentid = folder.ParentIdAsBackend; + } + return this; + } #endregion @@ -100,8 +114,8 @@ namespace Acacia.ZPush.API.SharedFolders { store = folder.Store.UserName, folderid = folder.BackendId, - parentid = folder.Parent?.BackendId ?? BackendId.NONE, - name = folder.Name, + parentid = folder.ParentIdAsBackend, + name = folder.DefaultName, type = OutlookConstants.USER_SYNC_TYPES[(int)folder.Type], flags = folder.IsMailFolder ? ShareFlags.SendAsOwner : ShareFlags.None }; @@ -161,6 +175,7 @@ namespace Acacia.ZPush.API.SharedFolders } public bool FlagSendAsOwner { get { return Flags.HasFlag(ShareFlags.SendAsOwner); } } + public bool FlagUpdateShareName { get { return Flags.HasFlag(ShareFlags.TrackShareName); } } /// /// Returns a copy with the specified 'send as owner' flag. @@ -170,6 +185,14 @@ namespace Acacia.ZPush.API.SharedFolders return WithFlags(value ? (_data.flags | ShareFlags.SendAsOwner) : (_data.flags & ~ShareFlags.SendAsOwner)); } + /// + /// Returns a copy with the specified 'update share name' flag. + /// + public SharedFolder WithFlagUpdateShareName(bool value) + { + return WithFlags(value ? (_data.flags | ShareFlags.TrackShareName) : (_data.flags & ~ShareFlags.TrackShareName)); + } + #endregion #region Standard overrides diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/Types.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/Types.cs index e602ce3..b1b7ee0 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/Types.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/API/SharedFolders/Types.cs @@ -29,7 +29,22 @@ namespace Acacia.ZPush.API.SharedFolders public enum ShareFlags { None = 0, + + /// + /// Mails from folders containing this flag will be sent as the owner of the share, not the user. + /// SendAsOwner = 1, + + /// + /// Folders with this flag will be renamed when the original folder is renamed. + /// + TrackShareName = 2, + + /// + /// The mask indicating which flag changes cause an Apply to become needed. I.e. flags not in the mask + /// are updated only if other changes are made. + /// + Mask_Apply = 1 } /// diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/Soap/SoapSerializer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/Soap/SoapSerializer.cs index eff1718..e02f120 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/Soap/SoapSerializer.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/Soap/SoapSerializer.cs @@ -169,7 +169,21 @@ namespace Acacia.ZPush.Connect.Soap } private class TypeHandlerInt : TypeHandler { - public TypeHandlerInt() : base(SoapConstants.XMLNS_XSD, "int", typeof(long)) { } + public TypeHandlerInt() : base(SoapConstants.XMLNS_XSD, null, typeof(int)) { } + + public override void Serialize(string name, object value, StringBuilder s) + { + s.Append(string.Format("<{0} xsi:type=\"xsd:int\">{1}", name, value)); + } + + protected override object DeserializeContents(XmlNode node, Type expectedType) + { + return long.Parse(node.InnerText); + } + } + private class TypeHandlerLong : TypeHandler + { + public TypeHandlerLong() : base(SoapConstants.XMLNS_XSD, "int", typeof(long)) { } public override void Serialize(string name, object value, StringBuilder s) { @@ -439,6 +453,8 @@ namespace Acacia.ZPush.Connect.Soap static SoapSerializer() { RegisterTypeHandler(new TypeHandlerBoolean()); + // What is called an int in soap might actually be a long here. + RegisterTypeHandler(new TypeHandlerLong()); RegisterTypeHandler(new TypeHandlerInt()); RegisterTypeHandler(new TypeHandlerString()); RegisterTypeHandler(new TypeHandlerList()); diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/ZPushConnection.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/ZPushConnection.cs index 28ef6f2..e18a406 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/ZPushConnection.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/Connect/ZPushConnection.cs @@ -130,11 +130,14 @@ namespace Acacia.ZPush.Connect { // Content using (HttpContent content = request.GetContent()) - using (HttpResponseMessage response = _client.PostAsync(url, content, _cancel ?? CancellationToken.None).Result) - using (HttpContent responseContent = response.Content) { - Logger.Instance.Debug(this, "Response: {0}", responseContent.ReadAsStringAsync().Result); - return request.ParseResponse(responseContent.ReadAsStreamAsync().Result); + Logger.Instance.Trace(this, "Request: {0}", content.ReadAsStringAsync().Result); + using (HttpResponseMessage response = _client.PostAsync(url, content, _cancel ?? CancellationToken.None).Result) + using (HttpContent responseContent = response.Content) + { + Logger.Instance.Trace(this, "Response: {0}", responseContent.ReadAsStringAsync().Result); + return request.ParseResponse(responseContent.ReadAsStreamAsync().Result); + } } } } From 12e8f6526548055a42cc8ec3d71e36308e4b243d Mon Sep 17 00:00:00 2001 From: Patrick Simpson Date: Mon, 27 Feb 2017 12:36:17 +0100 Subject: [PATCH 2/5] Fix for undisposed wrapper. --- .../AcaciaZPushPlugin/UI/GABLookupControl.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/GABLookupControl.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/GABLookupControl.cs index 31cf925..e25783e 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/GABLookupControl.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/GABLookupControl.cs @@ -247,15 +247,17 @@ namespace Acacia.UI if (_gab?.Contacts != null) { // Begin GAB lookup, search on full name or username - ISearch search = _gab.Contacts.Search(); - search.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Equal, username); - - // Fetch the result, if any. - // TODO: make a SearchOne method? - List users = new List(); - foreach (IContactItem result in search.Search(1)) + using (ISearch search = _gab.Contacts.Search()) { - return new GABUser(result.FullName, result.CustomerID); + search.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Equal, username); + + // Fetch the result, if any. + List users = new List(); + using (IContactItem result = search.SearchOne()) + { + if (result != null) + return new GABUser(result.FullName, result.CustomerID); + } } } From f44e092ca02c6731ea6870c0cb378294056de81c Mon Sep 17 00:00:00 2001 From: Patrick Simpson Date: Mon, 27 Feb 2017 13:16:53 +0100 Subject: [PATCH 3/5] [KOE-17] signatures now include smtp address of account for uniqueness. Signatures are also synced periodically. --- .../Features/Signatures/FeatureSignatures.cs | 65 +++++++++++++------ .../Stubs/OutlookWrappers/SignatureWrapper.cs | 2 +- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs index e612e59..32faec6 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs @@ -59,6 +59,7 @@ namespace Acacia.Features.Signatures { _gab.SyncFinished += GAB_SyncFinished; } + Watcher.Sync.AddTask(this, Name, Periodic_Sync); } private void Watcher_AccountDiscovered(ZPushAccount account) @@ -70,32 +71,56 @@ namespace Acacia.Features.Signatures { // TODO: make a helper to register for all zpush accounts with specific capabilities, best even // the feature's capabilities - if (account.Confirmed == ZPushAccount.ConfirmationType.IsZPush && - account.Capabilities.Has("signatures")) + if (account.Confirmed == ZPushAccount.ConfirmationType.IsZPush) { - Logger.Instance.Trace(this, "Checking signature hash for account {0}: {1}", account, account.ServerSignaturesHash); + SyncSignatures(account, account.ServerSignaturesHash); + } + } - // Fetch signatures if there is a change - if (account.ServerSignaturesHash != account.Account.LocalSignaturesHash) + private void Periodic_Sync(ZPushConnection connection) + { + try + { + // TODO: merge this into ZPushAccount, allow periodic rechecking of Z-Push confirmation. That was other + // features can be updated too, e.g. OOF status. That's pretty easy to do, only need to check if + // no other features will break if the ConfirmedChanged event is raised multiple times + ActiveSync.SettingsOOF oof = connection.Execute(new ActiveSync.SettingsOOFGet()); + SyncSignatures(connection.Account, oof.RawResponse.SignaturesHash); + } + catch(System.Exception e) + { + Logger.Instance.Error(this, "Error fetching signature hash: {0}", e); + } + } + + private void SyncSignatures(ZPushAccount account, string serverSignatureHash) + { + if (!account.Capabilities.Has("signatures")) + return; + + Logger.Instance.Trace(this, "Checking signature hash for account {0}: {1}", account, serverSignatureHash); + + // Fetch signatures if there is a change + if (serverSignatureHash != account.Account.LocalSignaturesHash) + { + try { - try - { - Logger.Instance.Debug(this, "Updating signatures: {0}", account); - FetchSignatures(account); + Logger.Instance.Debug(this, "Updating signatures: {0}", account); + FetchSignatures(account); - // Store updated hash - account.Account.LocalSignaturesHash = account.ServerSignaturesHash; - Logger.Instance.Debug(this, "Updated signatures: {0}", account); - } - catch (Exception e) - { - Logger.Instance.Error(this, "Error fetching signatures: {0}: {1}", account, e); - } + // Store updated hash + account.Account.LocalSignaturesHash = serverSignatureHash; + Logger.Instance.Debug(this, "Updated signatures: {0}", account); + } + catch (Exception e) + { + Logger.Instance.Error(this, "Error fetching signatures: {0}: {1}", account, e); } } } - + #region API + // Prevent field assignment warnings #pragma warning disable 0649 @@ -152,6 +177,8 @@ namespace Acacia.Features.Signatures } } + #endregion + private string StoreSignature(ISignatures signatures, ZPushAccount account, Signature signatureInfo) { string name = GetSignatureName(signatures, account, signatureInfo.name); @@ -204,7 +231,7 @@ namespace Acacia.Features.Signatures { return SignatureLocalName.ReplaceStringTokens("%", "%", new Dictionary { - { "account", account.DisplayName }, + { "account", account.Account.SmtpAddress }, { "name", name } }); } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs index 15279b0..a64ff85 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs @@ -50,7 +50,7 @@ namespace Acacia.Stubs.OutlookWrappers private static string GetPath(string name, string suffix) { - return Path.ChangeExtension(Path.Combine(BasePath, name), suffix); + return Path.Combine(BasePath, name) + "." + suffix; } public void Delete() From e98240ab472137ec39f82827541a5ea26761b355 Mon Sep 17 00:00:00 2001 From: Patrick Simpson Date: Mon, 27 Feb 2017 13:51:42 +0100 Subject: [PATCH 4/5] [KOE-17] Added settings dialog with resynchronise button. Added option to overwrite local signatures. --- .../AcaciaZPushPlugin.csproj | 9 + .../Features/Signatures/FeatureSignatures.cs | 86 ++++-- .../Signatures/SignaturesSettings.Designer.cs | 79 ++++++ .../Features/Signatures/SignaturesSettings.cs | 84 ++++++ .../Signatures/SignaturesSettings.resx | 252 ++++++++++++++++++ .../Properties/Resources.Designer.cs | 27 ++ .../Properties/Resources.resx | 9 + .../AcaciaZPushPlugin/UI/SettingsDialog.resx | 41 +-- 8 files changed, 542 insertions(+), 45 deletions(-) create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.Designer.cs create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.cs create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.resx diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj index fb76988..69353fd 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj @@ -275,6 +275,12 @@ + + UserControl + + + SignaturesSettings.cs + @@ -549,6 +555,9 @@ SharedFoldersDialog.cs + + SignaturesSettings.cs + ResXFileCodeGenerator Resources.Designer.cs diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs index 32faec6..4d0fc38 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs @@ -17,6 +17,7 @@ using Acacia.Features.GAB; /// Consult LICENSE file for details using Acacia.Stubs; using Acacia.Stubs.OutlookWrappers; +using Acacia.UI; using Acacia.Utils; using Acacia.ZPush; using Acacia.ZPush.Connect; @@ -39,6 +40,15 @@ namespace Acacia.Features.Signatures { #region Debug options + [AcaciaOption("If set, the local signature is always set to the server signature. If not set, the local signature will be set " + + "only if it is unspecified. ")] + public bool AlwaysSetLocal + { + get { return GetOption(OPTION_ALWAYS_SET_LOCAL); } + set { SetOption(OPTION_ALWAYS_SET_LOCAL, value); } + } + private static readonly BoolOption OPTION_ALWAYS_SET_LOCAL = new BoolOption("AlwaysSetLocal", false); + [AcaciaOption("The format for local names of synchronised signatures, to prevent overwriting local signatures. May contain %account% and %name%.")] public string SignatureLocalName { @@ -93,29 +103,49 @@ namespace Acacia.Features.Signatures } } + + internal void ResyncAll() + { + foreach(ZPushAccount account in Watcher.Accounts.GetAccounts()) + { + if (account.Confirmed == ZPushAccount.ConfirmationType.IsZPush) + { + SyncSignatures(account, null); + } + } + } + + /// + /// Syncs the signatures for the account. + /// + /// The account + /// The signature hash. If null, the hash will not be checked and a hard sync will be done. private void SyncSignatures(ZPushAccount account, string serverSignatureHash) { if (!account.Capabilities.Has("signatures")) return; - Logger.Instance.Trace(this, "Checking signature hash for account {0}: {1}", account, serverSignatureHash); + // Check hash if needed + if (serverSignatureHash != null) + { + Logger.Instance.Trace(this, "Checking signature hash for account {0}: {1}", account, serverSignatureHash); + if (serverSignatureHash == account.Account.LocalSignaturesHash) + return; + } // Fetch signatures if there is a change - if (serverSignatureHash != account.Account.LocalSignaturesHash) + try { - try - { - Logger.Instance.Debug(this, "Updating signatures: {0}", account); - FetchSignatures(account); + Logger.Instance.Debug(this, "Updating signatures: {0}", account); + string hash = FetchSignatures(account); - // Store updated hash - account.Account.LocalSignaturesHash = serverSignatureHash; - Logger.Instance.Debug(this, "Updated signatures: {0}", account); - } - catch (Exception e) - { - Logger.Instance.Error(this, "Error fetching signatures: {0}: {1}", account, e); - } + // Store updated hash + account.Account.LocalSignaturesHash = hash; + Logger.Instance.Debug(this, "Updated signatures: {0}: {1}", account, hash); + } + catch (Exception e) + { + Logger.Instance.Error(this, "Error fetching signatures: {0}: {1}", account, e); } } @@ -146,7 +176,12 @@ namespace Acacia.Features.Signatures { } - private void FetchSignatures(ZPushAccount account) + /// + /// Fetches the signatures for the account. + /// + /// The account. + /// The signature hash + private string FetchSignatures(ZPushAccount account) { Logger.Instance.Debug(this, "Fetching signatures for account {0}", account); using (ZPushConnection connection = account.Connect()) @@ -166,17 +201,25 @@ namespace Acacia.Features.Signatures } // Set default signatures if available and none are set - if (!string.IsNullOrEmpty(result.new_message) && string.IsNullOrEmpty(account.Account.SignatureNewMessage)) + if (!string.IsNullOrEmpty(result.new_message) && ShouldSetSignature(account.Account.SignatureNewMessage)) { account.Account.SignatureNewMessage = fullNames[result.new_message]; } - if (!string.IsNullOrEmpty(result.replyforward_message) && string.IsNullOrEmpty(account.Account.SignatureReplyForwardMessage)) + if (!string.IsNullOrEmpty(result.replyforward_message) && ShouldSetSignature(account.Account.SignatureReplyForwardMessage)) { account.Account.SignatureReplyForwardMessage = fullNames[result.replyforward_message]; } + + return result.hash; } } + private bool ShouldSetSignature(string currentSignature) + { + return string.IsNullOrEmpty(currentSignature) || AlwaysSetLocal; + } + + #endregion private string StoreSignature(ISignatures signatures, ZPushAccount account, Signature signatureInfo) @@ -334,5 +377,14 @@ namespace Acacia.Features.Signatures } } } + + #region Settings + + public override FeatureSettings GetSettings() + { + return new SignaturesSettings(this); + } + + #endregion } } \ No newline at end of file diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.Designer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.Designer.cs new file mode 100644 index 0000000..9740c08 --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.Designer.cs @@ -0,0 +1,79 @@ +namespace Acacia.Features.Signatures +{ + partial class SignaturesSettings + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SignaturesSettings)); + this._layout = new System.Windows.Forms.TableLayoutPanel(); + this.checkForceSet = new System.Windows.Forms.CheckBox(); + this.buttonResync = new System.Windows.Forms.Button(); + this._layout.SuspendLayout(); + this.SuspendLayout(); + // + // _layout + // + resources.ApplyResources(this._layout, "_layout"); + this._layout.Controls.Add(this.checkForceSet, 0, 0); + this._layout.Controls.Add(this.buttonResync, 0, 1); + this._layout.Name = "_layout"; + // + // checkForceSet + // + resources.ApplyResources(this.checkForceSet, "checkForceSet"); + this.checkForceSet.Name = "checkForceSet"; + this.checkForceSet.UseVisualStyleBackColor = true; + this.checkForceSet.CheckedChanged += new System.EventHandler(this.checkForceSet_CheckedChanged); + // + // buttonResync + // + resources.ApplyResources(this.buttonResync, "buttonResync"); + this.buttonResync.Name = "buttonResync"; + this.buttonResync.UseVisualStyleBackColor = true; + this.buttonResync.Click += new System.EventHandler(this.buttonResync_Click); + // + // SignaturesSettings + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.SystemColors.Window; + this.Controls.Add(this._layout); + this.Name = "SignaturesSettings"; + this._layout.ResumeLayout(false); + this._layout.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel _layout; + private System.Windows.Forms.CheckBox checkForceSet; + private System.Windows.Forms.Button buttonResync; + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.cs new file mode 100644 index 0000000..87ad446 --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.cs @@ -0,0 +1,84 @@ +/// Copyright 2016 Kopano b.v. +/// +/// This program is free software: you can redistribute it and/or modify +/// it under the terms of the GNU Affero General Public License, version 3, +/// as published by the Free Software Foundation. +/// +/// This program is distributed in the hope that it will be useful, +/// but WITHOUT ANY WARRANTY; without even the implied warranty of +/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +/// GNU Affero General Public License for more details. +/// +/// You should have received a copy of the GNU Affero General Public License +/// along with this program.If not, see. +/// +/// Consult LICENSE file for details + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Acacia.ZPush; +using Acacia.UI; + +namespace Acacia.Features.Signatures +{ + public partial class SignaturesSettings : FeatureSettings + { + private readonly FeatureSignatures _feature; + public override Feature Feature + { + get + { + return _feature; + } + } + + public SignaturesSettings(FeatureSignatures feature = null) + { + this._feature = feature; + + InitializeComponent(); + + // Allow null feature for designer + if (feature != null) + { + checkForceSet.Checked = feature.AlwaysSetLocal; + } + } + + override public void Apply() + { + } + + private void CheckDirty() + { + Dirty = false; + } + + private void buttonResync_Click(object sender, EventArgs e) + { + if (_feature != null) + { + ProgressDialog.Execute("SignaturesSync", + (ct) => + { + _feature.ResyncAll(); + return 0; + } + ); + } + } + + private void checkForceSet_CheckedChanged(object sender, EventArgs e) + { + if (_feature != null) + _feature.AlwaysSetLocal = checkForceSet.Checked; + } + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.resx b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.resx new file mode 100644 index 0000000..49becf8 --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/SignaturesSettings.resx @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + + GrowAndShrink + + + 1 + + + True + + + Fill + + + + 4, 4 + + + 4, 4, 4, 4 + + + 152, 17 + + + 0 + + + Override local signatures + + + checkForceSet + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + _layout + + + 0 + + + True + + + 3, 28 + + + 8, 0, 8, 0 + + + 154, 23 + + + 1 + + + Resynchronise signatures + + + buttonResync + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + _layout + + + 1 + + + Fill + + + 0, 0 + + + 2, 2, 2, 2 + + + 2 + + + 160, 54 + + + 0 + + + _layout + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="checkForceSet" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="buttonResync" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,100,Absolute,20" /><Rows Styles="AutoSize,0,AutoSize,0" /></TableLayoutSettings> + + + True + + + 6, 13 + + + True + + + GrowAndShrink + + + 2, 2, 2, 2 + + + 160, 54 + + + SignaturesSettings + + + Acacia.UI.FeatureSettings, Kopano, Version=0.1.0.0, Culture=neutral, PublicKeyToken=null + + \ No newline at end of file diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs index 204b24a..ae43403 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs @@ -132,6 +132,15 @@ namespace Acacia.Properties { } } + /// + /// Looks up a localized string similar to Signatures. + /// + internal static string Feature_Signatures { + get { + return ResourceManager.GetString("Feature_Signatures", resourceCulture); + } + } + /// /// Looks up a localized string similar to Address Book for {0}. /// @@ -1019,6 +1028,24 @@ namespace Acacia.Properties { } } + /// + /// Looks up a localized string similar to The signatures are being synchronised.. + /// + internal static string SignaturesSync_Label { + get { + return ResourceManager.GetString("SignaturesSync_Label", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Signatures. + /// + internal static string SignaturesSync_Title { + get { + return ResourceManager.GetString("SignaturesSync_Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to There is an error with the security certificate for server {0}. Do you want to allow the connection anyway?. /// diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx index a8eb0c0..c75b51b 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx @@ -445,4 +445,13 @@ Password unavailable + + Signatures + + + The signatures are being synchronised. + + + Signatures + \ No newline at end of file diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/SettingsDialog.resx b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/SettingsDialog.resx index fae433e..65262a9 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/SettingsDialog.resx +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/UI/SettingsDialog.resx @@ -126,14 +126,10 @@ - 358, 4 - - - - 4, 4, 4, 4 + 269, 3 - 100, 33 + 75, 27 0 @@ -157,13 +153,10 @@ True - 250, 4 - - - 4, 4, 4, 4 + 188, 3 - 100, 33 + 75, 27 1 @@ -187,13 +180,10 @@ True - 142, 4 - - - 4, 4, 4, 4 + 107, 3 - 100, 33 + 75, 27 2 @@ -213,6 +203,7 @@ 2 + Bottom @@ -220,16 +211,13 @@ RightToLeft - 0, 394 - - - 4, 4, 4, 4 + 0, 374 - 0, 0, 7, 0 + 0, 0, 5, 0 - 469, 37 + 352, 30 0 @@ -250,16 +238,13 @@ True - 8, 16 + 6, 13 True - 469, 431 - - - 4, 4, 4, 4 + 352, 404 CenterParent @@ -271,6 +256,6 @@ SettingsDialog - System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Acacia.UI.KopanoDialog, Kopano, Version=0.1.0.0, Culture=neutral, PublicKeyToken=null \ No newline at end of file From 5339fbec8bcc0fa83605517b7d43ce3d9cbb74ec Mon Sep 17 00:00:00 2001 From: KOE_Export_Strings_Commit Date: Mon, 27 Feb 2017 12:58:06 +0100 Subject: [PATCH 5/5] Commit strings #142 --- translations/KOE.pot | 30 ++++++++++++++++++++++++++++++ translations/en.po | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/translations/KOE.pot b/translations/KOE.pot index 5855095..0d96d0d 100644 --- a/translations/KOE.pot +++ b/translations/KOE.pot @@ -220,6 +220,18 @@ msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\$this. msgid "Shared Folders - {0}" msgstr "" +#: AcaciaZPushPlugin\Features\Signatures\SignaturesSettings\checkForceSet.Text +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Features\\Signatures\\SignaturesSettings\\checkForceSet.Text" +msgid "Override local signatures" +msgstr "" + +#: AcaciaZPushPlugin\Features\Signatures\SignaturesSettings\buttonResync.Text +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Features\\Signatures\\SignaturesSettings\\buttonResync.Text" +msgid "Resynchronise signatures" +msgstr "" + #: AcaciaZPushPlugin\Properties\Resources\OOFGet_Failed #, csharp-format msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\OOFGet_Failed" @@ -682,6 +694,24 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\AccountNoPassword_Title" msgid "Password unavailable" msgstr "" +#: AcaciaZPushPlugin\Properties\Resources\Feature_Signatures +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\Feature_Signatures" +msgid "Signatures" +msgstr "" + +#: AcaciaZPushPlugin\Properties\Resources\SignaturesSync_Label +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SignaturesSync_Label" +msgid "The signatures are being synchronised." +msgstr "" + +#: AcaciaZPushPlugin\Properties\Resources\SignaturesSync_Title +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SignaturesSync_Title" +msgid "Signatures" +msgstr "" + #: AcaciaZPushPlugin\UI\ProgressDialog\labelMessage.Text #, csharp-format msgctxt "AcaciaZPushPlugin\\UI\\ProgressDialog\\labelMessage.Text" diff --git a/translations/en.po b/translations/en.po index c520b48..e4ebb10 100644 --- a/translations/en.po +++ b/translations/en.po @@ -220,6 +220,18 @@ msgctxt "AcaciaZPushPlugin\\Features\\SharedFolders\\SharedFoldersDialog\\$this. msgid "Shared Folders - {0}" msgstr "Shared Folders - {0}" +#: AcaciaZPushPlugin\Features\Signatures\SignaturesSettings\checkForceSet.Text +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Features\\Signatures\\SignaturesSettings\\checkForceSet.Text" +msgid "Override local signatures" +msgstr "Override local signatures" + +#: AcaciaZPushPlugin\Features\Signatures\SignaturesSettings\buttonResync.Text +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Features\\Signatures\\SignaturesSettings\\buttonResync.Text" +msgid "Resynchronise signatures" +msgstr "Resynchronise signatures" + #: AcaciaZPushPlugin\Properties\Resources\OOFGet_Failed #, csharp-format msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\OOFGet_Failed" @@ -684,6 +696,24 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\AccountNoPassword_Title" msgid "Password unavailable" msgstr "Password unavailable" +#: AcaciaZPushPlugin\Properties\Resources\Feature_Signatures +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\Feature_Signatures" +msgid "Signatures" +msgstr "Signatures" + +#: AcaciaZPushPlugin\Properties\Resources\SignaturesSync_Label +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SignaturesSync_Label" +msgid "The signatures are being synchronised." +msgstr "The signatures are being synchronised." + +#: AcaciaZPushPlugin\Properties\Resources\SignaturesSync_Title +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SignaturesSync_Title" +msgid "Signatures" +msgstr "Signatures" + #: AcaciaZPushPlugin\UI\ProgressDialog\labelMessage.Text #, csharp-format msgctxt "AcaciaZPushPlugin\\UI\\ProgressDialog\\labelMessage.Text"