/* * Copyright (C) 2007 Eskil Bylund * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Text; using System.Text.RegularExpressions; using DCSharp.Security.Cryptography; namespace DCSharp { /// /// A globally-unique user identifier. /// public struct Uid { public static readonly Uid Empty = new Uid(new byte[Length]); public const int Length = 24; private byte[] buffer; /// /// Constructs a new Uid from a specific string. /// /// The byte value for the Uid, encoded in Base32. public Uid(string uid) : this(Base32.Decode(uid)) { } /// /// Constructs a new Uid from a specific byte array. /// /// The byte values for the Uid. /// The byte array must be 24 bytes long. public Uid(byte[] buffer) { if (buffer == null) { throw new ArgumentNullException("buffer"); } else if (!IsValid(buffer)) { throw new ArgumentException("buffer", "Invalid buffer length."); } this.buffer = buffer; } /// /// Generates a random Uid. /// /// A random Uid. public static Uid Generate() { return new Uid(Random()); } /// /// Calculates a Client ID from a Private ID. /// /// The PID. /// The calculated Cid. public static Uid CalculateCid(Uid pid) { using (Tiger algorithm = Tiger.Create()) { return new Uid(algorithm.ComputeHash(pid.ToByteArray())); } } /// /// Checks if the specified buffer can be used to create a new Uid. /// /// The buffer to validate. /// True if the buffer is valid; otherwise, false. public static bool IsValid(byte[] buffer) { return buffer != null && buffer.Length == Length; } /// /// Checks if a specific string can be used to create a new Uid. /// /// The string to validate."> /// True if the string is valid; otherwise, false. public static bool IsValid(string uid) { return uid != null && Regex.IsMatch(uid, "^[A-Za-z2-7]{39}$"); } /// /// Gets the value of the Uid as a byte array. /// /// The byte values of the Uid. public byte[] ToByteArray() { return (byte[])buffer.Clone(); } public static bool operator==(Uid a, Uid b) { for (int i = 0; i < Length; i++) { if (a.buffer[i] != b.buffer[i]) { return false; } } return true; } public static bool operator!=(Uid a, Uid b) { return !(a == b); } public static implicit operator string(Uid a) { return a.ToString(); } public static explicit operator Uid(string a) { return new Uid(a); } public override bool Equals(object value) { if (value == null) { return false; } if (GetType() == value.GetType()) { return this == (Uid)value; } return false; } public override int GetHashCode() { return BitConverter.ToInt32(buffer, 0); } public override string ToString() { return Base32.Encode(buffer); } private static byte[] Random() { byte[] buffer = new byte[Length]; new Random().NextBytes(buffer); return buffer; } } }