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/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/Features/Signatures/FeatureSignatures.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs index e612e59..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 { @@ -59,6 +69,7 @@ namespace Acacia.Features.Signatures { _gab.SyncFinished += GAB_SyncFinished; } + Watcher.Sync.AddTask(this, Name, Periodic_Sync); } private void Watcher_AccountDiscovered(ZPushAccount account) @@ -70,32 +81,76 @@ 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); + } + } + + + internal void ResyncAll() + { + foreach(ZPushAccount account in Watcher.Accounts.GetAccounts()) + { + if (account.Confirmed == ZPushAccount.ConfirmationType.IsZPush) { - try - { - 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); - } + 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; + + // 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 + try + { + Logger.Instance.Debug(this, "Updating signatures: {0}", account); + string hash = FetchSignatures(account); + + // 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); + } + } + + #region API + // Prevent field assignment warnings #pragma warning disable 0649 @@ -121,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()) @@ -141,17 +201,27 @@ 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) { string name = GetSignatureName(signatures, account, signatureInfo.name); @@ -204,7 +274,7 @@ namespace Acacia.Features.Signatures { return SignatureLocalName.ReplaceStringTokens("%", "%", new Dictionary { - { "account", account.DisplayName }, + { "account", account.Account.SmtpAddress }, { "name", name } }); } @@ -307,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/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() 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); + } } } 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 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); + } } } } 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"