mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-12-22 06:58:50 -05:00
Keepass lib 2.35
This commit is contained in:
parent
a2f2e3d6f8
commit
26c0fde41c
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
174
src/KeePassLib2Android/Collections/ProtectedBinarySet.cs
Normal file
174
src/KeePassLib2Android/Collections/ProtectedBinarySet.cs
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
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
|
||||
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;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using KeePassLib.Delegates;
|
||||
using KeePassLib.Security;
|
||||
|
||||
namespace KeePassLib.Collections
|
||||
{
|
||||
internal sealed class ProtectedBinarySet : IEnumerable<KeyValuePair<int, ProtectedBinary>>
|
||||
{
|
||||
private Dictionary<int, ProtectedBinary> m_d =
|
||||
new Dictionary<int, ProtectedBinary>();
|
||||
|
||||
public ProtectedBinarySet()
|
||||
{
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return m_d.GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<int, ProtectedBinary>> GetEnumerator()
|
||||
{
|
||||
return m_d.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
m_d.Clear();
|
||||
}
|
||||
|
||||
private int GetFreeID()
|
||||
{
|
||||
int i = m_d.Count;
|
||||
while(m_d.ContainsKey(i)) { ++i; }
|
||||
Debug.Assert(i == m_d.Count); // m_d.Count should be free
|
||||
return i;
|
||||
}
|
||||
|
||||
public ProtectedBinary Get(int iID)
|
||||
{
|
||||
ProtectedBinary pb;
|
||||
if(m_d.TryGetValue(iID, out pb)) return pb;
|
||||
|
||||
// Debug.Assert(false); // No assert
|
||||
return null;
|
||||
}
|
||||
|
||||
public int Find(ProtectedBinary pb)
|
||||
{
|
||||
if(pb == null) { Debug.Assert(false); return -1; }
|
||||
|
||||
// Fast search by reference
|
||||
foreach(KeyValuePair<int, ProtectedBinary> kvp in m_d)
|
||||
{
|
||||
if(object.ReferenceEquals(pb, kvp.Value))
|
||||
{
|
||||
Debug.Assert(pb.Equals(kvp.Value));
|
||||
return kvp.Key;
|
||||
}
|
||||
}
|
||||
|
||||
// Slow search by content
|
||||
foreach(KeyValuePair<int, ProtectedBinary> kvp in m_d)
|
||||
{
|
||||
if(pb.Equals(kvp.Value)) return kvp.Key;
|
||||
}
|
||||
|
||||
// Debug.Assert(false); // No assert
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void Set(int iID, ProtectedBinary pb)
|
||||
{
|
||||
if(iID < 0) { Debug.Assert(false); return; }
|
||||
if(pb == null) { Debug.Assert(false); return; }
|
||||
|
||||
m_d[iID] = pb;
|
||||
}
|
||||
|
||||
public void Add(ProtectedBinary pb)
|
||||
{
|
||||
if(pb == null) { Debug.Assert(false); return; }
|
||||
|
||||
int i = Find(pb);
|
||||
if(i >= 0) return; // Exists already
|
||||
|
||||
i = GetFreeID();
|
||||
m_d[i] = pb;
|
||||
}
|
||||
|
||||
public void AddFrom(ProtectedBinaryDictionary d)
|
||||
{
|
||||
if(d == null) { Debug.Assert(false); return; }
|
||||
|
||||
foreach(KeyValuePair<string, ProtectedBinary> kvp in d)
|
||||
{
|
||||
Add(kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFrom(PwGroup pg)
|
||||
{
|
||||
if(pg == null) { Debug.Assert(false); return; }
|
||||
|
||||
EntryHandler eh = delegate(PwEntry pe)
|
||||
{
|
||||
if(pe == null) { Debug.Assert(false); return true; }
|
||||
|
||||
AddFrom(pe.Binaries);
|
||||
foreach(PwEntry peHistory in pe.History)
|
||||
{
|
||||
if(peHistory == null) { Debug.Assert(false); continue; }
|
||||
AddFrom(peHistory.Binaries);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
pg.TraverseTree(TraversalMethod.PreOrder, null, eh);
|
||||
}
|
||||
|
||||
public ProtectedBinary[] ToArray()
|
||||
{
|
||||
int n = m_d.Count;
|
||||
ProtectedBinary[] v = new ProtectedBinary[n];
|
||||
|
||||
foreach(KeyValuePair<int, ProtectedBinary> kvp in m_d)
|
||||
{
|
||||
if((kvp.Key < 0) || (kvp.Key >= n))
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
v[kvp.Key] = kvp.Value;
|
||||
}
|
||||
|
||||
for(int i = 0; i < n; ++i)
|
||||
{
|
||||
if(v[i] == null)
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -20,11 +20,12 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using KeePassLib.Delegates;
|
||||
using KeePassLib.Interfaces;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
#if KeePassLibSD
|
||||
using KeePassLibSD;
|
||||
@ -182,7 +183,7 @@ namespace KeePassLib.Collections
|
||||
get { return ((m_l.Count > 0) ? m_l[0] : null); }
|
||||
}
|
||||
|
||||
private DateTime m_dtLocationChanged = DateTime.MinValue;
|
||||
private DateTime m_dtLocationChanged = TimeUtil.SafeMinValueUtc;
|
||||
public DateTime LocationChanged
|
||||
{
|
||||
get { return m_dtLocationChanged; }
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -106,9 +106,12 @@ namespace KeePassLib.Cryptography.Cipher
|
||||
}
|
||||
|
||||
protected override void Dispose(bool bDisposing)
|
||||
{
|
||||
if(bDisposing)
|
||||
{
|
||||
MemUtil.ZeroArray<uint>(m_s);
|
||||
MemUtil.ZeroArray<uint>(m_x);
|
||||
}
|
||||
|
||||
base.Dispose(bDisposing);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -115,8 +115,8 @@ namespace KeePassLib.Cryptography.Cipher
|
||||
|
||||
protected override void Dispose(bool bDisposing)
|
||||
{
|
||||
if(!bDisposing) return;
|
||||
|
||||
if(bDisposing)
|
||||
{
|
||||
if(m_sBase != null)
|
||||
{
|
||||
m_c.Dispose();
|
||||
@ -129,6 +129,9 @@ namespace KeePassLib.Cryptography.Cipher
|
||||
m_pbBuffer = null;
|
||||
}
|
||||
|
||||
base.Dispose(bDisposing);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
Debug.Assert(m_sBase != null);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -52,10 +52,13 @@ namespace KeePassLib.Cryptography.Cipher
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool bDisposing)
|
||||
{
|
||||
if(bDisposing)
|
||||
{
|
||||
MemUtil.ZeroByteArray(m_pBlock);
|
||||
m_iBlockPos = m_pBlock.Length;
|
||||
}
|
||||
}
|
||||
|
||||
protected void InvalidateBlock()
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -71,9 +71,12 @@ namespace KeePassLib.Cryptography.Cipher
|
||||
}
|
||||
|
||||
protected override void Dispose(bool bDisposing)
|
||||
{
|
||||
if(bDisposing)
|
||||
{
|
||||
MemUtil.ZeroArray<uint>(m_s);
|
||||
MemUtil.ZeroArray<uint>(m_x);
|
||||
}
|
||||
|
||||
base.Dispose(bDisposing);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -18,7 +18,10 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
#if !KeePassUAP
|
||||
@ -33,8 +36,8 @@ using KeePassLib.Utility;
|
||||
namespace KeePassLib.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Cryptographically strong random number generator. The returned
|
||||
/// values are unpredictable and cannot be reproduced.
|
||||
/// Cryptographically secure pseudo-random number generator.
|
||||
/// The returned values are unpredictable and cannot be reproduced.
|
||||
/// <c>CryptoRandom</c> is a singleton class.
|
||||
/// </summary>
|
||||
public sealed class CryptoRandom
|
||||
@ -90,12 +93,13 @@ namespace KeePassLib.Cryptography
|
||||
|
||||
private CryptoRandom()
|
||||
{
|
||||
Random rWeak = new Random();
|
||||
byte[] pb = new byte[8];
|
||||
rWeak.NextBytes(pb);
|
||||
m_uCounter = MemUtil.BytesToUInt64(pb);
|
||||
// Random rWeak = new Random(); // Based on tick count
|
||||
// byte[] pb = new byte[8];
|
||||
// rWeak.NextBytes(pb);
|
||||
// m_uCounter = MemUtil.BytesToUInt64(pb);
|
||||
m_uCounter = (ulong)DateTime.UtcNow.ToBinary();
|
||||
|
||||
AddEntropy(GetSystemData(rWeak));
|
||||
AddEntropy(GetSystemData());
|
||||
AddEntropy(GetCspData());
|
||||
}
|
||||
|
||||
@ -147,7 +151,7 @@ namespace KeePassLib.Cryptography
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] GetSystemData(Random rWeak)
|
||||
private static byte[] GetSystemData()
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
byte[] pb;
|
||||
@ -172,32 +176,40 @@ namespace KeePassLib.Cryptography
|
||||
catch(Exception) { }
|
||||
#endif
|
||||
|
||||
pb = MemUtil.Int32ToBytes(rWeak.Next());
|
||||
MemUtil.Write(ms, pb);
|
||||
|
||||
pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID());
|
||||
MemUtil.Write(ms, pb);
|
||||
|
||||
try
|
||||
{
|
||||
#if KeePassUAP
|
||||
string strOS = EnvironmentExt.OSVersion.VersionString;
|
||||
#else
|
||||
string strOS = Environment.OSVersion.VersionString;
|
||||
#endif
|
||||
AddStrHash(ms, strOS);
|
||||
|
||||
pb = MemUtil.Int32ToBytes(Environment.ProcessorCount);
|
||||
MemUtil.Write(ms, pb);
|
||||
|
||||
#if KeePassUAP
|
||||
Version v = EnvironmentExt.OSVersion.Version;
|
||||
#else
|
||||
Version v = Environment.OSVersion.Version;
|
||||
#endif
|
||||
pb = MemUtil.Int32ToBytes(v.GetHashCode());
|
||||
MemUtil.Write(ms, pb);
|
||||
|
||||
#if !KeePassUAP
|
||||
AddStrHash(ms, Environment.CommandLine);
|
||||
|
||||
pb = MemUtil.Int64ToBytes(Environment.WorkingSet);
|
||||
MemUtil.Write(ms, pb);
|
||||
#endif
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
try
|
||||
{
|
||||
foreach(DictionaryEntry de in Environment.GetEnvironmentVariables())
|
||||
{
|
||||
AddStrHash(ms, (de.Key as string));
|
||||
AddStrHash(ms, (de.Value as string));
|
||||
}
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
#if KeePassUAP
|
||||
pb = DiagnosticsExt.GetProcessEntropy();
|
||||
MemUtil.Write(ms, pb);
|
||||
@ -246,6 +258,18 @@ namespace KeePassLib.Cryptography
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
CultureInfo ci = CultureInfo.CurrentCulture;
|
||||
if(ci != null)
|
||||
{
|
||||
pb = MemUtil.Int32ToBytes(ci.GetHashCode());
|
||||
MemUtil.Write(ms, pb);
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
pb = Guid.NewGuid().ToByteArray();
|
||||
MemUtil.Write(ms, pb);
|
||||
|
||||
@ -254,6 +278,16 @@ namespace KeePassLib.Cryptography
|
||||
return pbAll;
|
||||
}
|
||||
|
||||
private static void AddStrHash(Stream s, string str)
|
||||
{
|
||||
if(s == null) { Debug.Assert(false); return; }
|
||||
if(string.IsNullOrEmpty(str)) return;
|
||||
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(str);
|
||||
byte[] pbHash = CryptoUtil.HashSha256(pbUtf8);
|
||||
MemUtil.Write(s, pbHash);
|
||||
}
|
||||
|
||||
private byte[] GetCspData()
|
||||
{
|
||||
byte[] pbCspRandom = new byte[32];
|
||||
@ -318,7 +352,7 @@ namespace KeePassLib.Cryptography
|
||||
byte[] pbRandom256 = GenerateRandom256();
|
||||
Debug.Assert(pbRandom256.Length == 32);
|
||||
|
||||
int cbCopy = Math.Min(cbRem, 32);
|
||||
int cbCopy = Math.Min(cbRem, pbRandom256.Length);
|
||||
Array.Copy(pbRandom256, 0, pbRes, iPos, cbCopy);
|
||||
|
||||
MemUtil.ZeroByteArray(pbRandom256);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -64,7 +64,7 @@ namespace KeePassLib.Cryptography
|
||||
/// properties, but for the same seed always the same stream
|
||||
/// is produced, i.e. this class can be used as stream cipher.
|
||||
/// </summary>
|
||||
public sealed class CryptoRandomStream
|
||||
public sealed class CryptoRandomStream : IDisposable
|
||||
{
|
||||
private readonly CrsAlgorithm m_crsAlgorithm;
|
||||
|
||||
@ -149,6 +149,30 @@ namespace KeePassLib.Cryptography
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing)
|
||||
{
|
||||
if(m_crsAlgorithm == CrsAlgorithm.ChaCha20)
|
||||
m_chacha20.Dispose();
|
||||
else if(m_crsAlgorithm == CrsAlgorithm.Salsa20)
|
||||
m_salsa20.Dispose();
|
||||
else if(m_crsAlgorithm == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
MemUtil.ZeroByteArray(m_pbState);
|
||||
m_i = 0;
|
||||
m_j = 0;
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get <paramref name="uRequestedCount" /> random bytes.
|
||||
/// </summary>
|
||||
@ -220,9 +244,11 @@ namespace KeePassLib.Cryptography
|
||||
int nStart = Environment.TickCount;
|
||||
for(int i = 0; i < nRounds; ++i)
|
||||
{
|
||||
CryptoRandomStream c = new CryptoRandomStream(cra, pbKey);
|
||||
using(CryptoRandomStream c = new CryptoRandomStream(cra, pbKey))
|
||||
{
|
||||
c.GetRandomBytes((uint)nDataSize);
|
||||
}
|
||||
}
|
||||
int nEnd = Environment.TickCount;
|
||||
|
||||
return (nEnd - nStart);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -20,9 +20,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
#if !KeePassUAP
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Cryptography
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -23,9 +23,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
#if !KeePassUAP
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Cryptography.Hash
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -33,7 +33,7 @@ namespace KeePassLib.Cryptography
|
||||
{
|
||||
public sealed class HashingStreamEx : Stream
|
||||
{
|
||||
private Stream m_sBaseStream;
|
||||
private readonly Stream m_sBaseStream;
|
||||
private readonly bool m_bWriting;
|
||||
private HashAlgorithm m_hash;
|
||||
|
||||
@ -97,19 +97,10 @@ namespace KeePassLib.Cryptography
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
m_sBaseStream.Flush();
|
||||
}
|
||||
|
||||
#if KeePassUAP
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(!disposing) return;
|
||||
#else
|
||||
public override void Close()
|
||||
if(disposing)
|
||||
{
|
||||
#endif
|
||||
if(m_hash != null)
|
||||
{
|
||||
try
|
||||
@ -126,6 +117,14 @@ namespace KeePassLib.Cryptography
|
||||
m_sBaseStream.Close();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
m_sBaseStream.Flush();
|
||||
}
|
||||
|
||||
public override long Seek(long lOffset, SeekOrigin soOrigin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -77,6 +77,16 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
||||
public ulong Lane = 0;
|
||||
public ulong Slice = 0;
|
||||
public ulong Index = 0;
|
||||
|
||||
public void Release()
|
||||
{
|
||||
if(this.Finished != null)
|
||||
{
|
||||
this.Finished.Close();
|
||||
this.Finished = null;
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] Argon2d(byte[] pbMsg, byte[] pbSalt, uint uParallel,
|
||||
@ -104,7 +114,12 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
||||
ctx.LaneLength = ctx.SegmentLength * NbSyncPoints;
|
||||
|
||||
Debug.Assert(NbBlockSize == (NbBlockSizeInQW *
|
||||
(ulong)Marshal.SizeOf(typeof(ulong))));
|
||||
#if KeePassUAP
|
||||
(ulong)Marshal.SizeOf<ulong>()
|
||||
#else
|
||||
(ulong)Marshal.SizeOf(typeof(ulong))
|
||||
#endif
|
||||
));
|
||||
ctx.Mem = new ulong[ctx.MemoryBlocks * NbBlockSizeInQW];
|
||||
|
||||
Blake2b h = new Blake2b();
|
||||
@ -186,8 +201,13 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
||||
// for(int i = 0; i < (int)NbBlockSizeInQW; ++i)
|
||||
// vDst[iDstOffset + i] = vSrc[iSrcOffset + i];
|
||||
|
||||
#if KeePassUAP
|
||||
Array.Copy(vSrc, (int)uSrcOffset, vDst, (int)uDstOffset,
|
||||
(int)NbBlockSizeInQW);
|
||||
#else
|
||||
Array.Copy(vSrc, (long)uSrcOffset, vDst, (long)uDstOffset,
|
||||
(long)NbBlockSizeInQW);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void XorBlock(ulong[] vDst, ulong uDstOffset, ulong[] vSrc,
|
||||
@ -456,7 +476,10 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
||||
}
|
||||
|
||||
for(int l = 0; l < np; ++l)
|
||||
{
|
||||
v[l].Finished.WaitOne();
|
||||
v[l].Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -47,7 +47,7 @@ namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
|
||||
if(ch == char.MinValue)
|
||||
{
|
||||
Array.Clear(vGenerated, 0, vGenerated.Length);
|
||||
MemUtil.ZeroArray<char>(vGenerated);
|
||||
return PwgError.TooFewCharacters;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vGenerated);
|
||||
psOut = new ProtectedString(true, pbUtf8);
|
||||
MemUtil.ZeroByteArray(pbUtf8);
|
||||
Array.Clear(vGenerated, 0, vGenerated.Length);
|
||||
MemUtil.ZeroArray<char>(vGenerated);
|
||||
|
||||
return PwgError.Success;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -132,7 +132,7 @@ namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vArray);
|
||||
psOut = new ProtectedString(true, pbUtf8);
|
||||
MemUtil.ZeroByteArray(pbUtf8);
|
||||
Array.Clear(vArray, 0, vArray.Length);
|
||||
MemUtil.ZeroArray<char>(vArray);
|
||||
vGenerated.Clear();
|
||||
|
||||
return PwgError.Success;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -20,9 +20,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
#if !KeePassUAP
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
using KeePassLib.Security;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
@ -48,8 +51,12 @@ namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
Debug.Assert(pwProfile != null);
|
||||
if(pwProfile == null) throw new ArgumentNullException("pwProfile");
|
||||
|
||||
CryptoRandomStream crs = CreateCryptoStream(pbUserEntropy);
|
||||
PwgError e = PwgError.Unknown;
|
||||
CryptoRandomStream crs = null;
|
||||
byte[] pbKey = null;
|
||||
try
|
||||
{
|
||||
crs = CreateRandomStream(pbUserEntropy, out pbKey);
|
||||
|
||||
if(pwProfile.GeneratorType == PasswordGeneratorType.CharSet)
|
||||
e = CharSetBasedGenerator.Generate(out psOut, pwProfile, crs);
|
||||
@ -58,13 +65,20 @@ namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
else if(pwProfile.GeneratorType == PasswordGeneratorType.Custom)
|
||||
e = GenerateCustom(out psOut, pwProfile, crs, pwAlgorithmPool);
|
||||
else { Debug.Assert(false); psOut = ProtectedString.Empty; }
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(crs != null) crs.Dispose();
|
||||
if(pbKey != null) MemUtil.ZeroByteArray(pbKey);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
private static CryptoRandomStream CreateCryptoStream(byte[] pbAdditionalEntropy)
|
||||
private static CryptoRandomStream CreateRandomStream(byte[] pbAdditionalEntropy,
|
||||
out byte[] pbKey)
|
||||
{
|
||||
byte[] pbKey = CryptoRandom.Instance.GetRandomBytes(128);
|
||||
pbKey = CryptoRandom.Instance.GetRandomBytes(128);
|
||||
|
||||
// Mix in additional entropy
|
||||
Debug.Assert(pbKey.Length >= 64);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -265,7 +265,7 @@ namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
else pcs.Add(ch);
|
||||
}
|
||||
|
||||
Array.Clear(vChars, 0, vChars.Length);
|
||||
MemUtil.ZeroArray<char>(vChars);
|
||||
MemUtil.ZeroByteArray(pbUtf8);
|
||||
return pp;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -422,7 +422,7 @@ namespace KeePassLib.Cryptography
|
||||
|
||||
char[] vChars = StrUtil.Utf8.GetChars(pbUnprotectedUtf8);
|
||||
uint uResult = EstimatePasswordBits(vChars);
|
||||
Array.Clear(vChars, 0, vChars.Length);
|
||||
MemUtil.ZeroArray<char>(vChars);
|
||||
|
||||
return uResult;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -688,6 +688,15 @@ namespace KeePassLib.Cryptography
|
||||
byte[] pbHash = h.Hash;
|
||||
if(!MemUtil.ArraysEqual(pbHash, pbExpc))
|
||||
throw new SecurityException("HMAC-SHA-256-" + strID);
|
||||
|
||||
// Reuse the object
|
||||
h.Initialize();
|
||||
h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0);
|
||||
h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0);
|
||||
|
||||
pbHash = h.Hash;
|
||||
if(!MemUtil.ArraysEqual(pbHash, pbExpc))
|
||||
throw new SecurityException("HMAC-SHA-256-" + strID + "-R");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -27,7 +27,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Dominik Reichl")]
|
||||
[assembly: AssemblyProduct("KeePassLib")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2003-2016 Dominik Reichl")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2003-2017 Dominik Reichl")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@ -38,5 +38,5 @@ using System.Runtime.InteropServices;
|
||||
[assembly: Guid("395f6eec-a1e0-4438-aa82-b75099348134")]
|
||||
|
||||
// Assembly version information
|
||||
[assembly: AssemblyVersion("2.34.0.*")]
|
||||
[assembly: AssemblyFileVersion("2.34.0.0")]
|
||||
[assembly: AssemblyVersion("2.35.0.*")]
|
||||
[assembly: AssemblyFileVersion("2.35.0.0")]
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -34,10 +34,10 @@ namespace KeePassLib
|
||||
/// </summary>
|
||||
public sealed class PwCustomIcon
|
||||
{
|
||||
private PwUuid m_pwUuid;
|
||||
private byte[] m_pbImageDataPng;
|
||||
private readonly PwUuid m_pwUuid;
|
||||
private readonly byte[] m_pbImageDataPng;
|
||||
|
||||
private Image m_imgOrg = null;
|
||||
private readonly Image m_imgOrg;
|
||||
private Dictionary<long, Image> m_dImageCache = new Dictionary<long, Image>();
|
||||
|
||||
// Recommended maximum sizes, not obligatory
|
||||
@ -80,7 +80,7 @@ namespace KeePassLib
|
||||
// m_imgOrg = Image.FromStream(ms);
|
||||
// ms.Close();
|
||||
try { m_imgOrg = GfxUtil.LoadImage(m_pbImageDataPng); }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
catch(Exception) { Debug.Assert(false); m_imgOrg = null; }
|
||||
|
||||
if(m_imgOrg != null)
|
||||
m_dImageCache[GetID(m_imgOrg.Width, m_imgOrg.Height)] =
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -79,6 +79,7 @@ namespace KeePassLib
|
||||
private DateTime m_dtKeyLastChanged = PwDefs.DtDefaultNow;
|
||||
private long m_lKeyChangeRecDays = -1;
|
||||
private long m_lKeyChangeForceDays = -1;
|
||||
private bool m_bKeyChangeForceOnce = false;
|
||||
|
||||
private IOConnectionInfo m_ioSource = new IOConnectionInfo();
|
||||
private bool m_bDatabaseOpened = false;
|
||||
@ -269,6 +270,12 @@ namespace KeePassLib
|
||||
set { m_lKeyChangeForceDays = value; }
|
||||
}
|
||||
|
||||
public bool MasterKeyChangeForceOnce
|
||||
{
|
||||
get { return m_bKeyChangeForceOnce; }
|
||||
set { m_bKeyChangeForceOnce = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The encryption algorithm used to encrypt the data part of the database.
|
||||
/// </summary>
|
||||
@ -535,7 +542,7 @@ namespace KeePassLib
|
||||
m_vCustomIcons = new List<PwCustomIcon>();
|
||||
m_bUINeedsIconUpdate = true;
|
||||
|
||||
DateTime dtNow = DateTime.Now;
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
|
||||
m_dtSettingsChanged = dtNow;
|
||||
m_strName = string.Empty;
|
||||
@ -550,6 +557,7 @@ namespace KeePassLib
|
||||
m_dtKeyLastChanged = dtNow;
|
||||
m_lKeyChangeRecDays = -1;
|
||||
m_lKeyChangeForceDays = -1;
|
||||
m_bKeyChangeForceOnce = false;
|
||||
|
||||
m_ioSource = new IOConnectionInfo();
|
||||
m_bDatabaseOpened = false;
|
||||
@ -1314,7 +1322,7 @@ namespace KeePassLib
|
||||
where T : class, ITimeLogger, IStructureItem, IDeepCloneable<T>
|
||||
{
|
||||
PwObjectPoolEx p = null;
|
||||
dtLoc = DateTime.MinValue;
|
||||
dtLoc = TimeUtil.SafeMinValueUtc;
|
||||
|
||||
IStructureItem ptOrg = ppOrg.GetItemByUuid(t.Uuid);
|
||||
if(ptOrg != null)
|
||||
@ -1341,7 +1349,7 @@ namespace KeePassLib
|
||||
pPool = null;
|
||||
|
||||
int iPosMax = kvpRange.Key;
|
||||
DateTime dtMax = DateTime.MinValue;
|
||||
DateTime dtMax = TimeUtil.SafeMinValueUtc;
|
||||
|
||||
for(int i = kvpRange.Key; i <= kvpRange.Value; ++i)
|
||||
{
|
||||
@ -1879,7 +1887,7 @@ namespace KeePassLib
|
||||
if(m_bUseRecycleBin)
|
||||
pgRecycleBin = m_pgRootGroup.FindGroup(m_pwRecycleBin, true);
|
||||
|
||||
DateTime dtNow = DateTime.Now;
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
PwObjectList<PwEntry> l = m_pgRootGroup.GetEntries(true);
|
||||
int i = 0;
|
||||
while(true)
|
||||
@ -2004,7 +2012,7 @@ namespace KeePassLib
|
||||
if((pg.Groups.UCount > 0) || (pg.Entries.UCount > 0)) continue;
|
||||
|
||||
pg.ParentGroup.Groups.Remove(pg);
|
||||
m_vDeletedObjects.Add(new PwDeletedObject(pg.Uuid, DateTime.Now));
|
||||
m_vDeletedObjects.Add(new PwDeletedObject(pg.Uuid, DateTime.UtcNow));
|
||||
|
||||
++uDeleted;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -55,20 +55,20 @@ namespace KeePassLib
|
||||
/// e.g. 2.19 = 0x02130000.
|
||||
/// It is highly recommended to use <c>FileVersion64</c> instead.
|
||||
/// </summary>
|
||||
public const uint Version32 = 0x02220000;
|
||||
public const uint Version32 = 0x02230000;
|
||||
|
||||
/// <summary>
|
||||
/// Version, encoded as 64-bit unsigned integer
|
||||
/// (component-wise, 16 bits per component).
|
||||
/// </summary>
|
||||
public const ulong FileVersion64 = 0x0002002200000000UL;
|
||||
public const ulong FileVersion64 = 0x0002002300000000UL;
|
||||
|
||||
/// <summary>
|
||||
/// Version, encoded as string.
|
||||
/// </summary>
|
||||
public const string VersionString = "2.34";
|
||||
public const string VersionString = "2.35";
|
||||
|
||||
public const string Copyright = @"Copyright © 2003-2016 Dominik Reichl";
|
||||
public const string Copyright = @"Copyright © 2003-2017 Dominik Reichl";
|
||||
|
||||
/// <summary>
|
||||
/// Product website URL. Terminated by a forward slash.
|
||||
@ -107,10 +107,11 @@ namespace KeePassLib
|
||||
/// A <c>DateTime</c> object that represents the time when the assembly
|
||||
/// was loaded.
|
||||
/// </summary>
|
||||
public static readonly DateTime DtDefaultNow = DateTime.Now;
|
||||
public static readonly DateTime DtDefaultNow = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// Default number of master key encryption/transformation rounds (making dictionary attacks harder).
|
||||
/// Default number of master key encryption/transformation rounds
|
||||
/// (making dictionary attacks harder).
|
||||
/// </summary>
|
||||
public const ulong DefaultKeyEncryptionRounds = 6000;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -311,8 +311,11 @@ namespace KeePassLib
|
||||
|
||||
if(bSetTimes)
|
||||
{
|
||||
m_tCreation = m_tLastMod = m_tLastAccess =
|
||||
m_tParentGroupLastMod = DateTime.Now;
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
m_tCreation = dtNow;
|
||||
m_tLastMod = dtNow;
|
||||
m_tLastAccess = dtNow;
|
||||
m_tParentGroupLastMod = dtNow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,8 +339,11 @@ namespace KeePassLib
|
||||
|
||||
if(bSetTimes)
|
||||
{
|
||||
m_tCreation = m_tLastMod = m_tLastAccess =
|
||||
m_tParentGroupLastMod = DateTime.Now;
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
m_tCreation = dtNow;
|
||||
m_tLastMod = dtNow;
|
||||
m_tLastAccess = dtNow;
|
||||
m_tParentGroupLastMod = dtNow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,7 +591,7 @@ namespace KeePassLib
|
||||
/// get touched, too.</param>
|
||||
public void Touch(bool bModified, bool bTouchParents)
|
||||
{
|
||||
m_tLastAccess = DateTime.Now;
|
||||
m_tLastAccess = DateTime.UtcNow;
|
||||
++m_uUsageCount;
|
||||
|
||||
if(bModified) m_tLastMod = m_tLastAccess;
|
||||
@ -724,7 +730,7 @@ namespace KeePassLib
|
||||
|
||||
private void RemoveOldestBackup()
|
||||
{
|
||||
DateTime dtMin = DateTime.MaxValue;
|
||||
DateTime dtMin = TimeUtil.SafeMaxValueUtc;
|
||||
uint idxRemove = uint.MaxValue;
|
||||
|
||||
for(uint u = 0; u < m_listHistory.UCount; ++u)
|
||||
@ -888,7 +894,7 @@ namespace KeePassLib
|
||||
|
||||
public void SetCreatedNow()
|
||||
{
|
||||
DateTime dt = DateTime.Now;
|
||||
DateTime dt = DateTime.UtcNow;
|
||||
|
||||
m_tCreation = dt;
|
||||
m_tLastAccess = dt;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -321,8 +321,11 @@ namespace KeePassLib
|
||||
|
||||
if(bSetTimes)
|
||||
{
|
||||
m_tCreation = m_tLastMod = m_tLastAccess =
|
||||
m_tParentGroupLastMod = DateTime.Now;
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
m_tCreation = dtNow;
|
||||
m_tLastMod = dtNow;
|
||||
m_tLastAccess = dtNow;
|
||||
m_tParentGroupLastMod = dtNow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,8 +342,11 @@ namespace KeePassLib
|
||||
|
||||
if(bSetTimes)
|
||||
{
|
||||
m_tCreation = m_tLastMod = m_tLastAccess =
|
||||
m_tParentGroupLastMod = DateTime.Now;
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
m_tCreation = dtNow;
|
||||
m_tLastMod = dtNow;
|
||||
m_tLastAccess = dtNow;
|
||||
m_tParentGroupLastMod = dtNow;
|
||||
}
|
||||
|
||||
if(strName != null) m_strName = strName;
|
||||
@ -557,7 +563,7 @@ namespace KeePassLib
|
||||
/// get touched, too.</param>
|
||||
public void Touch(bool bModified, bool bTouchParents)
|
||||
{
|
||||
m_tLastAccess = DateTime.Now;
|
||||
m_tLastAccess = DateTime.UtcNow;
|
||||
++m_uUsageCount;
|
||||
|
||||
if(bModified) m_tLastMod = m_tLastAccess;
|
||||
@ -662,22 +668,15 @@ namespace KeePassLib
|
||||
}
|
||||
}
|
||||
|
||||
foreach(PwGroup pg in m_listGroups)
|
||||
{
|
||||
if(groupHandler != null)
|
||||
{
|
||||
foreach(PwGroup pg in m_listGroups)
|
||||
{
|
||||
if(!groupHandler(pg)) return false;
|
||||
}
|
||||
|
||||
pg.PreOrderTraverseTree(groupHandler, entryHandler);
|
||||
}
|
||||
}
|
||||
else // groupHandler == null
|
||||
{
|
||||
foreach(PwGroup pg in m_listGroups)
|
||||
{
|
||||
pg.PreOrderTraverseTree(null, entryHandler);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -766,96 +765,112 @@ namespace KeePassLib
|
||||
/// <summary>
|
||||
/// Search this group and all subgroups for entries.
|
||||
/// </summary>
|
||||
/// <param name="sp">Specifies the search method.</param>
|
||||
/// <param name="listStorage">Entry list in which the search results will
|
||||
/// be stored.</param>
|
||||
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage)
|
||||
/// <param name="sp">Specifies the search parameters.</param>
|
||||
/// <param name="lResults">Entry list in which the search results
|
||||
/// will be stored.</param>
|
||||
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> lResults)
|
||||
{
|
||||
SearchEntries(sp, listStorage, null);
|
||||
SearchEntries(sp, lResults, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search this group and all subgroups for entries.
|
||||
/// </summary>
|
||||
/// <param name="sp">Specifies the search method.</param>
|
||||
/// <param name="listStorage">Entry list in which the search results will
|
||||
/// be stored.</param>
|
||||
/// <param name="sp">Specifies the search parameters.</param>
|
||||
/// <param name="lResults">Entry list in which the search results
|
||||
/// will be stored.</param>
|
||||
/// <param name="slStatus">Optional status reporting object.</param>
|
||||
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage,
|
||||
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> lResults,
|
||||
IStatusLogger slStatus)
|
||||
{
|
||||
if(sp == null) { Debug.Assert(false); return; }
|
||||
if(listStorage == null) { Debug.Assert(false); return; }
|
||||
if(lResults == null) { Debug.Assert(false); return; }
|
||||
|
||||
ulong uCurEntries = 0, uTotalEntries = 0;
|
||||
PwObjectList<PwEntry> lCand = GetEntries(true);
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
|
||||
List<string> lTerms = StrUtil.SplitSearchTerms(sp.SearchString);
|
||||
if((lTerms.Count <= 1) || sp.RegularExpression)
|
||||
PwObjectList<PwEntry> l = new PwObjectList<PwEntry>();
|
||||
foreach(PwEntry pe in lCand)
|
||||
{
|
||||
if(slStatus != null) uTotalEntries = GetEntriesCount(true);
|
||||
SearchEntriesSingle(sp, listStorage, slStatus, ref uCurEntries,
|
||||
uTotalEntries);
|
||||
return;
|
||||
if(sp.RespectEntrySearchingDisabled && !pe.GetSearchingEnabled())
|
||||
continue;
|
||||
if(sp.ExcludeExpired && pe.Expires && (pe.ExpiryTime <= dtNow))
|
||||
continue;
|
||||
|
||||
l.Add(pe);
|
||||
}
|
||||
lCand = l;
|
||||
|
||||
List<string> lTerms;
|
||||
if(sp.RegularExpression)
|
||||
{
|
||||
lTerms = new List<string>();
|
||||
lTerms.Add((sp.SearchString ?? string.Empty).Trim());
|
||||
}
|
||||
else lTerms = StrUtil.SplitSearchTerms(sp.SearchString);
|
||||
|
||||
// Search longer strings first (for improved performance)
|
||||
lTerms.Sort(StrUtil.CompareLengthGt);
|
||||
|
||||
string strFullSearch = sp.SearchString; // Backup
|
||||
ulong uPrcEntries = 0, uTotalEntries = lCand.UCount;
|
||||
SearchParameters spSub = sp.Clone();
|
||||
|
||||
PwGroup pg = this;
|
||||
for(int iTerm = 0; iTerm < lTerms.Count; ++iTerm)
|
||||
{
|
||||
// Update counters for a better state guess
|
||||
if(slStatus != null)
|
||||
{
|
||||
ulong uRemRounds = (ulong)(lTerms.Count - iTerm);
|
||||
uTotalEntries = uCurEntries + (uRemRounds *
|
||||
pg.GetEntriesCount(true));
|
||||
uTotalEntries = uPrcEntries + (uRemRounds *
|
||||
lCand.UCount);
|
||||
}
|
||||
|
||||
PwGroup pgNew = new PwGroup();
|
||||
|
||||
sp.SearchString = lTerms[iTerm];
|
||||
spSub.SearchString = lTerms[iTerm]; // No trim
|
||||
// spSub.RespectEntrySearchingDisabled = false; // Ignored by sub
|
||||
// spSub.ExcludeExpired = false; // Ignored by sub
|
||||
|
||||
bool bNegate = false;
|
||||
if(sp.SearchString.StartsWith("-"))
|
||||
if(spSub.SearchString.StartsWith(@"-") &&
|
||||
(spSub.SearchString.Length >= 2))
|
||||
{
|
||||
sp.SearchString = sp.SearchString.Substring(1);
|
||||
bNegate = (sp.SearchString.Length > 0);
|
||||
spSub.SearchString = spSub.SearchString.Substring(1);
|
||||
bNegate = true;
|
||||
}
|
||||
|
||||
if(!pg.SearchEntriesSingle(sp, pgNew.Entries, slStatus,
|
||||
ref uCurEntries, uTotalEntries))
|
||||
l = new PwObjectList<PwEntry>();
|
||||
if(!SearchEntriesSingle(lCand, spSub, l, slStatus,
|
||||
ref uPrcEntries, uTotalEntries))
|
||||
{
|
||||
pg = null;
|
||||
lCand.Clear();
|
||||
break;
|
||||
}
|
||||
|
||||
if(bNegate)
|
||||
{
|
||||
PwObjectList<PwEntry> lCand = pg.GetEntries(true);
|
||||
|
||||
pg = new PwGroup();
|
||||
foreach(PwEntry peCand in lCand)
|
||||
PwObjectList<PwEntry> lRem = new PwObjectList<PwEntry>();
|
||||
foreach(PwEntry pe in lCand)
|
||||
{
|
||||
if(pgNew.Entries.IndexOf(peCand) < 0) pg.Entries.Add(peCand);
|
||||
}
|
||||
}
|
||||
else pg = pgNew;
|
||||
if(l.IndexOf(pe) < 0) lRem.Add(pe);
|
||||
}
|
||||
|
||||
if(pg != null) listStorage.Add(pg.Entries);
|
||||
sp.SearchString = strFullSearch; // Restore
|
||||
lCand = lRem;
|
||||
}
|
||||
else lCand = l;
|
||||
}
|
||||
|
||||
private bool SearchEntriesSingle(SearchParameters spIn,
|
||||
PwObjectList<PwEntry> listStorage, IStatusLogger slStatus,
|
||||
ref ulong uCurEntries, ulong uTotalEntries)
|
||||
Debug.Assert(lResults.UCount == 0);
|
||||
lResults.Clear();
|
||||
lResults.Add(lCand);
|
||||
}
|
||||
|
||||
private static bool SearchEntriesSingle(PwObjectList<PwEntry> lSource,
|
||||
SearchParameters sp, PwObjectList<PwEntry> lResults,
|
||||
IStatusLogger slStatus, ref ulong uPrcEntries, ulong uTotalEntries)
|
||||
{
|
||||
SearchParameters sp = spIn.Clone();
|
||||
if(sp.SearchString == null) { Debug.Assert(false); return true; }
|
||||
sp.SearchString = sp.SearchString.Trim();
|
||||
if(lSource == null) { Debug.Assert(false); return true; }
|
||||
if(sp == null) { Debug.Assert(false); return true; }
|
||||
if(lResults == null) { Debug.Assert(false); return true; }
|
||||
Debug.Assert(lResults.UCount == 0);
|
||||
|
||||
bool bTitle = sp.SearchInTitles;
|
||||
bool bUserName = sp.SearchInUserNames;
|
||||
@ -866,10 +881,8 @@ namespace KeePassLib
|
||||
bool bUuids = sp.SearchInUuids;
|
||||
bool bGroupName = sp.SearchInGroupNames;
|
||||
bool bTags = sp.SearchInTags;
|
||||
bool bExcludeExpired = sp.ExcludeExpired;
|
||||
bool bRespectEntrySearchingDisabled = sp.RespectEntrySearchingDisabled;
|
||||
|
||||
DateTime dtNow = DateTime.Now;
|
||||
// bool bExcludeExpired = sp.ExcludeExpired;
|
||||
// bool bRespectEntrySearchingDisabled = sp.RespectEntrySearchingDisabled;
|
||||
|
||||
Regex rx = null;
|
||||
if(sp.RegularExpression)
|
||||
@ -887,46 +900,26 @@ namespace KeePassLib
|
||||
rx = new Regex(sp.SearchString, ro);
|
||||
}
|
||||
|
||||
ulong uLocalCurEntries = uCurEntries;
|
||||
ulong uLocalPrcEntries = uPrcEntries;
|
||||
|
||||
EntryHandler eh = null;
|
||||
if(sp.SearchString.Length <= 0) // Report all
|
||||
{
|
||||
eh = delegate(PwEntry pe)
|
||||
{
|
||||
if(slStatus != null)
|
||||
{
|
||||
if(!slStatus.SetProgress((uint)((uLocalCurEntries *
|
||||
100UL) / uTotalEntries))) return false;
|
||||
++uLocalCurEntries;
|
||||
}
|
||||
|
||||
if(bRespectEntrySearchingDisabled && !pe.GetSearchingEnabled())
|
||||
return true; // Skip
|
||||
if(bExcludeExpired && pe.Expires && (dtNow > pe.ExpiryTime))
|
||||
return true; // Skip
|
||||
|
||||
listStorage.Add(pe);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
if(sp.SearchString.Length == 0) lResults.Add(lSource);
|
||||
else
|
||||
{
|
||||
eh = delegate(PwEntry pe)
|
||||
foreach(PwEntry pe in lSource)
|
||||
{
|
||||
if(slStatus != null)
|
||||
{
|
||||
if(!slStatus.SetProgress((uint)((uLocalCurEntries *
|
||||
if(!slStatus.SetProgress((uint)((uLocalPrcEntries *
|
||||
100UL) / uTotalEntries))) return false;
|
||||
++uLocalCurEntries;
|
||||
++uLocalPrcEntries;
|
||||
}
|
||||
|
||||
if(bRespectEntrySearchingDisabled && !pe.GetSearchingEnabled())
|
||||
return true; // Skip
|
||||
if(bExcludeExpired && pe.Expires && (dtNow > pe.ExpiryTime))
|
||||
return true; // Skip
|
||||
// if(bRespectEntrySearchingDisabled && !pe.GetSearchingEnabled())
|
||||
// continue;
|
||||
// if(bExcludeExpired && pe.Expires && (pe.ExpiryTime <= dtNow))
|
||||
// continue;
|
||||
|
||||
uint uInitialResults = listStorage.UCount;
|
||||
uint uInitialResults = lResults.UCount;
|
||||
|
||||
foreach(KeyValuePair<string, ProtectedString> kvp in pe.Strings)
|
||||
{
|
||||
@ -935,76 +928,77 @@ namespace KeePassLib
|
||||
if(strKey == PwDefs.TitleField)
|
||||
{
|
||||
if(bTitle) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||
rx, pe, listStorage);
|
||||
rx, pe, lResults);
|
||||
}
|
||||
else if(strKey == PwDefs.UserNameField)
|
||||
{
|
||||
if(bUserName) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||
rx, pe, listStorage);
|
||||
rx, pe, lResults);
|
||||
}
|
||||
else if(strKey == PwDefs.PasswordField)
|
||||
{
|
||||
if(bPassword) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||
rx, pe, listStorage);
|
||||
rx, pe, lResults);
|
||||
}
|
||||
else if(strKey == PwDefs.UrlField)
|
||||
{
|
||||
if(bUrl) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||
rx, pe, listStorage);
|
||||
rx, pe, lResults);
|
||||
}
|
||||
else if(strKey == PwDefs.NotesField)
|
||||
{
|
||||
if(bNotes) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||
rx, pe, listStorage);
|
||||
rx, pe, lResults);
|
||||
}
|
||||
else if(bOther)
|
||||
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||
rx, pe, listStorage);
|
||||
rx, pe, lResults);
|
||||
|
||||
// An entry can match only once => break if we have added it
|
||||
if(listStorage.UCount > uInitialResults) break;
|
||||
if(lResults.UCount != uInitialResults) break;
|
||||
}
|
||||
|
||||
if(bUuids && (listStorage.UCount == uInitialResults))
|
||||
SearchEvalAdd(sp, pe.Uuid.ToHexString(), rx, pe, listStorage);
|
||||
if(bUuids && (lResults.UCount == uInitialResults))
|
||||
SearchEvalAdd(sp, pe.Uuid.ToHexString(), rx, pe, lResults);
|
||||
|
||||
if(bGroupName && (listStorage.UCount == uInitialResults) &&
|
||||
if(bGroupName && (lResults.UCount == uInitialResults) &&
|
||||
(pe.ParentGroup != null))
|
||||
SearchEvalAdd(sp, pe.ParentGroup.Name, rx, pe, listStorage);
|
||||
SearchEvalAdd(sp, pe.ParentGroup.Name, rx, pe, lResults);
|
||||
|
||||
if(bTags)
|
||||
{
|
||||
foreach(string strTag in pe.Tags)
|
||||
{
|
||||
if(listStorage.UCount != uInitialResults) break; // Match
|
||||
if(lResults.UCount != uInitialResults) break;
|
||||
|
||||
SearchEvalAdd(sp, strTag, rx, pe, listStorage);
|
||||
SearchEvalAdd(sp, strTag, rx, pe, lResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
if(!PreOrderTraverseTree(null, eh)) return false;
|
||||
uCurEntries = uLocalCurEntries;
|
||||
uPrcEntries = uLocalPrcEntries;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void SearchEvalAdd(SearchParameters sp, string strDataField,
|
||||
private static void SearchEvalAdd(SearchParameters sp, string strData,
|
||||
Regex rx, PwEntry pe, PwObjectList<PwEntry> lResults)
|
||||
{
|
||||
bool bMatch = false;
|
||||
if(sp == null) { Debug.Assert(false); return; }
|
||||
if(strData == null) { Debug.Assert(false); return; }
|
||||
if(pe == null) { Debug.Assert(false); return; }
|
||||
if(lResults == null) { Debug.Assert(false); return; }
|
||||
|
||||
bool bMatch;
|
||||
if(rx == null)
|
||||
bMatch = (strDataField.IndexOf(sp.SearchString,
|
||||
bMatch = (strData.IndexOf(sp.SearchString,
|
||||
sp.ComparisonMode) >= 0);
|
||||
else bMatch = rx.IsMatch(strDataField);
|
||||
else bMatch = rx.IsMatch(strData);
|
||||
|
||||
if(!bMatch && (sp.DataTransformationFn != null))
|
||||
{
|
||||
string strCmp = sp.DataTransformationFn(strDataField, pe);
|
||||
if(!object.ReferenceEquals(strCmp, strDataField))
|
||||
string strCmp = sp.DataTransformationFn(strData, pe);
|
||||
if(!object.ReferenceEquals(strCmp, strData))
|
||||
{
|
||||
if(rx == null)
|
||||
bMatch = (strCmp.IndexOf(sp.SearchString,
|
||||
@ -1424,15 +1418,20 @@ namespace KeePassLib
|
||||
|
||||
public PwObjectList<PwEntry> GetEntries(bool bIncludeSubGroupEntries)
|
||||
{
|
||||
if(bIncludeSubGroupEntries == false) return m_listEntries;
|
||||
PwObjectList<PwEntry> l = new PwObjectList<PwEntry>();
|
||||
|
||||
PwObjectList<PwEntry> list = m_listEntries.CloneShallow();
|
||||
foreach(PwGroup pgSub in m_listGroups)
|
||||
GroupHandler gh = delegate(PwGroup pg)
|
||||
{
|
||||
list.Add(pgSub.GetEntries(true));
|
||||
}
|
||||
l.Add(pg.Entries);
|
||||
return true;
|
||||
};
|
||||
|
||||
return list;
|
||||
gh(this);
|
||||
if(bIncludeSubGroupEntries)
|
||||
PreOrderTraverseTree(gh, null);
|
||||
|
||||
Debug.Assert(l.UCount == GetEntriesCount(bIncludeSubGroupEntries));
|
||||
return l;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1505,7 +1504,7 @@ namespace KeePassLib
|
||||
|
||||
if(bTakeOwnership) subGroup.m_pParentGroup = this;
|
||||
|
||||
if(bUpdateLocationChangedOfSub) subGroup.LocationChanged = DateTime.Now;
|
||||
if(bUpdateLocationChangedOfSub) subGroup.LocationChanged = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1540,7 +1539,7 @@ namespace KeePassLib
|
||||
// only assign it to the new one
|
||||
if(bTakeOwnership) pe.ParentGroup = this;
|
||||
|
||||
if(bUpdateLocationChangedOfEntry) pe.LocationChanged = DateTime.Now;
|
||||
if(bUpdateLocationChangedOfEntry) pe.LocationChanged = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public void SortSubGroups(bool bRecursive)
|
||||
@ -1556,7 +1555,7 @@ namespace KeePassLib
|
||||
|
||||
public void DeleteAllObjects(PwDatabase pdContext)
|
||||
{
|
||||
DateTime dtNow = DateTime.Now;
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
|
||||
foreach(PwEntry pe in m_listEntries)
|
||||
{
|
||||
@ -1600,7 +1599,7 @@ namespace KeePassLib
|
||||
|
||||
public void SetCreatedNow(bool bRecursive)
|
||||
{
|
||||
DateTime dt = DateTime.Now;
|
||||
DateTime dt = DateTime.UtcNow;
|
||||
|
||||
m_tCreation = dt;
|
||||
m_tLastAccess = dt;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -33,7 +33,9 @@ namespace KeePassLib.Resources
|
||||
m_strFatalError = TryGetEx(dictNew, "FatalError", m_strFatalError);
|
||||
m_strFatalErrorText = TryGetEx(dictNew, "FatalErrorText", m_strFatalErrorText);
|
||||
m_strFileCorrupted = TryGetEx(dictNew, "FileCorrupted", m_strFileCorrupted);
|
||||
m_strFileHeaderEndEarly = TryGetEx(dictNew, "FileHeaderEndEarly", m_strFileHeaderEndEarly);
|
||||
m_strFileHeaderCorrupted = TryGetEx(dictNew, "FileHeaderCorrupted", m_strFileHeaderCorrupted);
|
||||
m_strFileIncomplete = TryGetEx(dictNew, "FileIncomplete", m_strFileIncomplete);
|
||||
m_strFileIncompleteExpc = TryGetEx(dictNew, "FileIncompleteExpc", m_strFileIncompleteExpc);
|
||||
m_strFileLoadFailed = TryGetEx(dictNew, "FileLoadFailed", m_strFileLoadFailed);
|
||||
m_strFileLockedWrite = TryGetEx(dictNew, "FileLockedWrite", m_strFileLockedWrite);
|
||||
m_strFileNewVerOrPlgReq = TryGetEx(dictNew, "FileNewVerOrPlgReq", m_strFileNewVerOrPlgReq);
|
||||
@ -73,7 +75,9 @@ namespace KeePassLib.Resources
|
||||
"FatalError",
|
||||
"FatalErrorText",
|
||||
"FileCorrupted",
|
||||
"FileHeaderEndEarly",
|
||||
"FileHeaderCorrupted",
|
||||
"FileIncomplete",
|
||||
"FileIncompleteExpc",
|
||||
"FileLoadFailed",
|
||||
"FileLockedWrite",
|
||||
"FileNewVerOrPlgReq",
|
||||
@ -187,15 +191,37 @@ namespace KeePassLib.Resources
|
||||
get { return m_strFileCorrupted; }
|
||||
}
|
||||
|
||||
private static string m_strFileHeaderEndEarly =
|
||||
@"The file header is corrupted! Some header data was declared but is not present.";
|
||||
private static string m_strFileHeaderCorrupted =
|
||||
@"The file header is corrupted.";
|
||||
/// <summary>
|
||||
/// Look up a localized string similar to
|
||||
/// 'The file header is corrupted! Some header data was declared but is not present.'.
|
||||
/// 'The file header is corrupted.'.
|
||||
/// </summary>
|
||||
public static string FileHeaderEndEarly
|
||||
public static string FileHeaderCorrupted
|
||||
{
|
||||
get { return m_strFileHeaderEndEarly; }
|
||||
get { return m_strFileHeaderCorrupted; }
|
||||
}
|
||||
|
||||
private static string m_strFileIncomplete =
|
||||
@"Data is missing at the end of the file, i.e. the file is incomplete.";
|
||||
/// <summary>
|
||||
/// Look up a localized string similar to
|
||||
/// 'Data is missing at the end of the file, i.e. the file is incomplete.'.
|
||||
/// </summary>
|
||||
public static string FileIncomplete
|
||||
{
|
||||
get { return m_strFileIncomplete; }
|
||||
}
|
||||
|
||||
private static string m_strFileIncompleteExpc =
|
||||
@"Less data than expected could be read from the file.";
|
||||
/// <summary>
|
||||
/// Look up a localized string similar to
|
||||
/// 'Less data than expected could be read from the file.'.
|
||||
/// </summary>
|
||||
public static string FileIncompleteExpc
|
||||
{
|
||||
get { return m_strFileIncompleteExpc; }
|
||||
}
|
||||
|
||||
private static string m_strFileLoadFailed =
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -166,7 +166,7 @@ namespace KeePassLib.Security
|
||||
/// </summary>
|
||||
public ProtectedBinary()
|
||||
{
|
||||
Init(false, MemUtil.EmptyByteArray);
|
||||
Init(false, MemUtil.EmptyByteArray, 0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -181,7 +181,27 @@ namespace KeePassLib.Security
|
||||
/// i.e. the caller is responsible for clearing it.</param>
|
||||
public ProtectedBinary(bool bEnableProtection, byte[] pbData)
|
||||
{
|
||||
Init(bEnableProtection, pbData);
|
||||
if(pbData == null) throw new ArgumentNullException("pbData");
|
||||
|
||||
Init(bEnableProtection, pbData, 0, pbData.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new protected binary data object.
|
||||
/// </summary>
|
||||
/// <param name="bEnableProtection">If this paremeter is <c>true</c>,
|
||||
/// the data will be encrypted in memory. If it is <c>false</c>, the
|
||||
/// data is stored in plain-text in the process memory.</param>
|
||||
/// <param name="pbData">Value of the protected object.
|
||||
/// The input parameter is not modified and
|
||||
/// <c>ProtectedBinary</c> doesn't take ownership of the data,
|
||||
/// i.e. the caller is responsible for clearing it.</param>
|
||||
/// <param name="iOffset">Offset for <paramref name="pbData" />.</param>
|
||||
/// <param name="cbSize">Size for <paramref name="pbData" />.</param>
|
||||
public ProtectedBinary(bool bEnableProtection, byte[] pbData,
|
||||
int iOffset, int cbSize)
|
||||
{
|
||||
Init(bEnableProtection, pbData, iOffset, cbSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -197,14 +217,19 @@ namespace KeePassLib.Security
|
||||
if(xbProtected == null) throw new ArgumentNullException("xbProtected");
|
||||
|
||||
byte[] pb = xbProtected.ReadPlainText();
|
||||
Init(bEnableProtection, pb);
|
||||
Init(bEnableProtection, pb, 0, pb.Length);
|
||||
|
||||
if(bEnableProtection) MemUtil.ZeroByteArray(pb);
|
||||
}
|
||||
|
||||
private void Init(bool bEnableProtection, byte[] pbData)
|
||||
private void Init(bool bEnableProtection, byte[] pbData, int iOffset,
|
||||
int cbSize)
|
||||
{
|
||||
if(pbData == null) throw new ArgumentNullException("pbData");
|
||||
if(iOffset < 0) throw new ArgumentOutOfRangeException("iOffset");
|
||||
if(cbSize < 0) throw new ArgumentOutOfRangeException("cbSize");
|
||||
if(iOffset > (pbData.Length - cbSize))
|
||||
throw new ArgumentOutOfRangeException("cbSize");
|
||||
|
||||
#if KeePassLibSD
|
||||
m_lID = ++g_lCurID;
|
||||
@ -213,15 +238,15 @@ namespace KeePassLib.Security
|
||||
#endif
|
||||
|
||||
m_bProtected = bEnableProtection;
|
||||
m_uDataLen = (uint)pbData.Length;
|
||||
m_uDataLen = (uint)cbSize;
|
||||
|
||||
const int bs = ProtectedBinary.BlockSize;
|
||||
int nBlocks = (int)m_uDataLen / bs;
|
||||
if((nBlocks * bs) < (int)m_uDataLen) ++nBlocks;
|
||||
Debug.Assert((nBlocks * bs) >= (int)m_uDataLen);
|
||||
int nBlocks = cbSize / bs;
|
||||
if((nBlocks * bs) < cbSize) ++nBlocks;
|
||||
Debug.Assert((nBlocks * bs) >= cbSize);
|
||||
|
||||
m_pbData = new byte[nBlocks * bs];
|
||||
Array.Copy(pbData, m_pbData, (int)m_uDataLen);
|
||||
Array.Copy(pbData, iOffset, m_pbData, 0, cbSize);
|
||||
|
||||
Encrypt();
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -282,7 +282,7 @@ namespace KeePassLib.Security
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(v, 0, v.Length);
|
||||
MemUtil.ZeroArray<char>(v);
|
||||
MemUtil.ZeroByteArray(pb);
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ namespace KeePassLib.Security
|
||||
Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
|
||||
ReadString().Insert(iStart, strInsert));
|
||||
|
||||
Array.Clear(vNew, 0, vNew.Length);
|
||||
MemUtil.ZeroArray<char>(vNew);
|
||||
MemUtil.ZeroByteArray(pbNew);
|
||||
return ps;
|
||||
}
|
||||
@ -328,7 +328,7 @@ namespace KeePassLib.Security
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(v, 0, v.Length);
|
||||
MemUtil.ZeroArray<char>(v);
|
||||
MemUtil.ZeroByteArray(pb);
|
||||
}
|
||||
|
||||
@ -338,7 +338,7 @@ namespace KeePassLib.Security
|
||||
Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
|
||||
ReadString().Remove(iStart, nCount));
|
||||
|
||||
Array.Clear(vNew, 0, vNew.Length);
|
||||
MemUtil.ZeroArray<char>(vNew);
|
||||
MemUtil.ZeroByteArray(pbNew);
|
||||
return ps;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -31,7 +31,7 @@ namespace KeePassLib.Serialization
|
||||
private Stream m_s;
|
||||
// private Encoding m_enc; // See constructor
|
||||
|
||||
private string m_strReadExcp;
|
||||
private string m_strReadExcp; // May be null
|
||||
public string ReadExceptionText
|
||||
{
|
||||
get { return m_strReadExcp; }
|
||||
@ -67,7 +67,8 @@ namespace KeePassLib.Serialization
|
||||
byte[] pb = MemUtil.Read(m_s, nCount);
|
||||
if((pb == null) || (pb.Length != nCount))
|
||||
{
|
||||
if(m_strReadExcp != null) throw new IOException(m_strReadExcp);
|
||||
if(!string.IsNullOrEmpty(m_strReadExcp))
|
||||
throw new EndOfStreamException(m_strReadExcp);
|
||||
else throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
@ -76,7 +77,8 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
if(m_strReadExcp != null) throw new IOException(m_strReadExcp);
|
||||
if(!string.IsNullOrEmpty(m_strReadExcp))
|
||||
throw new IOException(m_strReadExcp);
|
||||
else throw;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -72,6 +72,27 @@ namespace KeePassLib.Serialization
|
||||
|
||||
string strPath = m_iocBase.Path;
|
||||
|
||||
if(m_iocBase.IsLocalFile())
|
||||
{
|
||||
try
|
||||
{
|
||||
if(File.Exists(strPath))
|
||||
{
|
||||
// Symbolic links are realized via reparse points;
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365503.aspx
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680.aspx
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365006.aspx
|
||||
// Performing a file transaction on a symbolic link
|
||||
// would delete/replace the symbolic link instead of
|
||||
// writing to its target
|
||||
FileAttributes fa = File.GetAttributes(strPath);
|
||||
if((long)(fa & FileAttributes.ReparsePoint) != 0)
|
||||
m_bTransacted = false;
|
||||
}
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
|
||||
#if !KeePassUAP
|
||||
// Prevent transactions for FTP URLs under .NET 4.0 in order to
|
||||
// avoid/workaround .NET bug 621450:
|
||||
@ -79,9 +100,8 @@ namespace KeePassLib.Serialization
|
||||
if(strPath.StartsWith("ftp:", StrUtil.CaseIgnoreCmp) &&
|
||||
(Environment.Version.Major >= 4) && !NativeLib.IsUnix())
|
||||
m_bTransacted = false;
|
||||
else
|
||||
{
|
||||
#endif
|
||||
|
||||
foreach(KeyValuePair<string, bool> kvp in g_dEnabled)
|
||||
{
|
||||
if(strPath.StartsWith(kvp.Key, StrUtil.CaseIgnoreCmp))
|
||||
@ -90,9 +110,6 @@ namespace KeePassLib.Serialization
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if !KeePassUAP
|
||||
}
|
||||
#endif
|
||||
|
||||
if(m_bTransacted)
|
||||
{
|
||||
@ -150,8 +167,8 @@ namespace KeePassLib.Serialization
|
||||
FileAttributes faBase = File.GetAttributes(m_iocBase.Path);
|
||||
bEfsEncrypted = ((long)(faBase & FileAttributes.Encrypted) != 0);
|
||||
#endif
|
||||
DateTime tCreation = File.GetCreationTime(m_iocBase.Path);
|
||||
File.SetCreationTime(m_iocTemp.Path, tCreation);
|
||||
DateTime tCreation = File.GetCreationTimeUtc(m_iocBase.Path);
|
||||
File.SetCreationTimeUtc(m_iocTemp.Path, tCreation);
|
||||
#if !KeePassUAP
|
||||
// May throw with Mono
|
||||
bkSecurity = File.GetAccessControl(m_iocBase.Path);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -124,20 +124,9 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
if(m_bWriting) m_bwOutput.Flush();
|
||||
}
|
||||
|
||||
#if KeePassUAP
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(!disposing) return;
|
||||
#else
|
||||
public override void Close()
|
||||
{
|
||||
#endif
|
||||
if(m_sBaseStream != null)
|
||||
if(disposing && (m_sBaseStream != null))
|
||||
{
|
||||
if(!m_bWriting) // Reading mode
|
||||
{
|
||||
@ -162,6 +151,13 @@ namespace KeePassLib.Serialization
|
||||
m_sBaseStream.Close();
|
||||
m_sBaseStream = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
if(m_bWriting) m_bwOutput.Flush();
|
||||
}
|
||||
|
||||
public override long Seek(long lOffset, SeekOrigin soOrigin)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -98,21 +98,9 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
Debug.Assert(m_sBase != null); // Object should not be disposed
|
||||
if(m_bWriting && (m_sBase != null)) m_sBase.Flush();
|
||||
}
|
||||
|
||||
#if KeePassUAP
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(!disposing) return;
|
||||
#else
|
||||
public override void Close()
|
||||
{
|
||||
#endif
|
||||
if(m_sBase != null)
|
||||
if(disposing && (m_sBase != null))
|
||||
{
|
||||
if(m_bWriting)
|
||||
{
|
||||
@ -130,6 +118,14 @@ namespace KeePassLib.Serialization
|
||||
m_sBase.Close();
|
||||
m_sBase = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
Debug.Assert(m_sBase != null); // Object should not be disposed
|
||||
if(m_bWriting && (m_sBase != null)) m_sBase.Flush();
|
||||
}
|
||||
|
||||
public override long Seek(long lOffset, SeekOrigin soOrigin)
|
||||
@ -206,7 +202,8 @@ namespace KeePassLib.Serialization
|
||||
|
||||
byte[] pbStoredHmac = MemUtil.Read(m_sBase, 32);
|
||||
if((pbStoredHmac == null) || (pbStoredHmac.Length != 32))
|
||||
throw new EndOfStreamException();
|
||||
throw new EndOfStreamException(KLRes.FileCorrupted + " " +
|
||||
KLRes.FileIncomplete);
|
||||
|
||||
// Block index is implicit: it's used in the HMAC computation,
|
||||
// but does not need to be stored
|
||||
@ -220,7 +217,8 @@ namespace KeePassLib.Serialization
|
||||
|
||||
byte[] pbBlockSize = MemUtil.Read(m_sBase, 4);
|
||||
if((pbBlockSize == null) || (pbBlockSize.Length != 4))
|
||||
throw new EndOfStreamException();
|
||||
throw new EndOfStreamException(KLRes.FileCorrupted + " " +
|
||||
KLRes.FileIncomplete);
|
||||
int nBlockSize = MemUtil.BytesToInt32(pbBlockSize);
|
||||
if(nBlockSize < 0)
|
||||
throw new InvalidDataException(KLRes.FileCorrupted);
|
||||
@ -229,7 +227,8 @@ namespace KeePassLib.Serialization
|
||||
|
||||
m_pbBuffer = MemUtil.Read(m_sBase, nBlockSize);
|
||||
if((m_pbBuffer == null) || ((m_pbBuffer.Length != nBlockSize) && m_bVerify))
|
||||
throw new EndOfStreamException();
|
||||
throw new EndOfStreamException(KLRes.FileCorrupted + " " +
|
||||
KLRes.FileIncompleteExpc);
|
||||
|
||||
if(m_bVerify)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -130,17 +130,12 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
#endif
|
||||
|
||||
#if KeePassUAP
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing) m_s.Dispose();
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
#else
|
||||
public override void Close()
|
||||
{
|
||||
m_s.Close();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !KeePassUAP
|
||||
public override int EndRead(IAsyncResult asyncResult)
|
||||
@ -193,22 +188,19 @@ namespace KeePassLib.Serialization
|
||||
internal sealed class IocStream : WrapperStream
|
||||
{
|
||||
private readonly bool m_bWrite; // Initially opened for writing
|
||||
private bool m_bDisposed = false;
|
||||
|
||||
public IocStream(Stream sBase) : base(sBase)
|
||||
{
|
||||
m_bWrite = sBase.CanWrite;
|
||||
}
|
||||
|
||||
#if KeePassUAP
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
#else
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
#endif
|
||||
if(MonoWorkarounds.IsRequired(10163) && m_bWrite)
|
||||
|
||||
if(disposing && MonoWorkarounds.IsRequired(10163) && m_bWrite &&
|
||||
!m_bDisposed)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -230,6 +222,8 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
|
||||
m_bDisposed = true;
|
||||
}
|
||||
|
||||
public static Stream WrapIfRequired(Stream s)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -132,7 +132,6 @@ namespace KeePassLib.Serialization
|
||||
if(xr == null) throw new ArgumentNullException("xr");
|
||||
|
||||
m_ctxGroups.Clear();
|
||||
m_dictBinPool = new Dictionary<string, ProtectedBinary>();
|
||||
|
||||
KdbContext ctx = KdbContext.Null;
|
||||
|
||||
@ -233,11 +232,11 @@ namespace KeePassLib.Serialization
|
||||
if(!string.IsNullOrEmpty(strHash) && (m_pbHashOfHeader != null) &&
|
||||
!m_bRepairMode)
|
||||
{
|
||||
Debug.Assert(m_uFileVersion <= FileVersion32_3);
|
||||
Debug.Assert(m_uFileVersion < FileVersion32_4);
|
||||
|
||||
byte[] pbHash = Convert.FromBase64String(strHash);
|
||||
if(!MemUtil.ArraysEqual(pbHash, m_pbHashOfHeader))
|
||||
throw new IOException(KLRes.FileCorrupted);
|
||||
throw new InvalidDataException(KLRes.FileCorrupted);
|
||||
}
|
||||
}
|
||||
else if(xr.Name == ElemSettingsChanged)
|
||||
@ -268,6 +267,8 @@ namespace KeePassLib.Serialization
|
||||
m_pwDatabase.MasterKeyChangeRec = ReadLong(xr, -1);
|
||||
else if(xr.Name == ElemDbKeyChangeForce)
|
||||
m_pwDatabase.MasterKeyChangeForce = ReadLong(xr, -1);
|
||||
else if(xr.Name == ElemDbKeyChangeForceOnce)
|
||||
m_pwDatabase.MasterKeyChangeForceOnce = ReadBool(xr, false);
|
||||
else if(xr.Name == ElemMemoryProt)
|
||||
return SwitchContext(ctx, KdbContext.MemoryProtection, xr);
|
||||
else if(xr.Name == ElemCustomIcons)
|
||||
@ -340,7 +341,14 @@ namespace KeePassLib.Serialization
|
||||
string strKey = xr.Value;
|
||||
ProtectedBinary pbData = ReadProtectedBinary(xr);
|
||||
|
||||
m_dictBinPool[strKey ?? string.Empty] = pbData;
|
||||
int iKey;
|
||||
if(!StrUtil.TryParseIntInvariant(strKey, out iKey))
|
||||
throw new FormatException();
|
||||
if(iKey < 0) throw new FormatException();
|
||||
|
||||
Debug.Assert(m_pbsBinaries.Get(iKey) == null);
|
||||
Debug.Assert(m_pbsBinaries.Find(pbData) < 0);
|
||||
m_pbsBinaries.Set(iKey, pbData);
|
||||
}
|
||||
else ReadUnknown(xr);
|
||||
}
|
||||
@ -386,7 +394,7 @@ namespace KeePassLib.Serialization
|
||||
else if(xr.Name == ElemNotes)
|
||||
m_ctxGroup.Notes = ReadString(xr);
|
||||
else if(xr.Name == ElemIcon)
|
||||
m_ctxGroup.IconId = (PwIcon)ReadInt(xr, (int)PwIcon.Folder);
|
||||
m_ctxGroup.IconId = ReadIconId(xr, PwIcon.Folder);
|
||||
else if(xr.Name == ElemCustomIconID)
|
||||
m_ctxGroup.CustomIconUuid = ReadUuid(xr);
|
||||
else if(xr.Name == ElemTimes)
|
||||
@ -441,7 +449,7 @@ namespace KeePassLib.Serialization
|
||||
if(xr.Name == ElemUuid)
|
||||
m_ctxEntry.Uuid = ReadUuid(xr);
|
||||
else if(xr.Name == ElemIcon)
|
||||
m_ctxEntry.IconId = (PwIcon)ReadInt(xr, (int)PwIcon.Key);
|
||||
m_ctxEntry.IconId = ReadIconId(xr, PwIcon.Key);
|
||||
else if(xr.Name == ElemCustomIconID)
|
||||
m_ctxEntry.CustomIconUuid = ReadUuid(xr);
|
||||
else if(xr.Name == ElemFgColor)
|
||||
@ -848,16 +856,46 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
|
||||
private DateTime ReadTime(XmlReader xr)
|
||||
{
|
||||
// Cf. WriteObject(string, DateTime)
|
||||
if((m_format == KdbxFormat.Default) && (m_uFileVersion >= FileVersion32_4))
|
||||
{
|
||||
// long l = ReadLong(xr, -1);
|
||||
// if(l != -1) return DateTime.FromBinary(l);
|
||||
|
||||
string str = ReadString(xr);
|
||||
byte[] pb = Convert.FromBase64String(str);
|
||||
if(pb.Length != 8)
|
||||
{
|
||||
Debug.Assert(false);
|
||||
byte[] pb8 = new byte[8];
|
||||
Array.Copy(pb, pb8, Math.Min(pb.Length, 8)); // Little-endian
|
||||
pb = pb8;
|
||||
}
|
||||
long lSec = MemUtil.BytesToInt64(pb);
|
||||
return new DateTime(lSec * TimeSpan.TicksPerSecond, DateTimeKind.Utc);
|
||||
}
|
||||
else
|
||||
{
|
||||
string str = ReadString(xr);
|
||||
|
||||
DateTime dt;
|
||||
if(TimeUtil.TryDeserializeUtc(str, out dt)) return dt;
|
||||
}
|
||||
|
||||
Debug.Assert(false);
|
||||
return m_dtNow;
|
||||
}
|
||||
|
||||
private PwIcon ReadIconId(XmlReader xr, PwIcon icDefault)
|
||||
{
|
||||
int i = ReadInt(xr, (int)icDefault);
|
||||
if((i >= 0) && (i < (int)PwIcon.Count)) return (PwIcon)i;
|
||||
|
||||
Debug.Assert(false);
|
||||
return icDefault;
|
||||
}
|
||||
|
||||
private ProtectedString ReadProtectedString(XmlReader xr)
|
||||
{
|
||||
XorredBuffer xb = ProcessNode(xr);
|
||||
@ -882,9 +920,12 @@ namespace KeePassLib.Serialization
|
||||
if(xr.MoveToAttribute(AttrRef))
|
||||
{
|
||||
string strRef = xr.Value;
|
||||
if(strRef != null)
|
||||
if(!string.IsNullOrEmpty(strRef))
|
||||
{
|
||||
ProtectedBinary pb = BinPoolGet(strRef);
|
||||
int iRef;
|
||||
if(StrUtil.TryParseIntInvariant(strRef, out iRef))
|
||||
{
|
||||
ProtectedBinary pb = m_pbsBinaries.Get(iRef);
|
||||
if(pb != null)
|
||||
{
|
||||
// https://sourceforge.net/p/keepass/feature-requests/2023/
|
||||
@ -902,6 +943,8 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
|
||||
bool bCompressed = false;
|
||||
if(xr.MoveToAttribute(AttrCompressed))
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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,6 +17,8 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// #define KDBX_BENCHMARK
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
@ -42,6 +44,7 @@ using KeePassLib.Cryptography.KeyDerivation;
|
||||
using KeePassLib.Interfaces;
|
||||
using KeePassLib.Keys;
|
||||
using KeePassLib.Resources;
|
||||
using KeePassLib.Security;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Serialization
|
||||
@ -75,9 +78,19 @@ namespace KeePassLib.Serialization
|
||||
Debug.Assert(sSource != null);
|
||||
if(sSource == null) throw new ArgumentNullException("sSource");
|
||||
|
||||
if(m_bUsedOnce)
|
||||
throw new InvalidOperationException("Do not reuse KdbxFile objects!");
|
||||
m_bUsedOnce = true;
|
||||
|
||||
#if KDBX_BENCHMARK
|
||||
Stopwatch swTime = Stopwatch.StartNew();
|
||||
#endif
|
||||
|
||||
m_format = fmt;
|
||||
m_slLogger = slLogger;
|
||||
|
||||
m_pbsBinaries.Clear();
|
||||
|
||||
UTF8Encoding encNoBom = StrUtil.Utf8;
|
||||
byte[] pbCipherKey = null;
|
||||
byte[] pbHmacKey64 = null;
|
||||
@ -96,14 +109,18 @@ namespace KeePassLib.Serialization
|
||||
BinaryReaderEx br = new BinaryReaderEx(sHashing,
|
||||
encNoBom, KLRes.FileCorrupted);
|
||||
byte[] pbHeader = LoadHeader(br);
|
||||
m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);
|
||||
|
||||
int cbEncKey, cbEncIV;
|
||||
ICipherEngine iCipher = GetCipher(out cbEncKey, out cbEncIV);
|
||||
|
||||
ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);
|
||||
|
||||
string strIncomplete = KLRes.FileHeaderCorrupted + " " +
|
||||
KLRes.FileIncomplete;
|
||||
|
||||
Stream sPlain;
|
||||
if(m_uFileVersion <= FileVersion32_3)
|
||||
if(m_uFileVersion < FileVersion32_4)
|
||||
{
|
||||
Stream sDecrypted = EncryptStream(sHashing, iCipher,
|
||||
pbCipherKey, cbEncIV, false);
|
||||
@ -112,11 +129,11 @@ namespace KeePassLib.Serialization
|
||||
lStreams.Add(sDecrypted);
|
||||
|
||||
BinaryReaderEx brDecrypted = new BinaryReaderEx(sDecrypted,
|
||||
encNoBom, KLRes.FileCorrupted);
|
||||
encNoBom, strIncomplete);
|
||||
byte[] pbStoredStartBytes = brDecrypted.ReadBytes(32);
|
||||
|
||||
if((m_pbStreamStartBytes == null) || (m_pbStreamStartBytes.Length != 32))
|
||||
throw new InvalidDataException();
|
||||
throw new EndOfStreamException(strIncomplete);
|
||||
if(!MemUtil.ArraysEqual(pbStoredStartBytes, m_pbStreamStartBytes))
|
||||
throw new InvalidCompositeKeyException();
|
||||
|
||||
@ -124,10 +141,16 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
else // KDBX >= 4
|
||||
{
|
||||
byte[] pbStoredHash = MemUtil.Read(sHashing, 32);
|
||||
if((pbStoredHash == null) || (pbStoredHash.Length != 32))
|
||||
throw new EndOfStreamException(strIncomplete);
|
||||
if(!MemUtil.ArraysEqual(m_pbHashOfHeader, pbStoredHash))
|
||||
throw new InvalidDataException(KLRes.FileHeaderCorrupted);
|
||||
|
||||
byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
|
||||
byte[] pbStoredHmac = MemUtil.Read(sHashing, 32);
|
||||
if((pbStoredHmac == null) || (pbStoredHmac.Length != 32))
|
||||
throw new InvalidDataException();
|
||||
throw new EndOfStreamException(strIncomplete);
|
||||
if(!MemUtil.ArraysEqual(pbHeaderHmac, pbStoredHmac))
|
||||
throw new InvalidCompositeKeyException();
|
||||
|
||||
@ -148,6 +171,9 @@ namespace KeePassLib.Serialization
|
||||
lStreams.Add(sXml);
|
||||
}
|
||||
else sXml = sPlain;
|
||||
|
||||
if(m_uFileVersion >= FileVersion32_4)
|
||||
LoadInnerHeader(sXml); // Binary header before XML
|
||||
}
|
||||
else if(fmt == KdbxFormat.PlainXml)
|
||||
sXml = sHashing;
|
||||
@ -155,16 +181,15 @@ namespace KeePassLib.Serialization
|
||||
|
||||
if(fmt == KdbxFormat.Default)
|
||||
{
|
||||
if(m_pbProtectedStreamKey == null)
|
||||
if(m_pbInnerRandomStreamKey == null)
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new SecurityException("Invalid protected stream key!");
|
||||
throw new SecurityException("Invalid inner random stream key!");
|
||||
}
|
||||
|
||||
m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
|
||||
m_pbProtectedStreamKey);
|
||||
m_pbInnerRandomStreamKey);
|
||||
}
|
||||
else m_randomStream = null; // No random stream for plain-text files
|
||||
|
||||
#if KeePassDebug_WriteXml
|
||||
// FileStream fsOut = new FileStream("Raw.xml", FileMode.Create,
|
||||
@ -196,6 +221,12 @@ namespace KeePassLib.Serialization
|
||||
|
||||
CommonCleanUpRead(lStreams, sHashing);
|
||||
}
|
||||
|
||||
#if KDBX_BENCHMARK
|
||||
swTime.Stop();
|
||||
MessageService.ShowInfo("Loading KDBX took " +
|
||||
swTime.ElapsedMilliseconds.ToString() + " ms.");
|
||||
#endif
|
||||
}
|
||||
|
||||
private void CommonCleanUpRead(List<Stream> lStreams, HashingStreamEx sHashing)
|
||||
@ -206,6 +237,8 @@ namespace KeePassLib.Serialization
|
||||
m_pbHashOfFileOnDisk = sHashing.Hash;
|
||||
Debug.Assert(m_pbHashOfFileOnDisk != null);
|
||||
|
||||
CleanUpInnerRandomStream();
|
||||
|
||||
// Reset memory protection settings (to always use reasonable
|
||||
// defaults)
|
||||
m_pwDatabase.MemoryProtection = new MemoryProtectionConfig();
|
||||
@ -228,6 +261,10 @@ namespace KeePassLib.Serialization
|
||||
|
||||
private byte[] LoadHeader(BinaryReaderEx br)
|
||||
{
|
||||
string strPrevExcpText = br.ReadExceptionText;
|
||||
br.ReadExceptionText = KLRes.FileHeaderCorrupted + " " +
|
||||
KLRes.FileIncompleteExpc;
|
||||
|
||||
MemoryStream msHeader = new MemoryStream();
|
||||
Debug.Assert(br.CopyDataTo == null);
|
||||
br.CopyDataTo = msHeader;
|
||||
@ -262,7 +299,7 @@ namespace KeePassLib.Serialization
|
||||
byte[] pbHeader = msHeader.ToArray();
|
||||
msHeader.Close();
|
||||
|
||||
m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);
|
||||
br.ReadExceptionText = strPrevExcpText;
|
||||
return pbHeader;
|
||||
}
|
||||
|
||||
@ -275,21 +312,13 @@ namespace KeePassLib.Serialization
|
||||
|
||||
int cbSize;
|
||||
Debug.Assert(m_uFileVersion > 0);
|
||||
if(m_uFileVersion <= FileVersion32_3)
|
||||
if(m_uFileVersion < FileVersion32_4)
|
||||
cbSize = (int)MemUtil.BytesToUInt16(brSource.ReadBytes(2));
|
||||
else cbSize = MemUtil.BytesToInt32(brSource.ReadBytes(4));
|
||||
if(cbSize < 0) throw new FormatException(KLRes.FileCorrupted);
|
||||
|
||||
byte[] pbData = MemUtil.EmptyByteArray;
|
||||
if(cbSize > 0)
|
||||
{
|
||||
string strPrevExcpText = brSource.ReadExceptionText;
|
||||
brSource.ReadExceptionText = KLRes.FileHeaderEndEarly;
|
||||
|
||||
pbData = brSource.ReadBytes(cbSize);
|
||||
|
||||
brSource.ReadExceptionText = strPrevExcpText;
|
||||
}
|
||||
if(cbSize > 0) pbData = brSource.ReadBytes(cbSize);
|
||||
|
||||
bool bResult = true;
|
||||
KdbxHeaderFieldID kdbID = (KdbxHeaderFieldID)btFieldID;
|
||||
@ -314,6 +343,8 @@ namespace KeePassLib.Serialization
|
||||
|
||||
// Obsolete; for backward compatibility only
|
||||
case KdbxHeaderFieldID.TransformSeed:
|
||||
Debug.Assert(m_uFileVersion < FileVersion32_4);
|
||||
|
||||
AesKdf kdfS = new AesKdf();
|
||||
if(!m_pwDatabase.KdfParameters.KdfUuid.Equals(kdfS.Uuid))
|
||||
m_pwDatabase.KdfParameters = kdfS.GetDefaultParameters();
|
||||
@ -326,6 +357,8 @@ namespace KeePassLib.Serialization
|
||||
|
||||
// Obsolete; for backward compatibility only
|
||||
case KdbxHeaderFieldID.TransformRounds:
|
||||
Debug.Assert(m_uFileVersion < FileVersion32_4);
|
||||
|
||||
AesKdf kdfR = new AesKdf();
|
||||
if(!m_pwDatabase.KdfParameters.KdfUuid.Equals(kdfR.Uuid))
|
||||
m_pwDatabase.KdfParameters = kdfR.GetDefaultParameters();
|
||||
@ -339,17 +372,20 @@ namespace KeePassLib.Serialization
|
||||
m_pbEncryptionIV = pbData;
|
||||
break;
|
||||
|
||||
case KdbxHeaderFieldID.ProtectedStreamKey:
|
||||
m_pbProtectedStreamKey = pbData;
|
||||
case KdbxHeaderFieldID.InnerRandomStreamKey:
|
||||
Debug.Assert(m_uFileVersion < FileVersion32_4);
|
||||
Debug.Assert(m_pbInnerRandomStreamKey == null);
|
||||
m_pbInnerRandomStreamKey = pbData;
|
||||
CryptoRandom.Instance.AddEntropy(pbData);
|
||||
break;
|
||||
|
||||
case KdbxHeaderFieldID.StreamStartBytes:
|
||||
Debug.Assert(m_uFileVersion <= FileVersion32_3);
|
||||
Debug.Assert(m_uFileVersion < FileVersion32_4);
|
||||
m_pbStreamStartBytes = pbData;
|
||||
break;
|
||||
|
||||
case KdbxHeaderFieldID.InnerRandomStreamID:
|
||||
Debug.Assert(m_uFileVersion < FileVersion32_4);
|
||||
SetInnerRandomStreamID(pbData);
|
||||
break;
|
||||
|
||||
@ -373,6 +409,68 @@ namespace KeePassLib.Serialization
|
||||
return bResult;
|
||||
}
|
||||
|
||||
private void LoadInnerHeader(Stream s)
|
||||
{
|
||||
BinaryReaderEx br = new BinaryReaderEx(s, StrUtil.Utf8,
|
||||
KLRes.FileCorrupted + " " + KLRes.FileIncompleteExpc);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(!ReadInnerHeaderField(br)) break;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReadInnerHeaderField(BinaryReaderEx br)
|
||||
{
|
||||
Debug.Assert(br != null);
|
||||
if(br == null) throw new ArgumentNullException("br");
|
||||
|
||||
byte btFieldID = br.ReadByte();
|
||||
|
||||
int cbSize = MemUtil.BytesToInt32(br.ReadBytes(4));
|
||||
if(cbSize < 0) throw new FormatException(KLRes.FileCorrupted);
|
||||
|
||||
byte[] pbData = MemUtil.EmptyByteArray;
|
||||
if(cbSize > 0) pbData = br.ReadBytes(cbSize);
|
||||
|
||||
bool bResult = true;
|
||||
KdbxInnerHeaderFieldID kdbID = (KdbxInnerHeaderFieldID)btFieldID;
|
||||
switch(kdbID)
|
||||
{
|
||||
case KdbxInnerHeaderFieldID.EndOfHeader:
|
||||
bResult = false; // Returning false indicates end of header
|
||||
break;
|
||||
|
||||
case KdbxInnerHeaderFieldID.InnerRandomStreamID:
|
||||
SetInnerRandomStreamID(pbData);
|
||||
break;
|
||||
|
||||
case KdbxInnerHeaderFieldID.InnerRandomStreamKey:
|
||||
Debug.Assert(m_pbInnerRandomStreamKey == null);
|
||||
m_pbInnerRandomStreamKey = pbData;
|
||||
CryptoRandom.Instance.AddEntropy(pbData);
|
||||
break;
|
||||
|
||||
case KdbxInnerHeaderFieldID.Binary:
|
||||
if(pbData.Length < 1) throw new FormatException();
|
||||
KdbxBinaryFlags f = (KdbxBinaryFlags)pbData[0];
|
||||
bool bProt = ((f & KdbxBinaryFlags.Protected) != KdbxBinaryFlags.None);
|
||||
|
||||
ProtectedBinary pb = new ProtectedBinary(bProt, pbData,
|
||||
1, pbData.Length - 1);
|
||||
m_pbsBinaries.Add(pb);
|
||||
|
||||
if(bProt) MemUtil.ZeroByteArray(pbData);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
private void SetCipher(byte[] pbID)
|
||||
{
|
||||
if((pbID == null) || (pbID.Length != (int)PwUuid.UuidSize))
|
||||
@ -400,18 +498,33 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public static List<PwEntry> ReadEntries(PwDatabase pwDatabase, Stream msData)
|
||||
public static List<PwEntry> ReadEntries(Stream msData)
|
||||
{
|
||||
return ReadEntries(msData);
|
||||
return ReadEntries(msData, null, false);
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public static List<PwEntry> ReadEntries(PwDatabase pdContext, Stream msData)
|
||||
{
|
||||
return ReadEntries(msData, pdContext, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read entries from a stream.
|
||||
/// </summary>
|
||||
/// <param name="msData">Input stream to read the entries from.</param>
|
||||
/// <returns>Extracted entries.</returns>
|
||||
public static List<PwEntry> ReadEntries(Stream msData)
|
||||
/// <param name="pdContext">Context database (e.g. for storing icons).</param>
|
||||
/// <param name="bCopyIcons">If <c>true</c>, custom icons required by
|
||||
/// the loaded entries are copied to the context database.</param>
|
||||
/// <returns>Loaded entries.</returns>
|
||||
public static List<PwEntry> ReadEntries(Stream msData, PwDatabase pdContext,
|
||||
bool bCopyIcons)
|
||||
{
|
||||
List<PwEntry> lEntries = new List<PwEntry>();
|
||||
|
||||
if(msData == null) { Debug.Assert(false); return lEntries; }
|
||||
// pdContext may be null
|
||||
|
||||
/* KdbxFile f = new KdbxFile(pwDatabase);
|
||||
f.m_format = KdbxFormat.PlainXml;
|
||||
|
||||
@ -441,17 +554,37 @@ namespace KeePassLib.Serialization
|
||||
return vEntries; */
|
||||
|
||||
PwDatabase pd = new PwDatabase();
|
||||
pd.New(new IOConnectionInfo(), new CompositeKey());
|
||||
|
||||
KdbxFile f = new KdbxFile(pd);
|
||||
f.Load(msData, KdbxFormat.PlainXml, null);
|
||||
|
||||
List<PwEntry> vEntries = new List<PwEntry>();
|
||||
foreach(PwEntry pe in pd.RootGroup.Entries)
|
||||
{
|
||||
pe.SetUuid(new PwUuid(true), true);
|
||||
vEntries.Add(pe);
|
||||
lEntries.Add(pe);
|
||||
|
||||
if(bCopyIcons && (pdContext != null))
|
||||
{
|
||||
PwUuid pu = pe.CustomIconUuid;
|
||||
if(!pu.Equals(PwUuid.Zero))
|
||||
{
|
||||
int iSrc = pd.GetCustomIconIndex(pu);
|
||||
int iDst = pdContext.GetCustomIconIndex(pu);
|
||||
|
||||
if(iSrc < 0) { Debug.Assert(false); }
|
||||
else if(iDst < 0)
|
||||
{
|
||||
pdContext.CustomIcons.Add(pd.CustomIcons[iSrc]);
|
||||
|
||||
pdContext.Modified = true;
|
||||
pdContext.UINeedsIconUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vEntries;
|
||||
return lEntries;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -81,14 +81,22 @@ namespace KeePassLib.Serialization
|
||||
Debug.Assert(sSaveTo != null);
|
||||
if(sSaveTo == null) throw new ArgumentNullException("sSaveTo");
|
||||
|
||||
if(m_bUsedOnce)
|
||||
throw new InvalidOperationException("Do not reuse KdbxFile objects!");
|
||||
m_bUsedOnce = true;
|
||||
|
||||
m_format = fmt;
|
||||
m_slLogger = slLogger;
|
||||
|
||||
PwGroup pgRoot = (pgDataSource ?? m_pwDatabase.RootGroup);
|
||||
UTF8Encoding encNoBom = StrUtil.Utf8;
|
||||
CryptoRandom cr = CryptoRandom.Instance;
|
||||
byte[] pbCipherKey = null;
|
||||
byte[] pbHmacKey64 = null;
|
||||
|
||||
m_pbsBinaries.Clear();
|
||||
m_pbsBinaries.AddFrom(pgRoot);
|
||||
|
||||
List<Stream> lStreams = new List<Stream>();
|
||||
lStreams.Add(sSaveTo);
|
||||
|
||||
@ -114,20 +122,24 @@ namespace KeePassLib.Serialization
|
||||
"UUID: " + puKdf.ToHexString() + ".");
|
||||
kdf.Randomize(m_pwDatabase.KdfParameters);
|
||||
|
||||
if(m_uFileVersion <= FileVersion32_3)
|
||||
if(m_format == KdbxFormat.Default)
|
||||
{
|
||||
if(m_uFileVersion < FileVersion32_4)
|
||||
{
|
||||
m_craInnerRandomStream = CrsAlgorithm.Salsa20;
|
||||
m_pbProtectedStreamKey = cr.GetRandomBytes(32);
|
||||
m_pbInnerRandomStreamKey = cr.GetRandomBytes(32);
|
||||
}
|
||||
else // KDBX >= 4
|
||||
{
|
||||
m_craInnerRandomStream = CrsAlgorithm.ChaCha20;
|
||||
m_pbProtectedStreamKey = cr.GetRandomBytes(64);
|
||||
m_pbInnerRandomStreamKey = cr.GetRandomBytes(64);
|
||||
}
|
||||
m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
|
||||
m_pbProtectedStreamKey);
|
||||
|
||||
if(m_uFileVersion <= FileVersion32_3)
|
||||
m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
|
||||
m_pbInnerRandomStreamKey);
|
||||
}
|
||||
|
||||
if(m_uFileVersion < FileVersion32_4)
|
||||
m_pbStreamStartBytes = cr.GetRandomBytes(32);
|
||||
|
||||
Stream sXml;
|
||||
@ -142,7 +154,7 @@ namespace KeePassLib.Serialization
|
||||
ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);
|
||||
|
||||
Stream sPlain;
|
||||
if(m_uFileVersion <= FileVersion32_3)
|
||||
if(m_uFileVersion < FileVersion32_4)
|
||||
{
|
||||
Stream sEncrypted = EncryptStream(sHashing, iCipher,
|
||||
pbCipherKey, cbEncIV, true);
|
||||
@ -156,6 +168,9 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
else // KDBX >= 4
|
||||
{
|
||||
// For integrity checking (without knowing the master key)
|
||||
MemUtil.Write(sHashing, m_pbHashOfHeader);
|
||||
|
||||
byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
|
||||
MemUtil.Write(sHashing, pbHeaderHmac);
|
||||
|
||||
@ -176,6 +191,9 @@ namespace KeePassLib.Serialization
|
||||
lStreams.Add(sXml);
|
||||
}
|
||||
else sXml = sPlain;
|
||||
|
||||
if(m_uFileVersion >= FileVersion32_4)
|
||||
WriteInnerHeader(sXml); // Binary header before XML
|
||||
}
|
||||
else if(m_format == KdbxFormat.PlainXml)
|
||||
sXml = sHashing;
|
||||
@ -202,7 +220,7 @@ namespace KeePassLib.Serialization
|
||||
#endif
|
||||
m_xmlWriter = xw;
|
||||
|
||||
WriteDocument(pgDataSource);
|
||||
WriteDocument(pgRoot);
|
||||
|
||||
m_xmlWriter.Flush();
|
||||
m_xmlWriter.Close();
|
||||
@ -224,6 +242,8 @@ namespace KeePassLib.Serialization
|
||||
m_pbHashOfFileOnDisk = sHashing.Hash;
|
||||
Debug.Assert(m_pbHashOfFileOnDisk != null);
|
||||
|
||||
CleanUpInnerRandomStream();
|
||||
|
||||
m_xmlWriter = null;
|
||||
m_pbHashOfHeader = null;
|
||||
}
|
||||
@ -246,7 +266,7 @@ namespace KeePassLib.Serialization
|
||||
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.MasterSeed, m_pbMasterSeed);
|
||||
|
||||
if(m_uFileVersion <= FileVersion32_3)
|
||||
if(m_uFileVersion < FileVersion32_4)
|
||||
{
|
||||
Debug.Assert(m_pwDatabase.KdfParameters.KdfUuid.Equals(
|
||||
(new AesKdf()).Uuid));
|
||||
@ -263,15 +283,18 @@ namespace KeePassLib.Serialization
|
||||
if(m_pbEncryptionIV.Length > 0)
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.EncryptionIV, m_pbEncryptionIV);
|
||||
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.ProtectedStreamKey, m_pbProtectedStreamKey);
|
||||
if(m_uFileVersion < FileVersion32_4)
|
||||
{
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamKey,
|
||||
m_pbInnerRandomStreamKey);
|
||||
|
||||
if(m_uFileVersion <= FileVersion32_3)
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.StreamStartBytes,
|
||||
m_pbStreamStartBytes);
|
||||
|
||||
int nIrsID = (int)m_craInnerRandomStream;
|
||||
WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamID,
|
||||
MemUtil.Int32ToBytes(nIrsID));
|
||||
}
|
||||
|
||||
// Write public custom data only when there is at least one item,
|
||||
// because KDBX 3.1 didn't support this field yet
|
||||
@ -298,7 +321,7 @@ namespace KeePassLib.Serialization
|
||||
if(cb < 0) { Debug.Assert(false); throw new OutOfMemoryException(); }
|
||||
|
||||
Debug.Assert(m_uFileVersion > 0);
|
||||
if(m_uFileVersion <= FileVersion32_3)
|
||||
if(m_uFileVersion < FileVersion32_4)
|
||||
{
|
||||
if(cb > (int)ushort.MaxValue)
|
||||
{
|
||||
@ -310,21 +333,64 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
else MemUtil.Write(s, MemUtil.Int32ToBytes(cb));
|
||||
|
||||
if(cb > 0) s.Write(pb, 0, cb);
|
||||
MemUtil.Write(s, pb);
|
||||
}
|
||||
|
||||
private void WriteDocument(PwGroup pgDataSource)
|
||||
private void WriteInnerHeader(Stream s)
|
||||
{
|
||||
int nIrsID = (int)m_craInnerRandomStream;
|
||||
WriteInnerHeaderField(s, KdbxInnerHeaderFieldID.InnerRandomStreamID,
|
||||
MemUtil.Int32ToBytes(nIrsID), null);
|
||||
|
||||
WriteInnerHeaderField(s, KdbxInnerHeaderFieldID.InnerRandomStreamKey,
|
||||
m_pbInnerRandomStreamKey, null);
|
||||
|
||||
ProtectedBinary[] vBin = m_pbsBinaries.ToArray();
|
||||
for(int i = 0; i < vBin.Length; ++i)
|
||||
{
|
||||
ProtectedBinary pb = vBin[i];
|
||||
if(pb == null) throw new InvalidOperationException();
|
||||
|
||||
KdbxBinaryFlags f = KdbxBinaryFlags.None;
|
||||
if(pb.IsProtected) f |= KdbxBinaryFlags.Protected;
|
||||
|
||||
byte[] pbFlags = new byte[1] { (byte)f };
|
||||
byte[] pbData = pb.ReadData();
|
||||
|
||||
WriteInnerHeaderField(s, KdbxInnerHeaderFieldID.Binary,
|
||||
pbFlags, pbData);
|
||||
|
||||
if(pb.IsProtected) MemUtil.ZeroByteArray(pbData);
|
||||
}
|
||||
|
||||
WriteInnerHeaderField(s, KdbxInnerHeaderFieldID.EndOfHeader,
|
||||
null, null);
|
||||
}
|
||||
|
||||
private void WriteInnerHeaderField(Stream s, KdbxInnerHeaderFieldID kdbID,
|
||||
byte[] pbData1, byte[] pbData2)
|
||||
{
|
||||
s.WriteByte((byte)kdbID);
|
||||
|
||||
byte[] pb1 = (pbData1 ?? MemUtil.EmptyByteArray);
|
||||
byte[] pb2 = (pbData2 ?? MemUtil.EmptyByteArray);
|
||||
|
||||
int cb = pb1.Length + pb2.Length;
|
||||
if(cb < 0) { Debug.Assert(false); throw new OutOfMemoryException(); }
|
||||
|
||||
MemUtil.Write(s, MemUtil.Int32ToBytes(cb));
|
||||
MemUtil.Write(s, pb1);
|
||||
MemUtil.Write(s, pb2);
|
||||
}
|
||||
|
||||
private void WriteDocument(PwGroup pgRoot)
|
||||
{
|
||||
Debug.Assert(m_xmlWriter != null);
|
||||
if(m_xmlWriter == null) throw new InvalidOperationException();
|
||||
|
||||
PwGroup pgRoot = (pgDataSource ?? m_pwDatabase.RootGroup);
|
||||
|
||||
uint uNumGroups, uNumEntries, uCurEntry = 0;
|
||||
pgRoot.GetCounts(true, out uNumGroups, out uNumEntries);
|
||||
|
||||
BinPoolBuild(pgRoot);
|
||||
|
||||
m_xmlWriter.WriteStartDocument(true);
|
||||
m_xmlWriter.WriteStartElement(ElemDocNode);
|
||||
|
||||
@ -398,11 +464,11 @@ namespace KeePassLib.Serialization
|
||||
|
||||
WriteObject(ElemGenerator, PwDatabase.LocalizedAppName, false);
|
||||
|
||||
if((m_pbHashOfHeader != null) && (m_uFileVersion <= FileVersion32_3))
|
||||
if((m_pbHashOfHeader != null) && (m_uFileVersion < FileVersion32_4))
|
||||
WriteObject(ElemHeaderHash, Convert.ToBase64String(
|
||||
m_pbHashOfHeader), false);
|
||||
|
||||
if(m_uFileVersion > FileVersion32_3)
|
||||
if(m_uFileVersion >= FileVersion32_4)
|
||||
WriteObject(ElemSettingsChanged, m_pwDatabase.SettingsChanged);
|
||||
|
||||
WriteObject(ElemDbName, m_pwDatabase.Name, true);
|
||||
@ -416,6 +482,8 @@ namespace KeePassLib.Serialization
|
||||
WriteObject(ElemDbKeyChanged, m_pwDatabase.MasterKeyChanged);
|
||||
WriteObject(ElemDbKeyChangeRec, m_pwDatabase.MasterKeyChangeRec);
|
||||
WriteObject(ElemDbKeyChangeForce, m_pwDatabase.MasterKeyChangeForce);
|
||||
if(m_pwDatabase.MasterKeyChangeForceOnce)
|
||||
WriteObject(ElemDbKeyChangeForceOnce, true);
|
||||
|
||||
WriteList(ElemMemoryProt, m_pwDatabase.MemoryProtection);
|
||||
|
||||
@ -432,7 +500,9 @@ namespace KeePassLib.Serialization
|
||||
WriteObject(ElemLastSelectedGroup, m_pwDatabase.LastSelectedGroup);
|
||||
WriteObject(ElemLastTopVisibleGroup, m_pwDatabase.LastTopVisibleGroup);
|
||||
|
||||
if((m_format != KdbxFormat.Default) || (m_uFileVersion < FileVersion32_4))
|
||||
WriteBinPool();
|
||||
|
||||
WriteList(ElemCustomData, m_pwDatabase.CustomData);
|
||||
|
||||
m_xmlWriter.WriteEndElement();
|
||||
@ -700,8 +770,28 @@ namespace KeePassLib.Serialization
|
||||
private void WriteObject(string name, DateTime value)
|
||||
{
|
||||
Debug.Assert(name != null);
|
||||
Debug.Assert(value.Kind == DateTimeKind.Utc);
|
||||
|
||||
WriteObject(name, TimeUtil.SerializeUtc(value), false);
|
||||
// Cf. ReadTime
|
||||
if((m_format == KdbxFormat.Default) && (m_uFileVersion >= FileVersion32_4))
|
||||
{
|
||||
DateTime dt = TimeUtil.ToUtc(value, false);
|
||||
|
||||
// DateTime dtBase = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
// dt -= new TimeSpan(dtBase.Ticks);
|
||||
|
||||
// WriteObject(name, dt.ToBinary());
|
||||
|
||||
// dt = TimeUtil.RoundToMultOf2PowLess1s(dt);
|
||||
// long lBin = dt.ToBinary();
|
||||
|
||||
long lSec = dt.Ticks / TimeSpan.TicksPerSecond;
|
||||
// WriteObject(name, lSec);
|
||||
|
||||
byte[] pb = MemUtil.Int64ToBytes(lSec);
|
||||
WriteObject(name, Convert.ToBase64String(pb), false);
|
||||
}
|
||||
else WriteObject(name, TimeUtil.SerializeUtc(value), false);
|
||||
}
|
||||
|
||||
private void WriteObject(string name, string strKeyName,
|
||||
@ -748,7 +838,7 @@ namespace KeePassLib.Serialization
|
||||
bProtected = m_pwDatabase.MemoryProtection.ProtectNotes;
|
||||
}
|
||||
|
||||
if(bProtected && (m_format != KdbxFormat.PlainXml))
|
||||
if(bProtected && (m_format == KdbxFormat.Default))
|
||||
{
|
||||
m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);
|
||||
|
||||
@ -823,11 +913,15 @@ namespace KeePassLib.Serialization
|
||||
m_xmlWriter.WriteEndElement();
|
||||
m_xmlWriter.WriteStartElement(ElemValue);
|
||||
|
||||
string strRef = (bAllowRef ? BinPoolFind(value) : null);
|
||||
if(strRef != null)
|
||||
string strRef = null;
|
||||
if(bAllowRef)
|
||||
{
|
||||
m_xmlWriter.WriteAttributeString(AttrRef, strRef);
|
||||
int iRef = m_pbsBinaries.Find(value);
|
||||
if(iRef >= 0) strRef = iRef.ToString(NumberFormatInfo.InvariantInfo);
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
if(strRef != null)
|
||||
m_xmlWriter.WriteAttributeString(AttrRef, strRef);
|
||||
else SubWriteValue(value);
|
||||
|
||||
m_xmlWriter.WriteEndElement(); // ElemValue
|
||||
@ -836,7 +930,7 @@ namespace KeePassLib.Serialization
|
||||
|
||||
private void SubWriteValue(ProtectedBinary value)
|
||||
{
|
||||
if(value.IsProtected && (m_format != KdbxFormat.PlainXml))
|
||||
if(value.IsProtected && (m_format == KdbxFormat.Default))
|
||||
{
|
||||
m_xmlWriter.WriteAttributeString(AttrProtected, ValTrue);
|
||||
|
||||
@ -846,18 +940,26 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
|
||||
if(m_pwDatabase.Compression != PwCompressionAlgorithm.None)
|
||||
{
|
||||
m_xmlWriter.WriteAttributeString(AttrCompressed, ValTrue);
|
||||
|
||||
byte[] pbRaw = value.ReadData();
|
||||
byte[] pbCmp = MemUtil.Compress(pbRaw);
|
||||
m_xmlWriter.WriteBase64(pbCmp, 0, pbCmp.Length);
|
||||
|
||||
if(value.IsProtected)
|
||||
{
|
||||
MemUtil.ZeroByteArray(pbRaw);
|
||||
MemUtil.ZeroByteArray(pbCmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] pbRaw = value.ReadData();
|
||||
m_xmlWriter.WriteBase64(pbRaw, 0, pbRaw.Length);
|
||||
|
||||
if(value.IsProtected) MemUtil.ZeroByteArray(pbRaw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -877,11 +979,13 @@ namespace KeePassLib.Serialization
|
||||
{
|
||||
m_xmlWriter.WriteStartElement(ElemBinaries);
|
||||
|
||||
foreach(KeyValuePair<string, ProtectedBinary> kvp in m_dictBinPool)
|
||||
ProtectedBinary[] v = m_pbsBinaries.ToArray();
|
||||
for(int i = 0; i < v.Length; ++i)
|
||||
{
|
||||
m_xmlWriter.WriteStartElement(ElemBinary);
|
||||
m_xmlWriter.WriteAttributeString(AttrId, kvp.Key);
|
||||
SubWriteValue(kvp.Value);
|
||||
m_xmlWriter.WriteAttributeString(AttrId,
|
||||
i.ToString(NumberFormatInfo.InvariantInfo));
|
||||
SubWriteValue(v[i]);
|
||||
m_xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
@ -889,21 +993,18 @@ namespace KeePassLib.Serialization
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public static bool WriteEntries(Stream msOutput, PwDatabase pwDatabase,
|
||||
PwEntry[] vEntries)
|
||||
{
|
||||
return WriteEntries(msOutput, vEntries);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write entries to a stream.
|
||||
/// </summary>
|
||||
/// <param name="msOutput">Output stream to which the entries will be written.</param>
|
||||
/// <param name="vEntries">Entries to serialize.</param>
|
||||
/// <returns>Returns <c>true</c>, if the entries were written successfully
|
||||
/// to the stream.</returns>
|
||||
public static bool WriteEntries(Stream msOutput, PwEntry[] vEntries)
|
||||
{
|
||||
return WriteEntries(msOutput, null, vEntries);
|
||||
}
|
||||
|
||||
public static bool WriteEntries(Stream msOutput, PwDatabase pdContext,
|
||||
PwEntry[] vEntries)
|
||||
{
|
||||
if(msOutput == null) { Debug.Assert(false); return false; }
|
||||
// pdContext may be null
|
||||
if(vEntries == null) { Debug.Assert(false); return false; }
|
||||
|
||||
/* KdbxFile f = new KdbxFile(pwDatabase);
|
||||
f.m_format = KdbxFormat.PlainXml;
|
||||
|
||||
@ -934,8 +1035,27 @@ namespace KeePassLib.Serialization
|
||||
PwDatabase pd = new PwDatabase();
|
||||
pd.New(new IOConnectionInfo(), new CompositeKey());
|
||||
|
||||
foreach(PwEntry peCopy in vEntries)
|
||||
pd.RootGroup.AddEntry(peCopy.CloneDeep(), true);
|
||||
PwGroup pg = pd.RootGroup;
|
||||
if(pg == null) { Debug.Assert(false); return false; }
|
||||
|
||||
foreach(PwEntry pe in vEntries)
|
||||
{
|
||||
PwUuid pu = pe.CustomIconUuid;
|
||||
if(!pu.Equals(PwUuid.Zero) && (pd.GetCustomIconIndex(pu) < 0))
|
||||
{
|
||||
int i = -1;
|
||||
if(pdContext != null) i = pdContext.GetCustomIconIndex(pu);
|
||||
if(i >= 0)
|
||||
{
|
||||
PwCustomIcon ci = pdContext.CustomIcons[i];
|
||||
pd.CustomIcons.Add(ci);
|
||||
}
|
||||
else { Debug.Assert(pdContext == null); }
|
||||
}
|
||||
|
||||
PwEntry peCopy = pe.CloneDeep();
|
||||
pg.AddEntry(peCopy, true);
|
||||
}
|
||||
|
||||
KdbxFile f = new KdbxFile(pd);
|
||||
f.Save(msOutput, null, KdbxFormat.PlainXml, null);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -82,7 +82,9 @@ namespace KeePassLib.Serialization
|
||||
/// file version is too high), the last 2 bytes are informational.
|
||||
/// </summary>
|
||||
private const uint FileVersion32 = 0x00040000;
|
||||
private const uint FileVersion32_3 = 0x00030001; // Old format
|
||||
|
||||
internal const uint FileVersion32_4 = 0x00040000; // First of 4.x series
|
||||
internal const uint FileVersion32_3 = 0x00030001; // Old format 3.1
|
||||
|
||||
private const uint FileVersionCriticalMask = 0xFFFF0000;
|
||||
|
||||
@ -113,6 +115,7 @@ namespace KeePassLib.Serialization
|
||||
private const string ElemDbKeyChanged = "MasterKeyChanged";
|
||||
private const string ElemDbKeyChangeRec = "MasterKeyChangeRec";
|
||||
private const string ElemDbKeyChangeForce = "MasterKeyChangeForce";
|
||||
private const string ElemDbKeyChangeForceOnce = "MasterKeyChangeForceOnce";
|
||||
private const string ElemRecycleBinEnabled = "RecycleBinEnabled";
|
||||
private const string ElemRecycleBinUuid = "RecycleBinUUID";
|
||||
private const string ElemRecycleBinChanged = "RecycleBinChanged";
|
||||
@ -196,6 +199,7 @@ namespace KeePassLib.Serialization
|
||||
private const string ElemStringDictExItem = "Item";
|
||||
|
||||
private PwDatabase m_pwDatabase; // Not null, see constructor
|
||||
private bool m_bUsedOnce = false;
|
||||
|
||||
private XmlWriter m_xmlWriter = null;
|
||||
private CryptoRandomStream m_randomStream = null;
|
||||
@ -206,20 +210,19 @@ namespace KeePassLib.Serialization
|
||||
private byte[] m_pbMasterSeed = null;
|
||||
// private byte[] m_pbTransformSeed = null;
|
||||
private byte[] m_pbEncryptionIV = null;
|
||||
private byte[] m_pbProtectedStreamKey = null;
|
||||
private byte[] m_pbStreamStartBytes = null;
|
||||
|
||||
// ArcFourVariant only for backward compatibility; KeePass defaults
|
||||
// to a more secure algorithm when *writing* databases
|
||||
private CrsAlgorithm m_craInnerRandomStream = CrsAlgorithm.ArcFourVariant;
|
||||
private byte[] m_pbInnerRandomStreamKey = null;
|
||||
|
||||
private Dictionary<string, ProtectedBinary> m_dictBinPool =
|
||||
new Dictionary<string, ProtectedBinary>();
|
||||
private ProtectedBinarySet m_pbsBinaries = new ProtectedBinarySet();
|
||||
|
||||
private byte[] m_pbHashOfHeader = null;
|
||||
private byte[] m_pbHashOfFileOnDisk = null;
|
||||
|
||||
private readonly DateTime m_dtNow = DateTime.Now; // Cache current time
|
||||
private readonly DateTime m_dtNow = DateTime.UtcNow; // Cache current time
|
||||
|
||||
private const uint NeutralLanguageOffset = 0x100000; // 2^20, see 32-bit Unicode specs
|
||||
private const uint NeutralLanguageIDSec = 0x7DC5C; // See 32-bit Unicode specs
|
||||
@ -236,13 +239,29 @@ namespace KeePassLib.Serialization
|
||||
TransformSeed = 5, // KDBX 3.1, for backward compatibility only
|
||||
TransformRounds = 6, // KDBX 3.1, for backward compatibility only
|
||||
EncryptionIV = 7,
|
||||
ProtectedStreamKey = 8,
|
||||
InnerRandomStreamKey = 8, // KDBX 3.1, for backward compatibility only
|
||||
StreamStartBytes = 9, // KDBX 3.1, for backward compatibility only
|
||||
InnerRandomStreamID = 10,
|
||||
KdfParameters = 11, // KDBX 4
|
||||
InnerRandomStreamID = 10, // KDBX 3.1, for backward compatibility only
|
||||
KdfParameters = 11, // KDBX 4, superseding Transform*
|
||||
PublicCustomData = 12 // KDBX 4
|
||||
}
|
||||
|
||||
// Inner header in KDBX >= 4 files
|
||||
private enum KdbxInnerHeaderFieldID : byte
|
||||
{
|
||||
EndOfHeader = 0,
|
||||
InnerRandomStreamID = 1, // Supersedes KdbxHeaderFieldID.InnerRandomStreamID
|
||||
InnerRandomStreamKey = 2, // Supersedes KdbxHeaderFieldID.InnerRandomStreamKey
|
||||
Binary = 3
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum KdbxBinaryFlags : byte
|
||||
{
|
||||
None = 0,
|
||||
Protected = 1
|
||||
}
|
||||
|
||||
public byte[] HashOfFileOnDisk
|
||||
{
|
||||
get { return m_pbHashOfFileOnDisk; }
|
||||
@ -255,6 +274,13 @@ namespace KeePassLib.Serialization
|
||||
set { m_bRepairMode = value; }
|
||||
}
|
||||
|
||||
private uint m_uForceVersion = 0;
|
||||
internal uint ForceVersion
|
||||
{
|
||||
get { return m_uForceVersion; }
|
||||
set { m_uForceVersion = value; }
|
||||
}
|
||||
|
||||
private string m_strDetachBins = null;
|
||||
/// <summary>
|
||||
/// Detach binaries when opening a file. If this isn't <c>null</c>,
|
||||
@ -301,6 +327,10 @@ namespace KeePassLib.Serialization
|
||||
|
||||
private uint GetMinKdbxVersion()
|
||||
{
|
||||
if(m_uForceVersion != 0) return m_uForceVersion;
|
||||
|
||||
// See also KeePassKdb2x3.Export (KDBX 3.1 export module)
|
||||
|
||||
AesKdf kdfAes = new AesKdf();
|
||||
if(!kdfAes.Uuid.Equals(m_pwDatabase.KdfParameters.KdfUuid))
|
||||
return FileVersion32;
|
||||
@ -445,64 +475,12 @@ namespace KeePassLib.Serialization
|
||||
// Do not clear the list
|
||||
}
|
||||
|
||||
private void BinPoolBuild(PwGroup pgDataSource)
|
||||
private void CleanUpInnerRandomStream()
|
||||
{
|
||||
m_dictBinPool = new Dictionary<string, ProtectedBinary>();
|
||||
if(m_randomStream != null) m_randomStream.Dispose();
|
||||
|
||||
if(pgDataSource == null) { Debug.Assert(false); return; }
|
||||
|
||||
EntryHandler eh = delegate(PwEntry pe)
|
||||
{
|
||||
foreach(PwEntry peHistory in pe.History)
|
||||
{
|
||||
BinPoolAdd(peHistory.Binaries);
|
||||
}
|
||||
|
||||
BinPoolAdd(pe.Binaries);
|
||||
return true;
|
||||
};
|
||||
|
||||
pgDataSource.TraverseTree(TraversalMethod.PreOrder, null, eh);
|
||||
}
|
||||
|
||||
private void BinPoolAdd(ProtectedBinaryDictionary dict)
|
||||
{
|
||||
foreach(KeyValuePair<string, ProtectedBinary> kvp in dict)
|
||||
{
|
||||
BinPoolAdd(kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void BinPoolAdd(ProtectedBinary pb)
|
||||
{
|
||||
if(pb == null) { Debug.Assert(false); return; }
|
||||
|
||||
if(BinPoolFind(pb) != null) return; // Exists already
|
||||
|
||||
m_dictBinPool.Add(m_dictBinPool.Count.ToString(
|
||||
NumberFormatInfo.InvariantInfo), pb);
|
||||
}
|
||||
|
||||
private string BinPoolFind(ProtectedBinary pb)
|
||||
{
|
||||
if(pb == null) { Debug.Assert(false); return null; }
|
||||
|
||||
foreach(KeyValuePair<string, ProtectedBinary> kvp in m_dictBinPool)
|
||||
{
|
||||
if(pb.Equals(kvp.Value)) return kvp.Key;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ProtectedBinary BinPoolGet(string strKey)
|
||||
{
|
||||
if(strKey == null) { Debug.Assert(false); return null; }
|
||||
|
||||
ProtectedBinary pb;
|
||||
if(m_dictBinPool.TryGetValue(strKey, out pb)) return pb;
|
||||
|
||||
return null;
|
||||
if(m_pbInnerRandomStreamKey != null)
|
||||
MemUtil.ZeroByteArray(m_pbInnerRandomStreamKey);
|
||||
}
|
||||
|
||||
private static void SaveBinary(string strName, ProtectedBinary pb,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -335,7 +335,7 @@ namespace KeePassLib.Translation
|
||||
byte[] pb = StrUtil.Utf8.GetBytes(sb.ToString());
|
||||
byte[] pbSha = CryptoUtil.HashSha256(pb);
|
||||
|
||||
// Also see MatchHash
|
||||
// See also MatchHash
|
||||
return "v1:" + Convert.ToBase64String(pbSha, 0, 3,
|
||||
Base64FormattingOptions.None);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -57,7 +57,7 @@ namespace KeePassLib.Utility
|
||||
string strPath = strTemp + strPrefix + "-";
|
||||
Debug.Assert(strPath.IndexOf('/') < 0);
|
||||
|
||||
DateTime dtNow = DateTime.Now;
|
||||
DateTime dtNow = DateTime.UtcNow;
|
||||
string strTime = dtNow.ToString("s");
|
||||
strTime = strTime.Replace('T', '-');
|
||||
strTime = strTime.Replace(':', '-');
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -172,14 +172,13 @@ namespace KeePassLib.Utility
|
||||
img = GfxUtil.LoadImage(pbImg);
|
||||
else
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(pb, false);
|
||||
try
|
||||
using(MemoryStream ms = new MemoryStream(pb, false))
|
||||
{
|
||||
using(Icon ico = new Icon(ms, gi.Width, gi.Height))
|
||||
{
|
||||
Icon ico = new Icon(ms, gi.Width, gi.Height);
|
||||
img = ico.ToBitmap();
|
||||
ico.Dispose();
|
||||
}
|
||||
finally { ms.Close(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
@ -406,10 +405,12 @@ namespace KeePassLib.Utility
|
||||
|
||||
foreach(int q in v)
|
||||
{
|
||||
Image img = ScaleImage(imgIcon, q, q,
|
||||
ScaleTransformFlags.UIIcon);
|
||||
using(Image img = ScaleImage(imgIcon, q, q,
|
||||
ScaleTransformFlags.UIIcon))
|
||||
{
|
||||
g.DrawImageUnscaled(img, x, y);
|
||||
img.Dispose();
|
||||
}
|
||||
|
||||
x += q + 8;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -24,6 +24,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
|
||||
#if !KeePassUAP
|
||||
@ -37,6 +38,8 @@ namespace KeePassLib.Utility
|
||||
public static class MonoWorkarounds
|
||||
{
|
||||
private static Dictionary<uint, bool> m_dForceReq = new Dictionary<uint, bool>();
|
||||
private static Thread m_thFixClip = null;
|
||||
// private static Predicate<IntPtr> m_fOwnWindow = null;
|
||||
|
||||
private static bool? m_bReq = null;
|
||||
public static bool IsRequired()
|
||||
@ -56,6 +59,7 @@ namespace KeePassLib.Utility
|
||||
// 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.
|
||||
@ -70,6 +74,16 @@ namespace KeePassLib.Utility
|
||||
// 1418:
|
||||
// Minimizing a form while loading it doesn't work.
|
||||
// https://sourceforge.net/p/keepass/bugs/1418/
|
||||
// 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/
|
||||
// 2139:
|
||||
// Shortcut keys are ignored.
|
||||
// https://sourceforge.net/p/keepass/feature-requests/2139/
|
||||
@ -149,6 +163,113 @@ namespace KeePassLib.Utility
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Initialize()
|
||||
{
|
||||
Terminate();
|
||||
|
||||
// m_fOwnWindow = fOwnWindow;
|
||||
|
||||
if(IsRequired(1530))
|
||||
{
|
||||
try
|
||||
{
|
||||
ThreadStart ts = new ThreadStart(MonoWorkarounds.FixClipThread);
|
||||
m_thFixClip = new Thread(ts);
|
||||
m_thFixClip.Start();
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Terminate()
|
||||
{
|
||||
if(m_thFixClip != null)
|
||||
{
|
||||
try { m_thFixClip.Abort(); }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
m_thFixClip = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FixClipThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
#if !KeePassUAP
|
||||
const string strXSel = "xsel";
|
||||
const AppRunFlags rfW = AppRunFlags.WaitForExit;
|
||||
|
||||
string strLast = null;
|
||||
while(true)
|
||||
{
|
||||
string str = NativeLib.RunConsoleApp(strXSel,
|
||||
"--output --clipboard");
|
||||
if(str == null) return; // 'xsel' not installed
|
||||
|
||||
if(str != strLast)
|
||||
{
|
||||
if(NeedClipboardWorkaround())
|
||||
NativeLib.RunConsoleApp(strXSel,
|
||||
"--input --clipboard", str, rfW);
|
||||
|
||||
strLast = str;
|
||||
}
|
||||
|
||||
Thread.Sleep(250);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch(ThreadAbortException)
|
||||
{
|
||||
try { Thread.ResetAbort(); }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
finally { m_thFixClip = null; }
|
||||
}
|
||||
|
||||
private static bool NeedClipboardWorkaround()
|
||||
{
|
||||
const bool bDef = true;
|
||||
|
||||
try
|
||||
{
|
||||
string strHandle = (NativeLib.RunConsoleApp("xdotool",
|
||||
"getactivewindow") ?? string.Empty).Trim();
|
||||
if(strHandle.Length == 0) return bDef;
|
||||
|
||||
// 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 = m_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;
|
||||
|
||||
// Workaround for Remmina
|
||||
if(strWmClass.IndexOf("\"Remmina\"",
|
||||
StrUtil.CaseIgnoreCmp) >= 0) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
catch(ThreadAbortException) { throw; }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
return bDef;
|
||||
}
|
||||
|
||||
#if !KeePassUAP
|
||||
public static void ApplyTo(Form f)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -669,7 +669,8 @@ namespace KeePassLib.Utility
|
||||
return DateTime.TryParse(str, out dt);
|
||||
#else
|
||||
try { dt = DateTime.Parse(str); return true; }
|
||||
catch(Exception) { dt = DateTime.MinValue; return false; }
|
||||
catch(Exception) { dt = DateTime.UtcNow; }
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1732,5 +1733,16 @@ namespace KeePassLib.Utility
|
||||
|
||||
return iCount;
|
||||
}
|
||||
|
||||
internal static string ReplaceNulls(string str)
|
||||
{
|
||||
if(str == null) { Debug.Assert(false); return null; }
|
||||
|
||||
if(str.IndexOf('\0') < 0) return str;
|
||||
|
||||
// Replacing null characters by spaces is the
|
||||
// behavior of Notepad (on Windows 10)
|
||||
return str.Replace('\0', ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -38,11 +38,18 @@ namespace KeePassLib.Utility
|
||||
/// </summary>
|
||||
public const int PwTimeLength = 7;
|
||||
|
||||
public static readonly DateTime SafeMinValueUtc = new DateTime(
|
||||
DateTime.MinValue.Ticks + TimeSpan.TicksPerDay, DateTimeKind.Utc);
|
||||
public static readonly DateTime SafeMaxValueUtc = new DateTime(
|
||||
DateTime.MaxValue.Ticks - TimeSpan.TicksPerDay, DateTimeKind.Utc);
|
||||
|
||||
#if !KeePassLibSD
|
||||
private static string m_strDtfStd = null;
|
||||
private static string m_strDtfDate = null;
|
||||
#endif
|
||||
|
||||
// private static long m_lTicks2PowLess1s = 0;
|
||||
|
||||
private static DateTime? m_odtUnixRoot = null;
|
||||
public static DateTime UnixRoot
|
||||
{
|
||||
@ -50,8 +57,8 @@ namespace KeePassLib.Utility
|
||||
{
|
||||
if(m_odtUnixRoot.HasValue) return m_odtUnixRoot.Value;
|
||||
|
||||
DateTime dtRoot = (new DateTime(1970, 1, 1, 0, 0, 0, 0,
|
||||
DateTimeKind.Utc)).ToLocalTime();
|
||||
DateTime dtRoot = new DateTime(1970, 1, 1, 0, 0, 0, 0,
|
||||
DateTimeKind.Utc);
|
||||
|
||||
m_odtUnixRoot = dtRoot;
|
||||
return dtRoot;
|
||||
@ -63,10 +70,11 @@ namespace KeePassLib.Utility
|
||||
/// year 12 bits, month 4 bits, day 5 bits, hour 5 bits, minute 6
|
||||
/// bits, second 6 bits.
|
||||
/// </summary>
|
||||
/// <param name="dt"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete]
|
||||
public static byte[] PackTime(DateTime dt)
|
||||
{
|
||||
dt = ToLocal(dt, true);
|
||||
|
||||
byte[] pb = new byte[5];
|
||||
|
||||
// Pack time to 5 byte structure:
|
||||
@ -88,6 +96,7 @@ namespace KeePassLib.Utility
|
||||
/// </summary>
|
||||
/// <param name="pb">Packed time, 5 bytes.</param>
|
||||
/// <returns>Unpacked <c>DateTime</c> object.</returns>
|
||||
[Obsolete]
|
||||
public static DateTime UnpackTime(byte[] pb)
|
||||
{
|
||||
Debug.Assert((pb != null) && (pb.Length == 5));
|
||||
@ -104,7 +113,8 @@ namespace KeePassLib.Utility
|
||||
int nMinute = ((n4 & 0x0000000F) << 2) | (n5 >> 6);
|
||||
int nSecond = n5 & 0x0000003F;
|
||||
|
||||
return new DateTime(nYear, nMonth, nDay, nHour, nMinute, nSecond);
|
||||
return (new DateTime(nYear, nMonth, nDay, nHour, nMinute,
|
||||
nSecond, DateTimeKind.Local)).ToUniversalTime();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -112,10 +122,13 @@ namespace KeePassLib.Utility
|
||||
/// </summary>
|
||||
/// <param name="dt">Object to be encoded.</param>
|
||||
/// <returns>Packed time, 7 bytes (<c>PW_TIME</c>).</returns>
|
||||
[Obsolete]
|
||||
public static byte[] PackPwTime(DateTime dt)
|
||||
{
|
||||
Debug.Assert(PwTimeLength == 7);
|
||||
|
||||
dt = ToLocal(dt, true);
|
||||
|
||||
byte[] pb = new byte[7];
|
||||
pb[0] = (byte)(dt.Year & 0xFF);
|
||||
pb[1] = (byte)(dt.Year >> 8);
|
||||
@ -133,6 +146,7 @@ namespace KeePassLib.Utility
|
||||
/// </summary>
|
||||
/// <param name="pb">Packed time, 7 bytes.</param>
|
||||
/// <returns>Unpacked <c>DateTime</c> object.</returns>
|
||||
[Obsolete]
|
||||
public static DateTime UnpackPwTime(byte[] pb)
|
||||
{
|
||||
Debug.Assert(PwTimeLength == 7);
|
||||
@ -140,8 +154,8 @@ namespace KeePassLib.Utility
|
||||
Debug.Assert(pb != null); if(pb == null) throw new ArgumentNullException("pb");
|
||||
Debug.Assert(pb.Length == 7); if(pb.Length != 7) throw new ArgumentException();
|
||||
|
||||
return new DateTime(((int)pb[1] << 8) | (int)pb[0], (int)pb[2], (int)pb[3],
|
||||
(int)pb[4], (int)pb[5], (int)pb[6]);
|
||||
return (new DateTime(((int)pb[1] << 8) | (int)pb[0], (int)pb[2], (int)pb[3],
|
||||
(int)pb[4], (int)pb[5], (int)pb[6], DateTimeKind.Local)).ToUniversalTime();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -151,23 +165,32 @@ namespace KeePassLib.Utility
|
||||
/// <returns>String representing the specified <c>DateTime</c> object.</returns>
|
||||
public static string ToDisplayString(DateTime dt)
|
||||
{
|
||||
return dt.ToString();
|
||||
return ToLocal(dt, true).ToString();
|
||||
}
|
||||
|
||||
public static string ToDisplayStringDateOnly(DateTime dt)
|
||||
{
|
||||
return dt.ToString("d");
|
||||
return ToLocal(dt, true).ToString("d");
|
||||
}
|
||||
|
||||
public static DateTime FromDisplayString(string strDisplay)
|
||||
{
|
||||
DateTime dt;
|
||||
if(FromDisplayStringEx(strDisplay, out dt)) return dt;
|
||||
return DateTime.Now;
|
||||
}
|
||||
|
||||
public static bool FromDisplayStringEx(string strDisplay, out DateTime dt)
|
||||
{
|
||||
#if KeePassLibSD
|
||||
try { dt = DateTime.Parse(strDisplay); return dt; }
|
||||
try { dt = ToLocal(DateTime.Parse(strDisplay), true); return true; }
|
||||
catch(Exception) { }
|
||||
#else
|
||||
if(DateTime.TryParse(strDisplay, out dt)) return dt;
|
||||
if(DateTime.TryParse(strDisplay, out dt))
|
||||
{
|
||||
dt = ToLocal(dt, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// For some custom formats specified using the Control Panel,
|
||||
// DateTime.ToString returns the correct string, but
|
||||
@ -175,19 +198,25 @@ namespace KeePassLib.Utility
|
||||
// https://sourceforge.net/p/keepass/discussion/329221/thread/3a225b29/?limit=25&page=1#c6ae
|
||||
if((m_strDtfStd == null) || (m_strDtfDate == null))
|
||||
{
|
||||
DateTime dtUni = new DateTime(2111, 3, 4, 5, 6, 7);
|
||||
DateTime dtUni = new DateTime(2111, 3, 4, 5, 6, 7, DateTimeKind.Local);
|
||||
m_strDtfStd = DeriveCustomFormat(ToDisplayString(dtUni), dtUni);
|
||||
m_strDtfDate = DeriveCustomFormat(ToDisplayStringDateOnly(dtUni), dtUni);
|
||||
}
|
||||
const DateTimeStyles dts = DateTimeStyles.AllowWhiteSpaces;
|
||||
if(DateTime.TryParseExact(strDisplay, m_strDtfStd, null, dts, out dt))
|
||||
return dt;
|
||||
{
|
||||
dt = ToLocal(dt, true);
|
||||
return true;
|
||||
}
|
||||
if(DateTime.TryParseExact(strDisplay, m_strDtfDate, null, dts, out dt))
|
||||
return dt;
|
||||
{
|
||||
dt = ToLocal(dt, true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
Debug.Assert(false);
|
||||
return DateTime.Now;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !KeePassLibSD
|
||||
@ -277,8 +306,10 @@ namespace KeePassLib.Utility
|
||||
|
||||
public static string SerializeUtc(DateTime dt)
|
||||
{
|
||||
string str = dt.ToUniversalTime().ToString("s");
|
||||
if(str.EndsWith("Z") == false) str += "Z";
|
||||
Debug.Assert(dt.Kind != DateTimeKind.Unspecified);
|
||||
|
||||
string str = ToUtc(dt, false).ToString("s");
|
||||
if(!str.EndsWith("Z")) str += "Z";
|
||||
return str;
|
||||
}
|
||||
|
||||
@ -289,13 +320,13 @@ namespace KeePassLib.Utility
|
||||
if(str.EndsWith("Z")) str = str.Substring(0, str.Length - 1);
|
||||
|
||||
bool bResult = StrUtil.TryParseDateTime(str, out dt);
|
||||
if(bResult) dt = dt.ToLocalTime();
|
||||
if(bResult) dt = ToUtc(dt, true);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
public static double SerializeUnix(DateTime dt)
|
||||
{
|
||||
return (dt - TimeUtil.UnixRoot).TotalSeconds;
|
||||
return (ToUtc(dt, false) - TimeUtil.UnixRoot).TotalSeconds;
|
||||
}
|
||||
|
||||
public static DateTime ConvertUnixTime(double dtUnix)
|
||||
@ -303,20 +334,26 @@ namespace KeePassLib.Utility
|
||||
try { return TimeUtil.UnixRoot.AddSeconds(dtUnix); }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
|
||||
return DateTime.Now;
|
||||
return DateTime.UtcNow;
|
||||
}
|
||||
|
||||
#if !KeePassLibSD
|
||||
[Obsolete]
|
||||
public static DateTime? ParseUSTextDate(string strDate)
|
||||
{
|
||||
return ParseUSTextDate(strDate, DateTimeKind.Unspecified);
|
||||
}
|
||||
|
||||
private static string[] m_vUSMonths = null;
|
||||
/// <summary>
|
||||
/// Parse a US textual date string, like e.g. "January 02, 2012".
|
||||
/// </summary>
|
||||
public static DateTime? ParseUSTextDate(string strDate)
|
||||
public static DateTime? ParseUSTextDate(string strDate, DateTimeKind k)
|
||||
{
|
||||
if(strDate == null) { Debug.Assert(false); return null; }
|
||||
|
||||
if(m_vUSMonths == null)
|
||||
m_vUSMonths = new string[]{ "January", "February", "March",
|
||||
m_vUSMonths = new string[] { "January", "February", "March",
|
||||
"April", "May", "June", "July", "August", "September",
|
||||
"October", "November", "December" };
|
||||
|
||||
@ -326,14 +363,14 @@ namespace KeePassLib.Utility
|
||||
if(str.StartsWith(m_vUSMonths[i], StrUtil.CaseIgnoreCmp))
|
||||
{
|
||||
str = str.Substring(m_vUSMonths[i].Length);
|
||||
string[] v = str.Split(new char[]{ ',', ';' });
|
||||
string[] v = str.Split(new char[] { ',', ';' });
|
||||
if((v == null) || (v.Length != 2)) return null;
|
||||
|
||||
string strDay = v[0].Trim().TrimStart('0');
|
||||
int iDay, iYear;
|
||||
if(int.TryParse(strDay, out iDay) &&
|
||||
int.TryParse(v[1].Trim(), out iYear))
|
||||
return new DateTime(iYear, i + 1, iDay);
|
||||
return new DateTime(iYear, i + 1, iDay, 0, 0, 0, k);
|
||||
else { Debug.Assert(false); return null; }
|
||||
}
|
||||
}
|
||||
@ -343,11 +380,13 @@ namespace KeePassLib.Utility
|
||||
#endif
|
||||
|
||||
private static readonly DateTime m_dtInvMin =
|
||||
new DateTime(2999, 12, 27, 23, 59, 59);
|
||||
new DateTime(2999, 12, 27, 23, 59, 59, DateTimeKind.Utc);
|
||||
private static readonly DateTime m_dtInvMax =
|
||||
new DateTime(2999, 12, 29, 23, 59, 59);
|
||||
new DateTime(2999, 12, 29, 23, 59, 59, DateTimeKind.Utc);
|
||||
public static int Compare(DateTime dtA, DateTime dtB, bool bUnkIsPast)
|
||||
{
|
||||
Debug.Assert(dtA.Kind == dtB.Kind);
|
||||
|
||||
if(bUnkIsPast)
|
||||
{
|
||||
// 2999-12-28 23:59:59 in KeePass 1.x means 'unknown';
|
||||
@ -380,5 +419,64 @@ namespace KeePassLib.Utility
|
||||
return Compare(tlA.LastModificationTime, tlB.LastModificationTime,
|
||||
bUnkIsPast);
|
||||
}
|
||||
|
||||
public static DateTime ToUtc(DateTime dt, bool bUnspecifiedIsUtc)
|
||||
{
|
||||
DateTimeKind k = dt.Kind;
|
||||
if(k == DateTimeKind.Utc) return dt;
|
||||
if(k == DateTimeKind.Local) return dt.ToUniversalTime();
|
||||
|
||||
Debug.Assert(k == DateTimeKind.Unspecified);
|
||||
if(bUnspecifiedIsUtc)
|
||||
return new DateTime(dt.Ticks, DateTimeKind.Utc);
|
||||
return dt.ToUniversalTime(); // Unspecified = local
|
||||
}
|
||||
|
||||
public static DateTime ToLocal(DateTime dt, bool bUnspecifiedIsLocal)
|
||||
{
|
||||
DateTimeKind k = dt.Kind;
|
||||
if(k == DateTimeKind.Local) return dt;
|
||||
if(k == DateTimeKind.Utc) return dt.ToLocalTime();
|
||||
|
||||
Debug.Assert(k == DateTimeKind.Unspecified);
|
||||
if(bUnspecifiedIsLocal)
|
||||
return new DateTime(dt.Ticks, DateTimeKind.Local);
|
||||
return dt.ToLocalTime(); // Unspecified = UTC
|
||||
}
|
||||
|
||||
/* internal static DateTime RoundToMultOf2PowLess1s(DateTime dt)
|
||||
{
|
||||
long l2Pow = m_lTicks2PowLess1s;
|
||||
if(l2Pow == 0)
|
||||
{
|
||||
l2Pow = 1;
|
||||
while(true)
|
||||
{
|
||||
l2Pow <<= 1;
|
||||
if(l2Pow >= TimeSpan.TicksPerSecond) break;
|
||||
}
|
||||
l2Pow >>= 1;
|
||||
m_lTicks2PowLess1s = l2Pow;
|
||||
|
||||
Debug.Assert(TimeSpan.TicksPerSecond == 10000000L); // .NET
|
||||
Debug.Assert(l2Pow == (1L << 23)); // .NET
|
||||
}
|
||||
|
||||
long l = dt.Ticks;
|
||||
if((l % l2Pow) == 0L) return dt;
|
||||
|
||||
// Round down to full second
|
||||
l /= TimeSpan.TicksPerSecond;
|
||||
l *= TimeSpan.TicksPerSecond;
|
||||
|
||||
// Round up to multiple of l2Pow
|
||||
long l2PowM1 = l2Pow - 1L;
|
||||
l = (l + l2PowM1) & ~l2PowM1;
|
||||
DateTime dtRnd = new DateTime(l, dt.Kind);
|
||||
|
||||
Debug.Assert((dtRnd.Ticks % l2Pow) == 0L);
|
||||
Debug.Assert(dtRnd.ToString("u") == dt.ToString("u"));
|
||||
return dtRnd;
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 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
|
||||
@ -285,7 +285,7 @@ namespace KeePassLib.Utility
|
||||
else // Unhide
|
||||
{
|
||||
fa &= ~FileAttributes.Hidden;
|
||||
if((long)fa == 0) fa |= FileAttributes.Normal;
|
||||
if((long)fa == 0) fa = FileAttributes.Normal;
|
||||
}
|
||||
|
||||
File.SetAttributes(strFile, fa);
|
||||
|
Loading…
Reference in New Issue
Block a user