mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-03 15:40:18 -04:00
WIP Update lib to 2.37
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -17,13 +17,23 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if DEBUG
|
||||
// #define DEBUG_BREAKONFAIL
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
|
||||
#if !KeePassUAP
|
||||
using System.Windows.Forms;
|
||||
#endif
|
||||
|
||||
using ModernKeePassLib.Native;
|
||||
|
||||
@@ -31,19 +41,72 @@ namespace ModernKeePassLib.Utility
|
||||
{
|
||||
public static class MonoWorkarounds
|
||||
{
|
||||
private static bool? m_bReq = null;
|
||||
private const string AppXDoTool = "xdotool";
|
||||
|
||||
private static Dictionary<uint, bool> g_dForceReq = new Dictionary<uint, bool>();
|
||||
private static Thread g_thFixClip = null;
|
||||
// private static Predicate<IntPtr> g_fOwnWindow = null;
|
||||
|
||||
#if DEBUG_BREAKONFAIL
|
||||
private static DebugBreakTraceListener g_tlBreak = null;
|
||||
#endif
|
||||
|
||||
private static bool? g_bReq = null;
|
||||
public static bool IsRequired()
|
||||
{
|
||||
if(!m_bReq.HasValue) m_bReq = NativeLib.IsUnix();
|
||||
return m_bReq.Value;
|
||||
if(!g_bReq.HasValue) g_bReq = NativeLib.IsUnix();
|
||||
return g_bReq.Value;
|
||||
}
|
||||
|
||||
// 1219:
|
||||
// Mono prepends byte order mark (BOM) to StdIn.
|
||||
// https://sourceforge.net/p/keepass/bugs/1219/
|
||||
// 1245:
|
||||
// Key events not raised while Alt is down, and nav keys out of order.
|
||||
// https://sourceforge.net/p/keepass/bugs/1245/
|
||||
// 1254:
|
||||
// NumericUpDown bug: text is drawn below up/down buttons.
|
||||
// https://sourceforge.net/p/keepass/bugs/1254/
|
||||
// 1354:
|
||||
// Finalizer of NotifyIcon throws on Unity.
|
||||
// See also 1574.
|
||||
// https://sourceforge.net/p/keepass/bugs/1354/
|
||||
// 1358:
|
||||
// FileDialog crashes when ~/.recently-used is invalid.
|
||||
// https://sourceforge.net/p/keepass/bugs/1358/
|
||||
// 1366:
|
||||
// Drawing bug when scrolling a RichTextBox.
|
||||
// https://sourceforge.net/p/keepass/bugs/1366/
|
||||
// 1378:
|
||||
// Mono doesn't implement Microsoft.Win32.SystemEvents events.
|
||||
// https://sourceforge.net/p/keepass/bugs/1378/
|
||||
// https://github.com/mono/mono/blob/master/mcs/class/System/Microsoft.Win32/SystemEvents.cs
|
||||
// 1418:
|
||||
// Minimizing a form while loading it doesn't work.
|
||||
// https://sourceforge.net/p/keepass/bugs/1418/
|
||||
// 1468:
|
||||
// Use LibGCrypt for AES-KDF, because Mono's implementations
|
||||
// of RijndaelManaged and AesCryptoServiceProvider are slow.
|
||||
// https://sourceforge.net/p/keepass/bugs/1468/
|
||||
// 1527:
|
||||
// Timer causes 100% CPU load.
|
||||
// https://sourceforge.net/p/keepass/bugs/1527/
|
||||
// 1530:
|
||||
// Mono's clipboard functions don't work properly.
|
||||
// https://sourceforge.net/p/keepass/bugs/1530/
|
||||
// 1574:
|
||||
// Finalizer of NotifyIcon throws on Mac OS X.
|
||||
// See also 1354.
|
||||
// https://sourceforge.net/p/keepass/bugs/1574/
|
||||
// 1632:
|
||||
// RichTextBox rendering bug for bold/italic text.
|
||||
// https://sourceforge.net/p/keepass/bugs/1632/
|
||||
// 2139:
|
||||
// Shortcut keys are ignored.
|
||||
// https://sourceforge.net/p/keepass/feature-requests/2139/
|
||||
// 2140:
|
||||
// Explicit control focusing is ignored.
|
||||
// https://sourceforge.net/p/keepass/feature-requests/2140/
|
||||
// 5795:
|
||||
// Text in input field is incomplete.
|
||||
// https://bugzilla.xamarin.com/show_bug.cgi?id=5795
|
||||
@@ -60,6 +123,12 @@ namespace ModernKeePassLib.Utility
|
||||
// PictureBox not rendered when bitmap height >= control height.
|
||||
// https://bugzilla.xamarin.com/show_bug.cgi?id=12525
|
||||
// https://sourceforge.net/p/keepass/discussion/329220/thread/54f61e9a/
|
||||
// 100001:
|
||||
// Control locations/sizes are invalid/unexpected.
|
||||
// [NoRef]
|
||||
// 373134:
|
||||
// Control.InvokeRequired doesn't always return the correct value.
|
||||
// https://bugzilla.novell.com/show_bug.cgi?id=373134
|
||||
// 586901:
|
||||
// RichTextBox doesn't handle Unicode string correctly.
|
||||
// https://bugzilla.novell.com/show_bug.cgi?id=586901
|
||||
@@ -71,17 +140,23 @@ namespace ModernKeePassLib.Utility
|
||||
// https://bugzilla.novell.com/show_bug.cgi?id=649266
|
||||
// 686017:
|
||||
// Minimum sizes must be enforced.
|
||||
// http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=686017
|
||||
// https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=686017
|
||||
// 801414:
|
||||
// Mono recreates the main window incorrectly.
|
||||
// https://bugs.launchpad.net/ubuntu/+source/keepass2/+bug/801414
|
||||
// 891029:
|
||||
// Increase tab control height, otherwise Mono throws exceptions.
|
||||
// Increase tab control height and don't use images on tabs.
|
||||
// https://sourceforge.net/projects/keepass/forums/forum/329221/topic/4519750
|
||||
// https://bugs.launchpad.net/ubuntu/+source/keepass2/+bug/891029
|
||||
// https://sourceforge.net/p/keepass/bugs/1256/
|
||||
// https://sourceforge.net/p/keepass/bugs/1566/
|
||||
// https://sourceforge.net/p/keepass/bugs/1634/
|
||||
// 836428016:
|
||||
// ListView group header selection unsupported.
|
||||
// https://sourceforge.net/p/keepass/discussion/329221/thread/31dae0f0/
|
||||
// 2449941153:
|
||||
// RichTextBox doesn't properly escape '}' when generating RTF data.
|
||||
// https://sourceforge.net/p/keepass/discussion/329221/thread/920722a1/
|
||||
// 3574233558:
|
||||
// Problems with minimizing windows, no content rendered.
|
||||
// https://sourceforge.net/p/keepass/discussion/329220/thread/d50a79d6/
|
||||
@@ -89,6 +164,9 @@ namespace ModernKeePassLib.Utility
|
||||
{
|
||||
if(!MonoWorkarounds.IsRequired()) return false;
|
||||
|
||||
bool bForce;
|
||||
if(g_dForceReq.TryGetValue(uBugID, out bForce)) return bForce;
|
||||
|
||||
ulong v = NativeLib.MonoVersion;
|
||||
if(v != 0)
|
||||
{
|
||||
@@ -99,6 +177,140 @@ namespace ModernKeePassLib.Utility
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void SetEnabled(string strIDs, bool bEnabled)
|
||||
{
|
||||
if(string.IsNullOrEmpty(strIDs)) return;
|
||||
|
||||
string[] vIDs = strIDs.Split(new char[] { ',' });
|
||||
foreach(string strID in vIDs)
|
||||
{
|
||||
if(string.IsNullOrEmpty(strID)) continue;
|
||||
|
||||
uint uID;
|
||||
if(StrUtil.TryParseUInt(strID.Trim(), out uID))
|
||||
g_dForceReq[uID] = bEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Initialize()
|
||||
{
|
||||
Terminate();
|
||||
|
||||
// g_fOwnWindow = fOwnWindow;
|
||||
|
||||
if(IsRequired(1530))
|
||||
{
|
||||
try
|
||||
{
|
||||
ThreadStart ts = new ThreadStart(MonoWorkarounds.FixClipThread);
|
||||
g_thFixClip = new Thread(ts);
|
||||
g_thFixClip.Start();
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
|
||||
#if DEBUG_BREAKONFAIL
|
||||
if(IsRequired() && (g_tlBreak == null))
|
||||
{
|
||||
g_tlBreak = new DebugBreakTraceListener();
|
||||
Debug.Listeners.Add(g_tlBreak);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void Terminate()
|
||||
{
|
||||
if(g_thFixClip != null)
|
||||
{
|
||||
try { g_thFixClip.Abort(); }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
g_thFixClip = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FixClipThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
#if !KeePassUAP
|
||||
const int msDelay = 250;
|
||||
|
||||
string strTest = ClipboardU.GetText();
|
||||
if(strTest == null) return; // No clipboard support
|
||||
|
||||
// Without XDoTool, the workaround would be applied to
|
||||
// all applications, which may corrupt the clipboard
|
||||
// when it doesn't contain simple text only;
|
||||
// https://sourceforge.net/p/keepass/bugs/1603/#a113
|
||||
strTest = (NativeLib.RunConsoleApp(AppXDoTool,
|
||||
"help") ?? string.Empty).Trim();
|
||||
if(strTest.Length == 0) return;
|
||||
|
||||
Thread.Sleep(msDelay);
|
||||
|
||||
string strLast = null;
|
||||
while(true)
|
||||
{
|
||||
string str = ClipboardU.GetText();
|
||||
if(str == null) { Debug.Assert(false); }
|
||||
else if(str != strLast)
|
||||
{
|
||||
if(NeedClipboardWorkaround())
|
||||
ClipboardU.SetText(str, true);
|
||||
|
||||
strLast = str;
|
||||
}
|
||||
|
||||
Thread.Sleep(msDelay);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch(ThreadAbortException)
|
||||
{
|
||||
try { Thread.ResetAbort(); }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
finally { g_thFixClip = null; }
|
||||
}
|
||||
|
||||
#if !KeePassUAP
|
||||
private static bool NeedClipboardWorkaround()
|
||||
{
|
||||
try
|
||||
{
|
||||
string strHandle = (NativeLib.RunConsoleApp(AppXDoTool,
|
||||
"getactivewindow") ?? string.Empty).Trim();
|
||||
if(strHandle.Length == 0) { Debug.Assert(false); return false; }
|
||||
|
||||
// IntPtr h = new IntPtr(long.Parse(strHandle));
|
||||
long.Parse(strHandle); // Validate
|
||||
|
||||
// Detection of own windows based on Form.Handle
|
||||
// comparisons doesn't work reliably (Mono's handles
|
||||
// are usually off by 1)
|
||||
// Predicate<IntPtr> fOwnWindow = g_fOwnWindow;
|
||||
// if(fOwnWindow != null)
|
||||
// {
|
||||
// if(fOwnWindow(h)) return true;
|
||||
// }
|
||||
// else { Debug.Assert(false); }
|
||||
|
||||
string strWmClass = (NativeLib.RunConsoleApp("xprop",
|
||||
"-id " + strHandle + " WM_CLASS") ?? string.Empty);
|
||||
|
||||
if(strWmClass.IndexOf("\"" + PwDefs.ResClass + "\"",
|
||||
StrUtil.CaseIgnoreCmp) >= 0) return true;
|
||||
if(strWmClass.IndexOf("\"Remmina\"",
|
||||
StrUtil.CaseIgnoreCmp) >= 0) return true;
|
||||
}
|
||||
catch(ThreadAbortException) { throw; }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void ApplyTo(Form f)
|
||||
{
|
||||
if(!MonoWorkarounds.IsRequired()) return;
|
||||
@@ -320,5 +532,57 @@ namespace ModernKeePassLib.Utility
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that the file ~/.recently-used is valid (in order to
|
||||
/// prevent Mono's FileDialog from crashing).
|
||||
/// </summary>
|
||||
internal static void EnsureRecentlyUsedValid()
|
||||
{
|
||||
if(!MonoWorkarounds.IsRequired(1358)) return;
|
||||
|
||||
try
|
||||
{
|
||||
string strFile = Environment.GetFolderPath(
|
||||
Environment.SpecialFolder.Personal);
|
||||
strFile = UrlUtil.EnsureTerminatingSeparator(strFile, false);
|
||||
strFile += ".recently-used";
|
||||
|
||||
if(File.Exists(strFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Mono's WriteRecentlyUsedFiles method also loads the
|
||||
// XML file using XmlDocument
|
||||
XmlDocument xd = new XmlDocument();
|
||||
xd.Load(strFile);
|
||||
}
|
||||
catch(Exception) // The XML file is invalid
|
||||
{
|
||||
File.Delete(strFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
#endif // !KeePassUAP
|
||||
|
||||
#if DEBUG_BREAKONFAIL
|
||||
private sealed class DebugBreakTraceListener : TraceListener
|
||||
{
|
||||
public override void Fail(string message)
|
||||
{
|
||||
Debugger.Break();
|
||||
}
|
||||
|
||||
public override void Fail(string message, string detailMessage)
|
||||
{
|
||||
Debugger.Break();
|
||||
}
|
||||
|
||||
public override void Write(string message) { }
|
||||
public override void WriteLine(string message) { }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user