annotate ARClient/MARC.cs @ 0:90ea68d4f92f

First release
author Ivo Smits <Ivo@UCIS.nl>
date Sat, 08 Nov 2014 22:43:51 +0100
parents
children 27ccad26a830
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1 ???using System;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
2 using System.Collections;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
3 using System.IO;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
4 using System.Net;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
5 using System.Text;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
6 using UCIS.NaCl.v2;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
7 //using UCIS.NaCl.crypto_sign;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
8 using UCIS.Util;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
9
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
10 namespace ARClient {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
11 public static class Functions {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
12 public static String bin2hex(Byte[] bytes) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
13 StringBuilder sb = new StringBuilder();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
14 foreach (Byte b in bytes) sb.Append(b.ToString("x2"));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
15 return sb.ToString();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
16 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
17 public static Byte[] hex2bin(String hex) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
18 if (hex.Length % 2 != 0) hex = "0" + hex;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
19 Byte[] r = new Byte[hex.Length / 2];
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
20 for (int i = 0; i < r.Length; i++) if (!Byte.TryParse(hex.Substring(2 * i, 2), System.Globalization.NumberStyles.HexNumber, null, out r[i])) return null;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
21 return r;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
22 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
23 public static UInt32 DecodeInt32BigEndian(Byte[] data, int i) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
24 return (UInt32)(data[i + 3] + 256 * (data[i + 2] + 256 * (data[i + 1] + 256 * data[i])));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
25 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
26 public static Byte[] EncodeInt32BigEndian(UInt32 v) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
27 Byte[] r = new Byte[4];
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
28 UInt32 j;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
29 j = v % 256; r[3] = (Byte)j; v >>= 8;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
30 j = v % 256; r[2] = (Byte)j; v >>= 8;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
31 j = v % 256; r[1] = (Byte)j; v >>= 8;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
32 j = v % 256; r[0] = (Byte)j;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
33 return r;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
34 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
35 public static UInt16 DecodeInt16BigEndian(Byte[] data, int i) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
36 return (UInt16)(data[i + 1] + 256 * data[i]);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
37 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
38 public static Byte[] EncodeInt16BigEndian(UInt16 v) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
39 Byte[] r = new Byte[4];
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
40 int j;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
41 j = v % 256; r[1] = (Byte)j; v >>= 8;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
42 j = v % 256; r[0] = (Byte)j;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
43 return r;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
44 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
45 public static UInt32 ToBigEndian(UInt32 value) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
46 if (!BitConverter.IsLittleEndian) return value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
47 return ((value >> 24) & 0xff) | ((value >> 8) & 0xff00) | ((value << 8) & 0xff0000) | ((value << 24) & 0xff000000);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
48 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
49 public static UInt32 FromBigEndian(UInt32 value) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
50 if (!BitConverter.IsLittleEndian) return value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
51 return ((value >> 24) & 0xff) | ((value >> 8) & 0xff00) | ((value << 8) & 0xff0000) | ((value << 24) & 0xff000000);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
52 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
53 public static int CompareByteArrays(Byte[] a, Byte[] b) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
54 for (int i = 0; i < Math.Min(b.Length, a.Length); i++) if (b[i] != a[i]) return a[i] - b[i];
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
55 return b.Length - a.Length;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
56 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
57 public static String GetNameForLabel(Byte[] label) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
58 if (label == null || label.Length < 1) return String.Empty;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
59 switch (label[0]) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
60 case 0:
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
61 if (label.Length != 33) break;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
62 return "Key: " + bin2hex(ArrayUtil.Slice(label, 1));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
63 case 1:
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
64 if (label.Length != 6) break;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
65 return "IPv4: " + label[1].ToString() + "." + label[2].ToString() + "." + label[3].ToString() + "." + label[4].ToString() + "/" + label[5].ToString();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
66 case 2:
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
67 if (label.Length != 18) break;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
68 return "IPv6: " + (new IPAddress(ArrayUtil.Slice(label, 1, 16))).ToString() + "/" + label[17].ToString();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
69 case 3:
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
70 if (label.Length != 5) break;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
71 return "AS Number: " + DecodeInt32BigEndian(label, 1).ToString();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
72 case 4:
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
73 return "Domain: " + Encoding.UTF8.GetString(label, 1, label.Length - 1);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
74
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
75 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
76 return bin2hex(label);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
77 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
78 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
79 public struct BinaryString : IComparable {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
80 public Byte[] Bytes { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
81 public BinaryString(Byte[] bytes) : this() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
82 if (bytes == null) throw new ArgumentNullException("bytes");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
83 this.Bytes = bytes;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
84 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
85 public BinaryString(Byte[] bytes, int offset, int length) : this(ArrayUtil.Slice(bytes, offset, length)) { }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
86 public override string ToString() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
87 return Encoding.UTF8.GetString(Bytes);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
88 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
89 public static explicit operator Byte[](BinaryString bs) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
90 return bs.Bytes;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
91 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
92 public static explicit operator String(BinaryString bs) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
93 return bs.ToString();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
94 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
95 public int CompareTo(Object otherobj) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
96 if (otherobj == null) return 1;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
97 if (otherobj is BinaryString) return Functions.CompareByteArrays(Bytes, ((BinaryString)otherobj).Bytes);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
98 if (otherobj is Byte[]) return Functions.CompareByteArrays(Bytes, ((Byte[])otherobj));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
99 if (otherobj is String) return ToString().CompareTo(otherobj);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
100 return 1;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
101 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
102 public override bool Equals(object obj) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
103 return CompareTo(obj) == 0;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
104 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
105 public static Boolean operator ==(BinaryString a, Object b) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
106 return a.Equals(b);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
107 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
108 public static Boolean operator !=(BinaryString a, Object b) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
109 return !a.Equals(b);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
110 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
111 public override int GetHashCode() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
112 int hash = Bytes.Length;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
113 foreach (Byte b in Bytes) hash += b;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
114 return hash;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
115 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
116 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
117 public class MARCUpdate {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
118 public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
119 public static long DateTimeToUnix(DateTime value) { return (long)(value.ToUniversalTime() - UnixEpoch).TotalSeconds; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
120 public static DateTime DateTimeFromUnix(long seconds) { return UnixEpoch.AddSeconds(seconds);}
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
121
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
122 public Byte Version { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
123 public MARCKey Key { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
124 public UInt32 Serial { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
125 public MARCLabel Label { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
126 public MARCKey? Transfer { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
127 public UInt32? Expiration { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
128 public Byte[] UpdateMessage { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
129 private int ValueOffset = -1;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
130 private Object mValue = null;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
131 public Object Value {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
132 get {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
133 if (mValue == null) mValue = DecodeValue(UpdateMessage, ValueOffset, UpdateMessage.Length - ValueOffset);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
134 return mValue;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
135 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
136 private set {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
137 mValue = value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
138 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
139 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
140 public Boolean Expired {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
141 get {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
142 long currentTime = DateTimeToUnix(DateTime.UtcNow);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
143 return (Serial + 365 * 24 * 60 * 60 < currentTime) || ((Expiration ?? UInt32.MaxValue) < currentTime);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
144 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
145 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
146 public Boolean CanUpdate(MARCKey key) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
147 if (key == this.Key) return true;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
148 if (Expired) return true;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
149 if (Transfer != null && (Transfer.Value.Bytes.Length == 0 || Transfer.Value == key)) return true;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
150 return false;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
151 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
152 public DateTime UpdateTimestamp { get { return DateTimeFromUnix(Serial); } }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
153 public DateTime ExpirationTimestamp { get { return Expiration == null ? DateTime.MaxValue : DateTimeFromUnix(Expiration.Value); } }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
154 private MARCUpdate() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
155 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
156 public static MARCUpdate Create(ed25519keypair key, UInt32 serial, Byte[] label, Object value, UInt32? expiration, Byte[] transfer) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
157 MARCUpdate update = new MARCUpdate();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
158 update.Version = 2;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
159 update.Key = new MARCKey(key.PublicKey);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
160 update.Serial = serial;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
161 if (label.Length > 255) throw new ArgumentException("label");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
162 update.Label = new MARCLabel(label);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
163 update.Value = value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
164 update.Expiration = expiration;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
165 update.Transfer = transfer == null ? null : new MARCKey?(new MARCKey(transfer));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
166
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
167 MemoryStream buffer = new MemoryStream(1 + 32 + 64 + 4 + 1 + update.Label.Bytes.Length + 1);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
168 buffer.WriteByte(update.Version);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
169 buffer.Write(key.PublicKey, 0, 32);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
170 buffer.Write(new Byte[64], 0, 64); //Signature placeholder
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
171 buffer.Write(Functions.EncodeInt32BigEndian(update.Serial), 0, 4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
172 buffer.WriteByte(checked((Byte)update.Label.Bytes.Length));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
173 buffer.Write(update.Label.Bytes, 0, update.Label.Bytes.Length);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
174 int extcnt = 0;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
175 if (update.Transfer != null) extcnt++;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
176 if (update.Expiration != null) extcnt++;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
177 buffer.WriteByte((Byte)extcnt);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
178 if (update.Transfer != null) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
179 buffer.WriteByte(1);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
180 buffer.Write(Functions.EncodeInt16BigEndian(checked((UInt16)update.Transfer.Value.Bytes.Length)), 0, 2);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
181 buffer.Write(update.Transfer.Value.Bytes, 0, update.Transfer.Value.Bytes.Length);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
182 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
183 if (update.Expiration != null) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
184 buffer.WriteByte(4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
185 buffer.Write(Functions.EncodeInt16BigEndian(4), 0, 2);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
186 buffer.Write(Functions.EncodeInt32BigEndian(update.Expiration.Value), 0, 4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
187 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
188 update.ValueOffset = (int)buffer.Position;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
189 if (update.Value != null) EncodeValue(buffer, update.Value);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
190 Byte[] signature = key.GetSignature(buffer.GetBuffer(), 1 + 32 + 64, (int)buffer.Length - 1 - 32 - 64);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
191 buffer.Seek(1 + 32, SeekOrigin.Begin);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
192 buffer.Write(signature, 0, 64);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
193 update.UpdateMessage = buffer.ToArray();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
194 if (!update.VerifySignature()) throw new Exception("Key pair does not match");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
195 return update;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
196 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
197 public static MARCUpdate Decode(Byte[] data) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
198 int i = 0;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
199 int l = data.Length;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
200 if (l < 1 + 32 + 64) throw new Exception("Truncated data");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
201 MARCUpdate update = new MARCUpdate();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
202 update.Version = data[i++];
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
203 if (update.Version != 2) throw new Exception(String.Format("Unexpected version number {0}", update.Version));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
204 update.Key = new MARCKey(data, i, 32); i += 32;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
205 i += 64;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
206 if (data.Length < i + 4 + 1 + 1) throw new Exception("Truncated data");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
207 update.Serial = (UInt32)Functions.DecodeInt32BigEndian(data, i); i += 4;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
208 int labellen = data[i++];
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
209 if (data.Length < i + labellen + 1) throw new Exception("Truncated data");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
210 update.Label = new MARCLabel(data, i, labellen); i += labellen;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
211 for (int j = data[i++]; j > 0; j--) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
212 if (data.Length < i + 3) throw new Exception("Truncated data");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
213 int extid = data[i++];
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
214 int extlen = Functions.DecodeInt16BigEndian(data, i); i += 2;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
215 if (data.Length < i + extlen) throw new Exception("Truncated data");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
216 switch (extid) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
217 case 1: if (extlen == 0 || extlen >= 32) update.Transfer = new MARCKey(data, i, Math.Min(extlen, 32)); break;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
218 case 4: if (extlen >= 4) update.Expiration = Functions.DecodeInt32BigEndian(data, i); break;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
219 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
220 i += extlen;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
221 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
222 update.ValueOffset = i;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
223 update.UpdateMessage = data;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
224 return update;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
225 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
226 public Boolean VerifySignature() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
227 if (UpdateMessage == null) return false;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
228 if (UpdateMessage.Length < 1 + 32 + 64) return false;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
229 return ed25519.VerifySignature(new ArraySegment<Byte>(UpdateMessage, 1 + 32 + 64, UpdateMessage.Length - 1 - 32 - 64), new ArraySegment<byte>(UpdateMessage, 1 + 32, 64), ArrayUtil.Slice(UpdateMessage, 1, 32));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
230 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
231
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
232 public static Byte[] EncodeValue(Object value) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
233 using (MemoryStream ms = new MemoryStream()) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
234 EncodeValue(ms, value);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
235 return ms.ToArray();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
236 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
237 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
238 private static void EncodeValue(MemoryStream to, Object value) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
239 if (value == null) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
240 to.WriteByte(0);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
241 } else if (value is Byte[]) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
242 Byte[] s = (Byte[])value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
243 to.WriteByte(1);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
244 to.Write(s, 0, s.Length);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
245 } else if (value is IDictionary) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
246 to.WriteByte(3);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
247 IDictionary list = (IDictionary)value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
248 foreach (DictionaryEntry item in list) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
249 Byte[] s = Encoding.UTF8.GetBytes(item.Key.ToString());
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
250 to.WriteByte(checked((Byte)s.Length));
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
251 to.Write(s, 0, s.Length);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
252 long startpos = to.Position;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
253 to.Write(new Byte[4], 0, 4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
254 EncodeValue(to, item.Value);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
255 uint length = (uint)(to.Position - startpos - 4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
256 to.Seek(startpos, SeekOrigin.Begin);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
257 to.Write(Functions.EncodeInt32BigEndian(length), 0, 4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
258 to.Seek(length, SeekOrigin.Current);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
259 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
260 } else if (value is IList) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
261 to.WriteByte(2);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
262 IList list = (IList)value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
263 foreach (Object item in list) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
264 long startpos = to.Position;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
265 to.Write(new Byte[4], 0, 4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
266 EncodeValue(to, item);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
267 uint length = (uint)(to.Position - startpos - 4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
268 to.Seek(startpos, SeekOrigin.Begin);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
269 to.Write(Functions.EncodeInt32BigEndian(length), 0, 4);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
270 to.Seek(length, SeekOrigin.Current);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
271 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
272 } else {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
273 to.WriteByte(1);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
274 Byte[] s;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
275 if (value is BinaryString) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
276 s = ((BinaryString)value).Bytes;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
277 } else if (value is Byte[]) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
278 s = (Byte[])value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
279 } else {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
280 s = Encoding.UTF8.GetBytes(value.ToString());
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
281 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
282 to.Write(s, 0, s.Length);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
283 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
284 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
285 public static Object DecodeValue(Byte[] data) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
286 return DecodeValue(data, 0, data.Length);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
287 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
288 private static Object DecodeValue(Byte[] data, int i, int l) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
289 if (l < 1) return null;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
290 Byte type = data[i]; i++; l--;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
291 switch (type) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
292 case 0: return null;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
293 case 1: return new BinaryString(data, i, l);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
294 case 2: {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
295 ArrayList value = new ArrayList();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
296 while (l > 0) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
297 if (l < 4) throw new Exception("Truncated");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
298 Int32 len = (Int32)Functions.DecodeInt32BigEndian(data, i); i += 4; l -= 4;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
299 if (l < len) throw new Exception("Truncated");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
300 value.Add(DecodeValue(data, i, len)); i += len; l -= len;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
301 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
302 return value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
303 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
304 case 3: {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
305 Hashtable value = new Hashtable();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
306 while (l > 0) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
307 if (l < 5) throw new Exception("Truncated");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
308 Int32 len = data[i]; i++; l--;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
309 if (l < 4 + len) throw new Exception("Truncated");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
310 String key = Encoding.UTF8.GetString(data, i, len); i += len; l -= len;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
311 len = (Int32)Functions.DecodeInt32BigEndian(data, i); i += 4; l -= 4;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
312 if (l < len) throw new Exception("Truncated");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
313 value.Add(key, DecodeValue(data, i, len)); i += len; l -= len;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
314 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
315 return value;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
316 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
317 default: return null;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
318 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
319 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
320
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
321 public override String ToString() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
322 return Label.ToString();
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
323 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
324 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
325 public struct MARCLabel : IComparable {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
326 public Byte[] Bytes { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
327 public MARCLabel(Byte[] label)
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
328 : this() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
329 if (label == null) throw new ArgumentNullException("label");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
330 if (label.Length > 255) throw new ArgumentException("Parameter label is too long", "label");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
331 this.Bytes = label;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
332 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
333 public MARCLabel(Byte[] label, int offset, int len)
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
334 : this() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
335 this.Bytes = new Byte[len];
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
336 Buffer.BlockCopy(label, offset, this.Bytes, 0, len);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
337 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
338 public int CompareTo(Object otherobj) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
339 if (otherobj == null || !(otherobj is MARCLabel)) return 1;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
340 return Functions.CompareByteArrays(Bytes, ((MARCLabel)otherobj).Bytes);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
341 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
342 public override bool Equals(object obj) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
343 return CompareTo(obj) == 0;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
344 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
345 public static Boolean operator ==(MARCLabel a, Object b) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
346 return a.Equals(b);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
347 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
348 public static Boolean operator !=(MARCLabel a, Object b) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
349 return !a.Equals(b);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
350 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
351 public override int GetHashCode() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
352 int hash = Bytes.Length;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
353 foreach (Byte b in Bytes) hash += b;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
354 return hash;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
355 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
356
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
357 public override String ToString() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
358 return Functions.GetNameForLabel(Bytes);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
359 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
360 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
361 public struct MARCKey : IComparable {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
362 public Byte[] Bytes { get; private set; }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
363 public MARCKey(Byte[] key)
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
364 : this() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
365 if (key == null) throw new ArgumentNullException("key");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
366 if (key.Length != 32 && key.Length != 0) throw new ArgumentException("Incorrect key length", "key");
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
367 this.Bytes = key;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
368 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
369 public MARCKey(Byte[] label, int offset, int len) : this(ArrayUtil.Slice(label, offset, len)) { }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
370 public int CompareTo(Object otherobj) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
371 if (otherobj == null || !(otherobj is MARCKey)) return 1;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
372 return Functions.CompareByteArrays(Bytes, ((MARCKey)otherobj).Bytes);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
373 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
374 public override bool Equals(object obj) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
375 return CompareTo(obj) == 0;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
376 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
377 public static Boolean operator ==(MARCKey a, Object b) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
378 return a.Equals(b);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
379 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
380 public static Boolean operator !=(MARCKey a, Object b) {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
381 return !a.Equals(b);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
382 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
383 public override int GetHashCode() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
384 int hash = Bytes.Length;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
385 foreach (Byte b in Bytes) hash += b;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
386 return hash;
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
387 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
388 public override string ToString() {
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
389 return Functions.bin2hex(Bytes);
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
390 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
391 }
90ea68d4f92f First release
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
392 }