diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj index 588180c..831ef3d 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/AcaciaZPushPlugin.csproj @@ -133,8 +133,12 @@ --> + + ..\packages\Heijden.Dns.2.0.0\lib\net35\Heijden.Dns.dll + True + - ..\packages\NLog.4.2.3\lib\net45\NLog.dll + ..\packages\NLog.4.4.1\lib\net45\NLog.dll True @@ -272,6 +276,7 @@ + diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/WebApp/FeatureWebApp.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/WebApp/FeatureWebApp.cs index 34ad026..4b837ba 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/WebApp/FeatureWebApp.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Features/WebApp/FeatureWebApp.cs @@ -124,7 +124,7 @@ namespace Acacia.Features.WebApp private string PerformAutoDiscover(ZPushAccount account) { // Fetch the txt record - List txt = DnsUtil.GetTxtRecord(account.DomainName); + IList txt = DnsUtil.GetTxtRecord(account.DomainName); if (txt == null) return null; diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/IOleWindow.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/IOleWindow.cs new file mode 100644 index 0000000..473593c --- /dev/null +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Native/IOleWindow.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Acacia.Native +{ + [ComImport] + [Guid("00000114-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleWindow + { + void GetWindow(out IntPtr phwnd); + void ContextSensitiveHelp([In, MarshalAs(UnmanagedType.Bool)] bool fEnterMode); + } +} diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs index f2f609e..204b24a 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.Designer.cs @@ -60,6 +60,24 @@ namespace Acacia.Properties { } } + /// + /// Looks up a localized string similar to The password for account '{0}' is not available. Advanced Z-Push features will not work.. + /// + internal static string AccountNoPassword_Body { + get { + return ResourceManager.GetString("AccountNoPassword_Body", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password unavailable. + /// + internal static string AccountNoPassword_Title { + get { + return ResourceManager.GetString("AccountNoPassword_Title", resourceCulture); + } + } + /// /// Looks up a localized string similar to Support. /// diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx index 93b5c6b..a8eb0c0 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Properties/Resources.resx @@ -439,4 +439,10 @@ Contacts folder Shown when a secondary contact folder is detected, to inform the user that a restart is required + + The password for account '{0}' is not available. Advanced Z-Push features will not work. + + + Password unavailable + \ No newline at end of file diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ThisAddIn.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ThisAddIn.cs index 269c820..640a8f0 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ThisAddIn.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ThisAddIn.cs @@ -32,6 +32,7 @@ using Acacia.UI.Outlook; using System.Diagnostics; using System.Runtime.InteropServices; using System.Reflection; +using Acacia.Native; namespace Acacia { @@ -244,6 +245,41 @@ namespace Acacia } } + #region Window handle + + private class WindowHandle : IWin32Window + { + private IntPtr hWnd; + + public WindowHandle(IntPtr hWnd) + { + this.hWnd = hWnd; + } + + public IntPtr Handle + { + get + { + return hWnd; + } + } + } + + public IWin32Window Window + { + get + { + var win = Application.ActiveWindow() as IOleWindow; + if (win == null) + return null; + IntPtr hWnd; + win.GetWindow(out hWnd); + return new WindowHandle(hWnd); + } + } + + #endregion + protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject() { return OutlookUI; diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DnsUtil.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DnsUtil.cs index 800cb11..a66e0da 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DnsUtil.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Utils/DnsUtil.cs @@ -1,4 +1,6 @@ -/// Copyright 2016 Kopano b.v. + +using Heijden.DNS; +/// 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, @@ -13,7 +15,6 @@ /// along with this program.If not, see. /// /// Consult LICENSE file for details - using System; using System.Collections.Generic; using System.ComponentModel; @@ -26,73 +27,11 @@ namespace Acacia.Utils { public static class DnsUtil { - public static List GetTxtRecord(string name) + public static IList GetTxtRecord(string name) { - const Int16 DNS_TYPE_TEXT = 0x0010; - const Int32 DNS_QUERY_STANDARD = 0x00000000; - const Int32 DNS_ERROR_RCODE_NAME_ERROR = 9003; - const Int32 DNS_INFO_NO_RECORDS = 9501; - var queryResultsSet = IntPtr.Zero; - try - { - var dnsStatus = DnsQuery( - name, - DNS_TYPE_TEXT, - DNS_QUERY_STANDARD, - IntPtr.Zero, - ref queryResultsSet, - IntPtr.Zero - ); - if (dnsStatus == DNS_ERROR_RCODE_NAME_ERROR || dnsStatus == DNS_INFO_NO_RECORDS) - return null; - if (dnsStatus != 0) - throw new Win32Exception(dnsStatus); - DnsRecordTxt dnsRecord; - var lines = new List(); - for (var pointer = queryResultsSet; pointer != IntPtr.Zero; pointer = dnsRecord.pNext) - { - dnsRecord = (DnsRecordTxt)Marshal.PtrToStructure(pointer, typeof(DnsRecordTxt)); - if (dnsRecord.wType == DNS_TYPE_TEXT) - { - var stringArrayPointer = pointer + Marshal.OffsetOf(typeof(DnsRecordTxt), "pStringArray").ToInt32(); - for (var i = 0; i < dnsRecord.dwStringCount; ++i) - { - var stringPointer = (IntPtr)Marshal.PtrToStructure(stringArrayPointer, typeof(IntPtr)); - lines.Add(Marshal.PtrToStringUni(stringPointer)); - stringArrayPointer += IntPtr.Size; - } - } - } - if (lines.Count == 0) - return null; - return lines; - } - finally - { - const Int32 DnsFreeRecordList = 1; - if (queryResultsSet != IntPtr.Zero) - DnsRecordListFree(queryResultsSet, DnsFreeRecordList); - } - } - - [DllImport("Dnsapi.dll", EntryPoint = "DnsQuery_W", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] - static extern Int32 DnsQuery(String lpstrName, Int16 wType, Int32 options, IntPtr pExtra, ref IntPtr ppQueryResultsSet, IntPtr pReserved); - - [DllImport("Dnsapi.dll")] - static extern void DnsRecordListFree(IntPtr pRecordList, Int32 freeType); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - struct DnsRecordTxt - { - public IntPtr pNext; - public String pName; - public Int16 wType; - public Int16 wDataLength; - public Int32 flags; - public Int32 dwTtl; - public Int32 dwReserved; - public Int32 dwStringCount; - public String pStringArray; + Resolver resolver = new Resolver(); + Response response = resolver.Query(name, QType.TXT, QClass.IN); + return response.RecordsTXT.Select(r => r.ToString()).ToList(); } } } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccount.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccount.cs index 09fc992..d3c89c9 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccount.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushAccount.cs @@ -136,6 +136,12 @@ namespace Acacia.ZPush } } + [Browsable(false)] + public bool HasPassword + { + get { return Registry.GetValue(_regPath, OutlookConstants.REG_VAL_EAS_PASSWORD, null) != null; } + } + public string StoreID { get { return GetStoreId(_regPath); } diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs index 571cfb8..dc536c5 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/ZPush/ZPushWatcher.cs @@ -141,24 +141,39 @@ namespace Acacia.ZPush // Register any events HandleFolderWatchers(account); - // Send an OOF request to get the OOF state and capabilities - Tasks.Task(null, "ZPushCheck: " + account.DisplayName, () => + if (account.HasPassword) { - // TODO: if this fails, retry? - ActiveSync.SettingsOOF oof; - using (ZPushConnection connection = new ZPushConnection(account, new System.Threading.CancellationToken(false))) + // Send an OOF request to get the OOF state and capabilities + Tasks.Task(null, "ZPushCheck: " + account.DisplayName, () => { - oof = connection.Execute(new ActiveSync.SettingsOOFGet()); - } - account.OnConfirmationResponse(oof.RawResponse); + // TODO: if this fails, retry? + ActiveSync.SettingsOOF oof; + using (ZPushConnection connection = new ZPushConnection(account, new System.Threading.CancellationToken(false))) + { + oof = connection.Execute(new ActiveSync.SettingsOOFGet()); + } + account.OnConfirmationResponse(oof.RawResponse); - // [ZO-109] Always update the current selection, it might have changed. - Explorer_SelectionChange(); + // [ZO-109] Always update the current selection, it might have changed. + Explorer_SelectionChange(); - // Notify the OOF feature. - // TODO: this coupling is pretty hideous - ThisAddIn.Instance.GetFeature()?.OnOOFSettings(account, oof); - }); + // Notify the OOF feature. + // TODO: this coupling is pretty hideous + ThisAddIn.Instance.GetFeature()?.OnOOFSettings(account, oof); + }); + } + else + { + ThisAddIn.Instance.InvokeUI(() => + { + Logger.Instance.Warning(this, "Password not available for account: {0}", account); + System.Windows.Forms.MessageBox.Show(ThisAddIn.Instance.Window, + string.Format(Properties.Resources.AccountNoPassword_Body, account.DisplayName), + Properties.Resources.AccountNoPassword_Title, + System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information + ); + }); + } } internal void OnAccountsScanned() diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/packages.config b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/packages.config index fccc652..39929b3 100644 --- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/packages.config +++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/packages.config @@ -1,4 +1,5 @@  - + + \ No newline at end of file diff --git a/translations/KOE.pot b/translations/KOE.pot index 93bbd1c..5855095 100644 --- a/translations/KOE.pot +++ b/translations/KOE.pot @@ -670,6 +670,18 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SecondaryContactsPatched_Titl msgid "Contacts folder" msgstr "" +#: AcaciaZPushPlugin\Properties\Resources\AccountNoPassword_Body +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\AccountNoPassword_Body" +msgid "The password for account \'{0}\' is not available. Advanced Z-Push features will not work." +msgstr "" + +#: AcaciaZPushPlugin\Properties\Resources\AccountNoPassword_Title +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\AccountNoPassword_Title" +msgid "Password unavailable" +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 84c97b0..c520b48 100644 --- a/translations/en.po +++ b/translations/en.po @@ -672,6 +672,18 @@ msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\SecondaryContactsPatched_Titl msgid "Contacts folder" msgstr "Contacts folder" +#: AcaciaZPushPlugin\Properties\Resources\AccountNoPassword_Body +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\AccountNoPassword_Body" +msgid "The password for account \'{0}\' is not available. Advanced Z-Push features will not work." +msgstr "The password for account \'{0}\' is not available. Advanced Z-Push features will not work." + +#: AcaciaZPushPlugin\Properties\Resources\AccountNoPassword_Title +#, csharp-format +msgctxt "AcaciaZPushPlugin\\Properties\\Resources\\AccountNoPassword_Title" +msgid "Password unavailable" +msgstr "Password unavailable" + #: AcaciaZPushPlugin\UI\ProgressDialog\labelMessage.Text #, csharp-format msgctxt "AcaciaZPushPlugin\\UI\\ProgressDialog\\labelMessage.Text"