0
|
1 ???using System; |
|
2 using System.IO; |
|
3 using System.Text; |
|
4 using System.Collections.Generic; |
|
5 using UCIS.Pml; |
|
6 |
|
7 namespace UCIS.Pml { |
|
8 internal enum AmfDataType : byte { |
|
9 Number = 0, |
|
10 Boolean = 1, |
|
11 String = 2, |
|
12 UntypedObject = 3, |
|
13 MovieClip = 4, |
|
14 Null = 5, |
|
15 Undefined = 6, |
|
16 ReferencedObject = 7, |
|
17 MixedArray = 8, |
|
18 End = 9, |
|
19 Array = 10, |
|
20 Date = 11, |
|
21 LongString = 12, |
|
22 TypeAsObject = 13, |
|
23 Recordset = 14, |
|
24 Xml = 15, |
|
25 TypedObject = 16 |
|
26 } |
|
27 public class PmlAmfWriter : IPmlWriter { |
|
28 private BinaryWriter pWriter; |
|
29 |
|
30 public PmlAmfWriter(BinaryWriter Writer) { |
|
31 pWriter = Writer; |
|
32 } |
|
33 public PmlAmfWriter(Stream Stream) { |
|
34 pWriter = new BinaryWriter(Stream, Encoding.UTF8); |
|
35 } |
|
36 |
|
37 public BinaryWriter BaseWriter { |
|
38 get { return pWriter; } |
|
39 set { pWriter = value; } |
|
40 } |
|
41 |
|
42 public void WriteMessage(PmlElement Message) { |
|
43 WriteMessageTo(Message, pWriter); |
|
44 } |
|
45 |
|
46 public static void WriteMessageTo(PmlElement Message, BinaryWriter Writer) { |
|
47 lock (Writer) { |
|
48 WriteElementTo(Message, Writer); |
|
49 Writer.Flush(); |
|
50 } |
|
51 } |
|
52 |
|
53 private static void WriteElementTo(PmlElement Element, BinaryWriter Writer) { |
|
54 if (Element == null) { |
|
55 Writer.Write((byte)AmfDataType.Null); |
|
56 return; |
|
57 } |
|
58 switch (Element.Type) { |
|
59 case PmlType.Null: |
|
60 Writer.Write((byte)AmfDataType.Null); |
|
61 break; |
|
62 case PmlType.Dictionary: |
|
63 Writer.Write((byte)AmfDataType.UntypedObject); |
|
64 //WriteDictionary(Writer, (PmlDictionary)Element); |
|
65 WriteUntypedObject(Writer, (PmlDictionary)Element); |
|
66 break; |
|
67 case PmlType.Collection: |
|
68 Writer.Write((byte)AmfDataType.Array); |
|
69 WriteCollection(Writer, (PmlCollection)Element); |
|
70 break; |
|
71 case PmlType.Binary: |
|
72 Writer.Write((byte)AmfDataType.String); |
|
73 byte[] bytes = Element.ToByteArray(); |
|
74 if (bytes.Length > UInt16.MaxValue) { |
|
75 Writer.Write((byte)AmfDataType.String); |
|
76 WriteString(Writer, bytes); |
|
77 } else { |
|
78 Writer.Write((byte)AmfDataType.LongString); |
|
79 WriteLongString(Writer, bytes); |
|
80 } |
|
81 break; |
|
82 case PmlType.String: |
|
83 string str = Element.ToString(); |
|
84 if (str.Length < UInt16.MaxValue) { |
|
85 Writer.Write((byte)AmfDataType.String); |
|
86 WriteString(Writer, str); |
|
87 } else { |
|
88 Writer.Write((byte)AmfDataType.LongString); |
|
89 WriteLongString(Writer, str); |
|
90 } |
|
91 break; |
|
92 case PmlType.Integer: |
|
93 Writer.Write((byte)AmfDataType.Number); |
|
94 WriteDouble(Writer, (Element as PmlInteger).ToDouble()); |
|
95 break; |
|
96 } |
|
97 } |
|
98 private static void WriteEnd(BinaryWriter w) { |
|
99 WriteUInt16(w, 0); |
|
100 w.Write((byte)AmfDataType.End); |
|
101 } |
|
102 private static void WriteUntypedObject(BinaryWriter w, PmlDictionary value) { |
|
103 foreach (KeyValuePair<String, PmlElement> kvp in value) { |
|
104 WriteString(w, kvp.Key); |
|
105 WriteElementTo(kvp.Value, w); |
|
106 } |
|
107 WriteEnd(w); |
|
108 } |
|
109 private static void WriteDictionary(BinaryWriter w, PmlDictionary value) { |
|
110 WriteUInt32(w, (UInt32)value.Count); |
|
111 foreach (KeyValuePair<String, PmlElement> kvp in value) { |
|
112 WriteString(w, kvp.Key); |
|
113 WriteElementTo(kvp.Value, w); |
|
114 } |
|
115 } |
|
116 private static void WriteCollection(BinaryWriter w, PmlCollection value) { |
|
117 WriteUInt32(w,(UInt32)value.Count); |
|
118 foreach (PmlElement o in value) { |
|
119 WriteElementTo(o, w); |
|
120 } |
|
121 } |
|
122 private static void WriteDouble(BinaryWriter w, double value) { |
|
123 WriteReverse(w, BitConverter.GetBytes(value)); |
|
124 } |
|
125 private static void WriteUInt32(BinaryWriter w, UInt32 value) { |
|
126 WriteReverse(w, BitConverter.GetBytes(value)); |
|
127 } |
|
128 private static void WriteUInt16(BinaryWriter w, UInt16 value) { |
|
129 WriteReverse(w, BitConverter.GetBytes(value)); |
|
130 } |
|
131 private static void WriteString(BinaryWriter w, string value) { |
|
132 WriteString(w, Encoding.UTF8.GetBytes(value)); |
|
133 } |
|
134 private static void WriteLongString(BinaryWriter w, string value) { |
|
135 WriteLongString(w, Encoding.UTF8.GetBytes(value)); |
|
136 } |
|
137 private static void WriteString(BinaryWriter w, byte[] buffer) { |
|
138 WriteUInt16(w, (UInt16)buffer.Length); |
|
139 w.Write(buffer, 0, buffer.Length); |
|
140 } |
|
141 private static void WriteLongString(BinaryWriter w, byte[] buffer) { |
|
142 WriteUInt32(w, (UInt32)buffer.Length); |
|
143 w.Write(buffer, 0, buffer.Length); |
|
144 } |
|
145 private static void WriteReverse(BinaryWriter w, byte[] value) { |
|
146 Array.Reverse(value); |
|
147 w.Write(value); |
|
148 } |
|
149 } |
|
150 |
|
151 public class PmlAmfReader : IPmlReader { |
|
152 private BinaryReader pReader; |
|
153 |
|
154 public PmlAmfReader(BinaryReader Reader) { |
|
155 pReader = Reader; |
|
156 } |
|
157 public PmlAmfReader(Stream Stream) { |
|
158 pReader = new BinaryReader(Stream, Encoding.UTF8); |
|
159 } |
|
160 |
|
161 public BinaryReader BaseReader { |
|
162 get { return pReader; } |
|
163 set { pReader = value; } |
|
164 } |
|
165 |
|
166 public PmlElement ReadMessage() { |
|
167 return ReadMessageFrom(pReader); |
|
168 } |
|
169 |
|
170 public static PmlElement ReadMessageFrom(BinaryReader Reader) { |
|
171 PmlElement Element = null; |
|
172 lock (Reader) { |
|
173 Element = ReadElementFrom(Reader); |
|
174 } |
|
175 return Element; |
|
176 } |
|
177 |
|
178 |
|
179 private static PmlElement ReadElementFrom(BinaryReader Reader) { |
|
180 AmfDataType EType = (AmfDataType)Reader.ReadByte(); |
|
181 return ReadData(Reader, EType); |
|
182 } |
|
183 private static PmlElement ReadData(BinaryReader Reader, AmfDataType EType) { |
|
184 switch (EType) { |
|
185 case AmfDataType.Number: |
|
186 Double d = ReadDouble(Reader); |
|
187 if (d == (double)(Int64)d) { |
|
188 return new PmlInteger((Int64)d); |
|
189 } else if (d == (double)(UInt64)d) { |
|
190 return new PmlInteger((UInt64)d); |
|
191 } else { |
|
192 return new PmlString(d.ToString()); |
|
193 } |
|
194 case AmfDataType.Boolean: |
|
195 return new PmlInteger(Reader.ReadByte()); |
|
196 case AmfDataType.String: |
|
197 return new PmlString(ReadShortString(Reader)); |
|
198 case AmfDataType.Array: |
|
199 PmlCollection ElementC = new PmlCollection(); |
|
200 int size = ReadInt32(Reader); |
|
201 for (int i = 0; i < size; ++i) { |
|
202 ElementC.Add(ReadElementFrom(Reader)); |
|
203 } |
|
204 return ElementC; |
|
205 case AmfDataType.Date: |
|
206 return new PmlString(ReadDate(Reader).ToString()); |
|
207 case AmfDataType.LongString: |
|
208 return new PmlString(ReadLongString(Reader)); |
|
209 case AmfDataType.TypedObject: |
|
210 ReadShortString(Reader); |
|
211 return ReadUntypedObject(Reader); |
|
212 case AmfDataType.MixedArray: |
|
213 return ReadDictionary(Reader); |
|
214 case AmfDataType.Null: |
|
215 case AmfDataType.Undefined: |
|
216 case AmfDataType.End: |
|
217 return new PmlNull(); |
|
218 case AmfDataType.UntypedObject: |
|
219 return ReadUntypedObject(Reader); |
|
220 case AmfDataType.Xml: |
|
221 return new PmlString(ReadLongString(Reader)); |
|
222 case AmfDataType.MovieClip: |
|
223 case AmfDataType.ReferencedObject: |
|
224 case AmfDataType.TypeAsObject: |
|
225 case AmfDataType.Recordset: |
|
226 default: |
|
227 throw new NotSupportedException("The AMF type is not supported: " + EType.ToString()); |
|
228 } |
|
229 } |
|
230 |
|
231 private static PmlDictionary ReadUntypedObject(BinaryReader Reader) { |
|
232 PmlDictionary ElementD = new PmlDictionary(); |
|
233 string key = ReadShortString(Reader); |
|
234 for (byte type = Reader.ReadByte(); type != 9; type = Reader.ReadByte()) { |
|
235 ElementD.Add(key, ReadData(Reader, (AmfDataType)type)); |
|
236 key = ReadShortString(Reader); |
|
237 } |
|
238 return ElementD; |
|
239 } |
|
240 private static PmlDictionary ReadDictionary(BinaryReader Reader) { |
|
241 PmlDictionary ElementD = new PmlDictionary(); |
|
242 int size = ReadInt32(Reader); |
|
243 return ReadUntypedObject(Reader); |
|
244 } |
|
245 |
|
246 private static DateTime ReadDate(BinaryReader r) { |
|
247 double ms = ReadDouble(r); |
|
248 DateTime date = (new DateTime(1970, 1, 1)).AddMilliseconds(ms); |
|
249 ReadUInt16(r); //gets the timezone |
|
250 return date; |
|
251 } |
|
252 private static double ReadDouble(BinaryReader r) { |
|
253 return BitConverter.ToDouble(ReadReverse(r, 8), 0); |
|
254 } |
|
255 |
|
256 private static int ReadInt32(BinaryReader r) { |
|
257 return BitConverter.ToInt32(ReadReverse(r, 4), 0); |
|
258 } |
|
259 |
|
260 private static ushort ReadUInt16(BinaryReader r) { |
|
261 return BitConverter.ToUInt16(ReadReverse(r, 2), 0); |
|
262 } |
|
263 |
|
264 private static byte[] ReadReverse(BinaryReader r, int size) { |
|
265 byte[] buffer = r.ReadBytes(size); |
|
266 Array.Reverse(buffer); |
|
267 return buffer; |
|
268 } |
|
269 private static string ReadLongString(BinaryReader r) { |
|
270 int length = ReadInt32(r); |
|
271 return ReadString(r, length); |
|
272 } |
|
273 private static string ReadShortString(BinaryReader r) { |
|
274 int length = ReadUInt16(r); |
|
275 return ReadString(r, length); |
|
276 } |
|
277 private static string ReadString(BinaryReader r, int length) { |
|
278 byte[] buffer = r.ReadBytes(length); |
|
279 return Encoding.UTF8.GetString(buffer); |
|
280 } |
|
281 } |
|
282 } |