/* KeePass Password Safe - The Open-Source Password Manager Copyright (C) 2003-2016 Dominik Reichl This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ using System; using System.Collections.Generic; using System.Xml; using System.Diagnostics; using KeePassLib.Utility; namespace KeePassLib { // [ImmutableObject(true)] /// /// Represents an UUID of a password entry or group. Once created, /// PwUuid objects aren't modifyable anymore (immutable). /// public sealed class PwUuid : IComparable, IEquatable { /// /// Standard size in bytes of a UUID. /// public const uint UuidSize = 16; /// /// Zero UUID (all bytes are zero). /// public static readonly PwUuid Zero = new PwUuid(false); private byte[] m_pbUuid = null; // Never null after constructor /// /// Get the 16 UUID bytes. /// public byte[] UuidBytes { get { return m_pbUuid; } } /// /// Construct a new UUID object. /// /// If this parameter is true, a new /// UUID is generated. If it is false, the UUID is initialized /// to zero. public PwUuid(bool bCreateNew) { if(bCreateNew) CreateNew(); else SetZero(); } /// /// Construct a new UUID object. /// /// Initial value of the PwUuid object. public PwUuid(byte[] uuidBytes) { SetValue(uuidBytes); } /// /// Create a new, random UUID. /// /// Returns true if a random UUID has been generated, /// otherwise it returns false. private void CreateNew() { Debug.Assert(m_pbUuid == null); // Only call from constructor while(true) { m_pbUuid = Guid.NewGuid().ToByteArray(); if((m_pbUuid == null) || (m_pbUuid.Length != (int)UuidSize)) { Debug.Assert(false); throw new InvalidOperationException(); } // Zero is a reserved value -- do not generate Zero if(!Equals(PwUuid.Zero)) break; Debug.Assert(false); } } private void SetValue(byte[] uuidBytes) { Debug.Assert((uuidBytes != null) && (uuidBytes.Length == (int)UuidSize)); if(uuidBytes == null) throw new ArgumentNullException("uuidBytes"); if(uuidBytes.Length != (int)UuidSize) throw new ArgumentException(); Debug.Assert(m_pbUuid == null); // Only call from constructor m_pbUuid = new byte[UuidSize]; Array.Copy(uuidBytes, m_pbUuid, (int)UuidSize); } private void SetZero() { Debug.Assert(m_pbUuid == null); // Only call from constructor m_pbUuid = new byte[UuidSize]; // Array.Clear(m_pbUuid, 0, (int)UuidSize); #if DEBUG List l = new List(m_pbUuid); Debug.Assert(l.TrueForAll(bt => (bt == 0))); #endif } [Obsolete] public bool EqualsValue(PwUuid uuid) { return Equals(uuid); } public override bool Equals(object obj) { return Equals(obj as PwUuid); } public bool Equals(PwUuid other) { if(other == null) { Debug.Assert(false); return false; } for(int i = 0; i < (int)UuidSize; ++i) { if(m_pbUuid[i] != other.m_pbUuid[i]) return false; } return true; } private int m_h = 0; public override int GetHashCode() { if(m_h == 0) m_h = (int)MemUtil.Hash32(m_pbUuid, 0, m_pbUuid.Length); return m_h; } public int CompareTo(PwUuid other) { if(other == null) { Debug.Assert(false); throw new ArgumentNullException("other"); } for(int i = 0; i < (int)UuidSize; ++i) { if(m_pbUuid[i] < other.m_pbUuid[i]) return -1; if(m_pbUuid[i] > other.m_pbUuid[i]) return 1; } return 0; } /// /// Convert the UUID to its string representation. /// /// String containing the UUID value. public string ToHexString() { return MemUtil.ByteArrayToHexString(m_pbUuid); } #if DEBUG public override string ToString() { return ToHexString(); } #endif } [Obsolete] public sealed class PwUuidComparable : IComparable { private byte[] m_pbUuid = new byte[PwUuid.UuidSize]; public PwUuidComparable(PwUuid pwUuid) { if(pwUuid == null) throw new ArgumentNullException("pwUuid"); Array.Copy(pwUuid.UuidBytes, m_pbUuid, (int)PwUuid.UuidSize); } public int CompareTo(PwUuidComparable other) { if(other == null) throw new ArgumentNullException("other"); for(int i = 0; i < (int)PwUuid.UuidSize; ++i) { if(m_pbUuid[i] < other.m_pbUuid[i]) return -1; if(m_pbUuid[i] > other.m_pbUuid[i]) return 1; } return 0; } } }