From e735aafc72cac030fe406e15b844e27cb03db919 Mon Sep 17 00:00:00 2001
From: Patrick Simpson
Date: Thu, 23 Feb 2017 15:29:53 +0100
Subject: [PATCH] [KOE-17] Basic infrastructure is working, still need
replacement of placeholders
---
.../AcaciaZPushPlugin.csproj | 7 +-
.../AcaciaZPushPlugin/Constants.cs | 3 +-
.../AcaciaZPushPlugin/DebugOptions.cs | 32 +++
.../FeatureSecondaryContacts.cs | 11 +-
.../Features/Signatures/FeatureSignatures.cs | 186 ++++++++++++++++++
.../AcaciaZPushPlugin/Native/IOlkAccount.cs | 53 +++++
.../AcaciaZPushPlugin/Native/MAPI/Property.cs | 9 +
.../AcaciaZPushPlugin/OutlookConstants.cs | 4 +
.../AcaciaZPushPlugin/Stubs/IAccount.cs | 18 ++
.../AcaciaZPushPlugin/Stubs/IAddIn.cs | 4 +
.../AcaciaZPushPlugin/Stubs/ISignature.cs | 20 ++
.../AcaciaZPushPlugin/Stubs/ISignatures.cs | 14 ++
.../Stubs/OutlookWrappers/AccountWrapper.cs | 92 ++++++++-
.../Stubs/OutlookWrappers/AddInWrapper.cs | 36 +++-
.../Stubs/OutlookWrappers/SignatureWrapper.cs | 80 ++++++++
.../OutlookWrappers/SignaturesWrapper.cs | 38 ++++
.../Stubs/OutlookWrappers/StoresWrapper.cs | 2 +-
.../AcaciaZPushPlugin/ThisAddIn.cs | 7 -
.../AcaciaZPushPlugin/Utils/ReflectUtil.cs | 25 ++-
.../AcaciaZPushPlugin/Utils/RegistryUtil.cs | 6 +-
.../AcaciaZPushPlugin/Utils/StringUtil.cs | 21 ++
.../ZPush/Connect/Soap/SoapSerializer.cs | 171 ++++++++++------
.../ZPush/Connect/ZPushConnection.cs | 7 +
.../AcaciaZPushPlugin/ZPush/ZPushAccount.cs | 12 +-
24 files changed, 777 insertions(+), 81 deletions(-)
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/IOlkAccount.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ISignature.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/ISignatures.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignatureWrapper.cs
create mode 100644 src/AcaciaZPushPlugin/AcaciaZPushPlugin/Stubs/OutlookWrappers/SignaturesWrapper.cs
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
index 7370ed3..4e8901d 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj
@@ -274,16 +274,17 @@
+
+
-
@@ -299,6 +300,8 @@
+
+
@@ -312,6 +315,8 @@
+
+
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Constants.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Constants.cs
index d03a91d..eebca38 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Constants.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Constants.cs
@@ -74,7 +74,8 @@ namespace Acacia
public const string ZPUSH_HEADER_CLIENT_CAPABILITIES = "X-Push-Plugin-Capabilities";
public const string ZPUSH_HEADER_PLUGIN = "X-Push-Plugin";
public const string ZPUSH_HEADER_VERSION = "X-Z-Push-Version";
-
+ public const string ZPUSH_HEADER_SIGNATURES_HASH = "X-Push-Signatures-Hash";
+
#endregion
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/DebugOptions.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/DebugOptions.cs
index 93127fa..bf9fa73 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/DebugOptions.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/DebugOptions.cs
@@ -142,6 +142,38 @@ namespace Acacia
}
+ public class StringOption : Option
+ {
+ private readonly string _defaultValue;
+
+ public StringOption(string token, string defaultValue)
+ :
+ base(token)
+ {
+ this._defaultValue = defaultValue;
+ }
+
+ public override string GetToken(string value)
+ {
+ if (value.Equals(_defaultValue))
+ return null;
+ return Token + "=" + value.ToString();
+ }
+
+ public override string GetValue(string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ return _defaultValue;
+ else
+ {
+ if (value.ToLower().StartsWith(Token.ToLower() + "="))
+ value = value.Substring(Token.Length + 1);
+ return value;
+ }
+ }
+
+ }
+
// General
public static readonly BoolOption ENABLED = new BoolOption("", true);
public static readonly BoolOption FEATURE_DISABLED_DEFAULT = new BoolOption("", false);
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SecondaryContacts/FeatureSecondaryContacts.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SecondaryContacts/FeatureSecondaryContacts.cs
index 691eb2d..2d3586b 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SecondaryContacts/FeatureSecondaryContacts.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/SecondaryContacts/FeatureSecondaryContacts.cs
@@ -87,7 +87,6 @@ namespace Acacia.Features.SecondaryContacts
// So, when the folder is detected, we make it invisible and perform steps 1 and 2. We issue a warning
// that Outlook must be restarted. When the folder is detected again and is invisible, that means we've restarted
// At this point the name is patched and the folder is made visible.
-
if (!folder.AttrHidden)
{
// Stage 1
@@ -113,12 +112,12 @@ namespace Acacia.Features.SecondaryContacts
// Stage 2
// Patch the name
- Logger.Instance.Trace(this, "Patching name");
- folder.Name = strippedName;
+ Logger.Instance.Trace(this, "Patching name");
+ folder.Name = strippedName;
- // Show it
- folder.AttrHidden = false;
- Logger.Instance.Debug(this, "Shown secondary contacts folder: {0}", strippedName);
+ // Show it
+ folder.AttrHidden = false;
+ Logger.Instance.Debug(this, "Shown secondary contacts folder: {0}", strippedName);
}
Logger.Instance.Debug(this, "Patching done: {0}: {1}", strippedName, folder.AttrHidden);
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs
new file mode 100644
index 0000000..51f34cb
--- /dev/null
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/Signatures/FeatureSignatures.cs
@@ -0,0 +1,186 @@
+/// Copyright 2017 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 Acacia.Stubs;
+using Acacia.Stubs.OutlookWrappers;
+using Acacia.Utils;
+using Acacia.ZPush;
+using Acacia.ZPush.Connect;
+using Acacia.ZPush.Connect.Soap;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static Acacia.DebugOptions;
+
+namespace Acacia.Features.Signatures
+{
+ [AcaciaOption("Provides the possibility to synchronise signatures from the server.")]
+ public class FeatureSignatures : Feature
+ {
+ #region Debug options
+
+ [AcaciaOption("The format for local names of synchronised signatures, to prevent overwriting local signatures. May contain %account% and %name%.")]
+ public string SignatureLocalName
+ {
+ get { return GetOption(OPTION_SIGNATURE_LOCAL_NAME); }
+ set { SetOption(OPTION_SIGNATURE_LOCAL_NAME, value); }
+ }
+ private static readonly StringOption OPTION_SIGNATURE_LOCAL_NAME = new StringOption("SignatureLocalName", "%name% (KOE-%account%)");
+
+ #endregion
+
+ public override void Startup()
+ {
+ Watcher.AccountDiscovered += Watcher_AccountDiscovered;
+ }
+
+ private void Watcher_AccountDiscovered(ZPushAccount account)
+ {
+ account.ConfirmedChanged += Account_ConfirmedChanged;
+ }
+
+ private void Account_ConfirmedChanged(ZPushAccount account)
+ {
+ // 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"))
+ {
+ Logger.Instance.Trace(this, "Checking signature hash for account {0}: {1}", account, account.ServerSignaturesHash);
+
+ // Fetch signatures if there is a change
+ if (account.ServerSignaturesHash != account.Account.LocalSignaturesHash)
+ {
+ 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);
+ }
+ }
+ }
+ }
+
+
+ // Prevent field assignment warnings
+ #pragma warning disable 0649
+
+ private class Signature
+ {
+ public string id;
+ public string name;
+ public string content;
+ public bool isHTML;
+ }
+
+ private class GetSignatures
+ {
+ public Dictionary all;
+ public string new_message;
+ public string replyforward_message;
+ public string hash;
+ }
+
+ #pragma warning restore 0649
+
+ private class GetSignaturesRequest : SoapRequest
+ {
+ }
+
+ private void FetchSignatures(ZPushAccount account)
+ {
+ Logger.Instance.Debug(this, "Fetching signatures for account {0}", account);
+ using (ZPushConnection connection = account.Connect())
+ using (ZPushWebServiceInfo infoService = connection.InfoService)
+ {
+ GetSignatures result = infoService.Execute(new GetSignaturesRequest());
+
+ // Store the signatures
+ Dictionary