WIP Lib version 2.39.1

This commit is contained in:
BONNEVILLE Geoffroy
2018-05-22 18:27:44 +02:00
parent 0b95669db0
commit ad02740d8a
43 changed files with 1469 additions and 522 deletions

View File

@@ -496,11 +496,21 @@ namespace ModernKeePassLib.Utility
return UInt32ToBytes((uint)iValue);
}
public static void Int32ToBytesEx(int iValue, byte[] pb, int iOffset)
{
UInt32ToBytesEx((uint)iValue, pb, iOffset);
}
public static byte[] Int64ToBytes(long lValue)
{
return UInt64ToBytes((ulong)lValue);
}
public static void Int64ToBytesEx(long lValue, byte[] pb, int iOffset)
{
UInt64ToBytesEx((ulong)lValue, pb, iOffset);
}
public static uint RotateLeft32(uint u, int nBits)
{
return ((u << nBits) | (u >> (32 - nBits)));

View File

@@ -23,7 +23,7 @@ using System.Collections.Specialized;
using System.Diagnostics;
using System.Text;
#if !KeePassUAP
#if !ModernKeePassLib
using System.Windows.Forms;
#endif
@@ -34,7 +34,8 @@ namespace ModernKeePassLib.Utility
{
public sealed class MessageServiceEventArgs : EventArgs
{
private string m_strTitle = string.Empty;
#if !ModernKeePassLib
private string m_strTitle = string.Empty;
private string m_strText = string.Empty;
private MessageBoxButtons m_msgButtons = MessageBoxButtons.OK;
private MessageBoxIcon m_msgIcon = MessageBoxIcon.None;
@@ -54,12 +55,14 @@ namespace ModernKeePassLib.Utility
m_msgButtons = msgButtons;
m_msgIcon = msgIcon;
}
}
#endif
}
public static class MessageService
{
private static volatile uint m_uCurrentMessageCount = 0;
private static volatile uint m_uCurrentMessageCount = 0;
#if !ModernKeePassLib
#if !KeePassLibSD
private const MessageBoxIcon m_mbiInfo = MessageBoxIcon.Information;
private const MessageBoxIcon m_mbiWarning = MessageBoxIcon.Warning;
@@ -73,8 +76,8 @@ namespace ModernKeePassLib.Utility
private const MessageBoxIcon m_mbiFatal = MessageBoxIcon.Hand;
#endif
private const MessageBoxIcon m_mbiQuestion = MessageBoxIcon.Question;
public static string NewLine
#endif
public static string NewLine
{
#if !KeePassLibSD
get { return Environment.NewLine; }
@@ -123,7 +126,7 @@ namespace ModernKeePassLib.Utility
Exception exObj = (obj as Exception);
string strObj = (obj as string);
#if (!KeePassLibSD && !KeePassRT)
#if (!KeePassLibSD && !ModernKeePassLib)
StringCollection scObj = (obj as StringCollection);
#endif
@@ -131,10 +134,10 @@ namespace ModernKeePassLib.Utility
{
if(bFullExceptions)
strAppend = StrUtil.FormatException(exObj);
else if((exObj.Message != null) && (exObj.Message.Length > 0))
else if(!string.IsNullOrEmpty(exObj.Message))
strAppend = exObj.Message;
}
#if (!KeePassLibSD && !KeePassRT)
#if (!KeePassLibSD && !ModernKeePassLib)
else if(scObj != null)
{
StringBuilder sb = new StringBuilder();
@@ -146,7 +149,7 @@ namespace ModernKeePassLib.Utility
strAppend = sb.ToString();
}
#endif
else if(strObj != null)
else if (strObj != null)
strAppend = strObj;
else
strAppend = obj.ToString();
@@ -163,7 +166,7 @@ namespace ModernKeePassLib.Utility
return sbText.ToString();
}
#if (!KeePassLibSD && !KeePassRT)
#if (!KeePassLibSD && !ModernKeePassLib)
internal static Form GetTopForm()
{
FormCollection fc = Application.OpenForms;
@@ -173,8 +176,8 @@ namespace ModernKeePassLib.Utility
}
#endif
#if !KeePassUAP
internal static DialogResult SafeShowMessageBox(string strText, string strTitle,
#if !ModernKeePassLib
internal static DialogResult SafeShowMessageBox(string strText, string strTitle,
MessageBoxButtons mb, MessageBoxIcon mi, MessageBoxDefaultButton mdb)
{
#if (KeePassLibSD || KeePassRT)
@@ -405,7 +408,7 @@ namespace ModernKeePassLib.Utility
}
#endif // !KeePassUAP
internal static string GetLoadWarningMessage(string strFilePath,
internal static string GetLoadWarningMessage(string strFilePath,
Exception ex, bool bFullException)
{
string str = string.Empty;

View File

@@ -104,6 +104,9 @@ namespace ModernKeePassLib.Utility
// 1690:
// Removing items from a list view doesn't work properly.
// https://sourceforge.net/p/keepass/bugs/1690/
// 1716:
// 'Always on Top' doesn't work properly on the Cinnamon desktop.
// https://sourceforge.net/p/keepass/bugs/1716/
// 2139:
// Shortcut keys are ignored.
// https://sourceforge.net/p/keepass/feature-requests/2139/
@@ -560,7 +563,7 @@ namespace ModernKeePassLib.Utility
{
// Mono's WriteRecentlyUsedFiles method also loads the
// XML file using XmlDocument
XmlDocument xd = new XmlDocument();
XmlDocument xd = XmlUtilEx.CreateXmlDocument();
xd.Load(strFile);
}
catch(Exception) // The XML file is invalid

View File

@@ -227,7 +227,7 @@ namespace ModernKeePassLib.Utility
"Unicode (UTF-8)", StrUtil.Utf8, 1, new byte[] { 0xEF, 0xBB, 0xBF }));
#else
#if !KeePassLibSD
Encoding.Default.EncodingName,
Encoding.Default.EncodingName,
#else
Encoding.Default.WebName,
#endif
@@ -301,6 +301,28 @@ namespace ModernKeePassLib.Utility
return ("\\u" + sh.ToString(NumberFormatInfo.InvariantInfo) + "?");
}
public static string RtfFix(string strRtf)
{
if(strRtf == null) { Debug.Assert(false); return string.Empty; }
string str = strRtf;
// Workaround for .NET bug: the Rtf property of a RichTextBox
// can return an RTF text starting with "{\\urtf", but
// setting such an RTF text throws an exception (the setter
// checks for the RTF text to start with "{\\rtf");
// https://sourceforge.net/p/keepass/discussion/329221/thread/7788872f/
// https://www.microsoft.com/en-us/download/details.aspx?id=10725
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb774284.aspx
// https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/RichTextBox.cs
const string p = "{\\urtf"; // Typically "{\\urtf1\\ansi\\ansicpg65001"
if(str.StartsWith(p) && (str.Length > p.Length) &&
char.IsDigit(str[p.Length]))
str = str.Remove(2, 1); // Remove the 'u'
return str;
}
/// <summary>
/// Convert a string to a HTML sequence representing that string.
/// </summary>
@@ -324,7 +346,7 @@ namespace ModernKeePassLib.Utility
if(bNbsp) str = str.Replace(" ", @"&nbsp;"); // Before <br />
str = NormalizeNewLines(str, false);
str = str.Replace("\n", @"<br />" + Environment.NewLine);
str = str.Replace("\n", @"<br />" + MessageService.NewLine);
return str;
}
@@ -497,40 +519,40 @@ namespace ModernKeePassLib.Utility
{
string strText = string.Empty;
if(excp.Message != null)
strText += excp.Message + Environment.NewLine;
if(!string.IsNullOrEmpty(excp.Message))
strText += excp.Message + MessageService.NewLine;
#if !KeePassLibSD
if(excp.Source != null)
strText += excp.Source + Environment.NewLine;
if(!string.IsNullOrEmpty(excp.Source))
strText += excp.Source + MessageService.NewLine;
#endif
if(excp.StackTrace != null)
strText += excp.StackTrace + Environment.NewLine;
if(!string.IsNullOrEmpty(excp.StackTrace))
strText += excp.StackTrace + MessageService.NewLine;
#if !KeePassLibSD
#if !ModernKeePassLib && !KeePassRT
if(excp.TargetSite != null)
strText += excp.TargetSite.ToString() + Environment.NewLine;
strText += excp.TargetSite.ToString() + MessageService.NewLine;
#endif
if(excp.Data != null)
{
strText += Environment.NewLine;
strText += MessageService.NewLine;
foreach(DictionaryEntry de in excp.Data)
strText += @"'" + de.Key + @"' -> '" + de.Value + @"'" +
Environment.NewLine;
MessageService.NewLine;
}
#endif
if(excp.InnerException != null)
{
strText += Environment.NewLine + "Inner:" + Environment.NewLine;
if(excp.InnerException.Message != null)
strText += excp.InnerException.Message + Environment.NewLine;
strText += MessageService.NewLine + "Inner:" + MessageService.NewLine;
if(!string.IsNullOrEmpty(excp.InnerException.Message))
strText += excp.InnerException.Message + MessageService.NewLine;
#if !KeePassLibSD
if(excp.InnerException.Source != null)
strText += excp.InnerException.Source + Environment.NewLine;
if(!string.IsNullOrEmpty(excp.InnerException.Source))
strText += excp.InnerException.Source + MessageService.NewLine;
#endif
if(excp.InnerException.StackTrace != null)
strText += excp.InnerException.StackTrace + Environment.NewLine;
if(!string.IsNullOrEmpty(excp.InnerException.StackTrace))
strText += excp.InnerException.StackTrace + MessageService.NewLine;
#if !KeePassLibSD
#if !ModernKeePassLib && !KeePassRT
if(excp.InnerException.TargetSite != null)
@@ -539,10 +561,10 @@ namespace ModernKeePassLib.Utility
if(excp.InnerException.Data != null)
{
strText += Environment.NewLine;
strText += MessageService.NewLine;
foreach(DictionaryEntry de in excp.InnerException.Data)
strText += @"'" + de.Key + @"' -> '" + de.Value + @"'" +
Environment.NewLine;
MessageService.NewLine;
}
#endif
}
@@ -1140,32 +1162,58 @@ namespace ModernKeePassLib.Utility
return str;
}
private static char[] m_vNewLineChars = null;
public static void NormalizeNewLines(ProtectedStringDictionary dict,
bool bWindows)
{
if(dict == null) { Debug.Assert(false); return; }
if(m_vNewLineChars == null)
m_vNewLineChars = new char[]{ '\r', '\n' };
List<string> vKeys = dict.GetKeys();
foreach(string strKey in vKeys)
List<string> lKeys = dict.GetKeys();
foreach(string strKey in lKeys)
{
ProtectedString ps = dict.Get(strKey);
if(ps == null) { Debug.Assert(false); continue; }
string strValue = ps.ReadString();
if(strValue.IndexOfAny(m_vNewLineChars) < 0) continue;
dict.Set(strKey, new ProtectedString(ps.IsProtected,
NormalizeNewLines(strValue, bWindows)));
char[] v = ps.ReadChars();
if(!IsNewLineNormalized(v, bWindows))
dict.Set(strKey, new ProtectedString(ps.IsProtected,
NormalizeNewLines(ps.ReadString(), bWindows)));
MemUtil.ZeroArray<char>(v);
}
}
internal static bool IsNewLineNormalized(char[] v, bool bWindows)
{
if(v == null) { Debug.Assert(false); return true; }
if(bWindows)
{
int iFreeCr = -2; // Must be < -1 (for test "!= (i - 1)")
for(int i = 0; i < v.Length; ++i)
{
char ch = v[i];
if(ch == '\r')
{
if(iFreeCr >= 0) return false;
iFreeCr = i;
}
else if(ch == '\n')
{
if(iFreeCr != (i - 1)) return false;
iFreeCr = -2; // Consume \r
}
}
return (iFreeCr < 0); // Ensure no \r at end
}
return (Array.IndexOf<char>(v, '\r') < 0);
}
public static string GetNewLineSeq(string str)
{
if(str == null) { Debug.Assert(false); return Environment.NewLine; }
if(str == null) { Debug.Assert(false); return MessageService.NewLine; }
int n = str.Length, nLf = 0, nCr = 0, nCrLf = 0;
char chLast = char.MinValue;
@@ -1187,7 +1235,7 @@ namespace ModernKeePassLib.Utility
nLf -= nCrLf;
int nMax = Math.Max(nCrLf, Math.Max(nCr, nLf));
if(nMax == 0) return Environment.NewLine;
if(nMax == 0) return MessageService.NewLine;
if(nCrLf == nMax) return "\r\n";
return ((nLf == nMax) ? "\n" : "\r");
@@ -1319,7 +1367,7 @@ namespace ModernKeePassLib.Utility
try
{
byte[] pbPlain = StrUtil.Utf8.GetBytes(strPlainText);
byte[] pbEnc = ProtectedData.Protect(pbPlain, m_pbOptEnt,
byte[] pbEnc = CryptoUtil.ProtectData(pbPlain, m_pbOptEnt,
DataProtectionScope.CurrentUser);
#if (!ModernKeePassLib && !KeePassLibSD && !KeePassRT)
@@ -1340,7 +1388,7 @@ namespace ModernKeePassLib.Utility
try
{
byte[] pbEnc = Convert.FromBase64String(strCipherText);
byte[] pbPlain = ProtectedData.Unprotect(pbEnc, m_pbOptEnt,
byte[] pbPlain = CryptoUtil.UnprotectData(pbEnc, m_pbOptEnt,
DataProtectionScope.CurrentUser);
return StrUtil.Utf8.GetString(pbPlain, 0, pbPlain.Length);

View File

@@ -0,0 +1,65 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2018 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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using ModernKeePassLib.Delegates;
namespace KeePassLib.Utility
{
public static class TypeOverridePool
{
private static Dictionary<Type, GFunc<object>> g_d =
new Dictionary<Type, GFunc<object>>();
public static void Register(Type t, GFunc<object> f)
{
if(t == null) throw new ArgumentNullException("t");
if(f == null) throw new ArgumentNullException("f");
g_d[t] = f;
}
public static void Unregister(Type t)
{
if(t == null) throw new ArgumentNullException("t");
g_d.Remove(t);
}
public static bool IsRegistered(Type t)
{
if(t == null) throw new ArgumentNullException("t");
return g_d.ContainsKey(t);
}
public static T CreateInstance<T>()
where T : new()
{
GFunc<object> f;
if(g_d.TryGetValue(typeof(T), out f))
return (T)(f());
return new T();
}
}
}

View File

@@ -299,7 +299,7 @@ namespace ModernKeePassLib.Utility
else // Unhide
{
fa &= ~FileAttributes.Hidden;
if((long)fa == 0) fa |= FileAttributes.Normal;
if((long)fa == 0) fa = FileAttributes.Normal;
}
File.SetAttributes(strFile, fa);
@@ -635,13 +635,12 @@ namespace ModernKeePassLib.Utility
return false;
}
#if !ModernKeePassLib
public static string GetTempPath()
{
string strDir;
if(NativeLib.IsUnix())
strDir = NativeMethods.GetUserRuntimeDir();
#if KeePassRT
#if ModernKeePassLib
else strDir = Windows.Storage.ApplicationData.Current.TemporaryFolder.Path;
#else
else strDir = Path.GetTempPath();
@@ -655,7 +654,6 @@ namespace ModernKeePassLib.Utility
return strDir;
}
#endif
#if !ModernKeePassLib && !KeePassLibSD
// Structurally mostly equivalent to UrlUtil.GetFileInfos
@@ -779,5 +777,17 @@ namespace ModernKeePassLib.Utility
return str;
}
public static char GetDriveLetter(string strPath)
{
if(strPath == null) throw new ArgumentNullException("strPath");
Debug.Assert(default(char) == '\0');
if(strPath.Length < 3) return '\0';
if((strPath[1] != ':') || (strPath[2] != '\\')) return '\0';
char ch = char.ToUpperInvariant(strPath[0]);
return (((ch >= 'A') && (ch <= 'Z')) ? ch : '\0');
}
}
}

View File

@@ -0,0 +1,127 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2018 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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Windows.Data.Xml.Dom;
namespace ModernKeePassLib.Utility
{
public static class XmlUtilEx
{
public static XmlDocument CreateXmlDocument()
{
XmlDocument d = new XmlDocument();
// .NET 4.5.2 and newer do not resolve external XML resources
// by default; for older .NET versions, we explicitly
// prevent resolving
#if !ModernKeePassLib
d.XmlResolver = null; // Default in old .NET: XmlUrlResolver object
#endif
return d;
}
public static XmlReaderSettings CreateXmlReaderSettings()
{
XmlReaderSettings xrs = new XmlReaderSettings();
xrs.CloseInput = false;
xrs.IgnoreComments = true;
xrs.IgnoreProcessingInstructions = true;
xrs.IgnoreWhitespace = true;
#if KeePassUAP || ModernKeePassLib
xrs.DtdProcessing = DtdProcessing.Prohibit;
#else
// Also see PrepMonoDev.sh script
xrs.ProhibitDtd = true; // Obsolete in .NET 4, but still there
// xrs.DtdProcessing = DtdProcessing.Prohibit; // .NET 4 only
xrs.ValidationType = ValidationType.None;
xrs.XmlResolver = null;
#endif
return xrs;
}
public static XmlReader CreateXmlReader(Stream s)
{
if(s == null) { Debug.Assert(false); throw new ArgumentNullException("s"); }
return XmlReader.Create(s, CreateXmlReaderSettings());
}
public static XmlWriterSettings CreateXmlWriterSettings(bool isVersionGreaterThan4 = false)
{
XmlWriterSettings xws = new XmlWriterSettings();
xws.CloseOutput = isVersionGreaterThan4;
xws.Encoding = StrUtil.Utf8;
xws.Indent = true;
xws.IndentChars = "\t";
xws.NewLineOnAttributes = false;
#if ModernKeePassLib
// This is needed for Argon2Kdf write
xws.Async = true;
#endif
return xws;
}
public static XmlWriter CreateXmlWriter(Stream s, bool isVersionGreaterThan4 = false)
{
if(s == null) { Debug.Assert(false); throw new ArgumentNullException("s"); }
return XmlWriter.Create(s, CreateXmlWriterSettings(isVersionGreaterThan4));
}
public static void Serialize<T>(Stream s, T t)
{
if(s == null) { Debug.Assert(false); throw new ArgumentNullException("s"); }
XmlSerializer xs = new XmlSerializer(typeof(T));
using(XmlWriter xw = CreateXmlWriter(s))
{
xs.Serialize(xw, t);
}
}
public static T Deserialize<T>(Stream s)
{
if(s == null) { Debug.Assert(false); throw new ArgumentNullException("s"); }
XmlSerializer xs = new XmlSerializer(typeof(T));
T t = default(T);
using(XmlReader xr = CreateXmlReader(s))
{
t = (T)xs.Deserialize(xr);
}
return t;
}
}
}