aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications/Capabilities/LLSD.cs
diff options
context:
space:
mode:
authordiva2009-06-18 00:48:39 +0000
committerdiva2009-06-18 00:48:39 +0000
commit913bc3bdb380cebebd11b657966486448962ab47 (patch)
treef41837093cd692b9fe42a21c9cb1473ef81dd0f1 /OpenSim/Framework/Communications/Capabilities/LLSD.cs
parentFix an uninitialized data block. Thanks, jhurliman (diff)
downloadopensim-SC_OLD-913bc3bdb380cebebd11b657966486448962ab47.zip
opensim-SC_OLD-913bc3bdb380cebebd11b657966486448962ab47.tar.gz
opensim-SC_OLD-913bc3bdb380cebebd11b657966486448962ab47.tar.bz2
opensim-SC_OLD-913bc3bdb380cebebd11b657966486448962ab47.tar.xz
Moved OpenSim/Framework/Communications/Capabilities up to OpenSim/Framework/Capabilities. Didn't change the namespace because VC# is not helping, and this would imply manually changing more than 50 files. So the namespace is still OpenSim.Framework.Communications.Capabilities, to be cleaned up later by someone with more energy.
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/Capabilities/LLSD.cs (renamed from OpenSim/Framework/Communications/Capabilities/LLSD.cs)1358
1 files changed, 679 insertions, 679 deletions
diff --git a/OpenSim/Framework/Communications/Capabilities/LLSD.cs b/OpenSim/Framework/Capabilities/LLSD.cs
index c982092..73556fc 100644
--- a/OpenSim/Framework/Communications/Capabilities/LLSD.cs
+++ b/OpenSim/Framework/Capabilities/LLSD.cs
@@ -1,679 +1,679 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Globalization; 30using System.Globalization;
31using System.IO; 31using System.IO;
32using System.Security.Cryptography; 32using System.Security.Cryptography;
33using System.Text; 33using System.Text;
34using System.Xml; 34using System.Xml;
35using OpenMetaverse; 35using OpenMetaverse;
36 36
37namespace OpenSim.Framework.Communications.Capabilities 37namespace OpenSim.Framework.Communications.Capabilities
38{ 38{
39 /// <summary> 39 /// <summary>
40 /// Borrowed from (a older version of) libsl for now, as their new llsd code doesn't work we our decoding code. 40 /// Borrowed from (a older version of) libsl for now, as their new llsd code doesn't work we our decoding code.
41 /// </summary> 41 /// </summary>
42 public static class LLSD 42 public static class LLSD
43 { 43 {
44 /// <summary> 44 /// <summary>
45 /// 45 ///
46 /// </summary> 46 /// </summary>
47 public class LLSDParseException : Exception 47 public class LLSDParseException : Exception
48 { 48 {
49 public LLSDParseException(string message) : base(message) 49 public LLSDParseException(string message) : base(message)
50 { 50 {
51 } 51 }
52 } 52 }
53 53
54 /// <summary> 54 /// <summary>
55 /// 55 ///
56 /// </summary> 56 /// </summary>
57 public class LLSDSerializeException : Exception 57 public class LLSDSerializeException : Exception
58 { 58 {
59 public LLSDSerializeException(string message) : base(message) 59 public LLSDSerializeException(string message) : base(message)
60 { 60 {
61 } 61 }
62 } 62 }
63 63
64 /// <summary> 64 /// <summary>
65 /// 65 ///
66 /// </summary> 66 /// </summary>
67 /// <param name="b"></param> 67 /// <param name="b"></param>
68 /// <returns></returns> 68 /// <returns></returns>
69 public static object LLSDDeserialize(byte[] b) 69 public static object LLSDDeserialize(byte[] b)
70 { 70 {
71 return LLSDDeserialize(new MemoryStream(b, false)); 71 return LLSDDeserialize(new MemoryStream(b, false));
72 } 72 }
73 73
74 /// <summary> 74 /// <summary>
75 /// 75 ///
76 /// </summary> 76 /// </summary>
77 /// <param name="st"></param> 77 /// <param name="st"></param>
78 /// <returns></returns> 78 /// <returns></returns>
79 public static object LLSDDeserialize(Stream st) 79 public static object LLSDDeserialize(Stream st)
80 { 80 {
81 XmlTextReader reader = new XmlTextReader(st); 81 XmlTextReader reader = new XmlTextReader(st);
82 reader.Read(); 82 reader.Read();
83 SkipWS(reader); 83 SkipWS(reader);
84 84
85 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd") 85 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "llsd")
86 throw new LLSDParseException("Expected <llsd>"); 86 throw new LLSDParseException("Expected <llsd>");
87 87
88 reader.Read(); 88 reader.Read();
89 object ret = LLSDParseOne(reader); 89 object ret = LLSDParseOne(reader);
90 SkipWS(reader); 90 SkipWS(reader);
91 91
92 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd") 92 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "llsd")
93 throw new LLSDParseException("Expected </llsd>"); 93 throw new LLSDParseException("Expected </llsd>");
94 94
95 return ret; 95 return ret;
96 } 96 }
97 97
98 /// <summary> 98 /// <summary>
99 /// 99 ///
100 /// </summary> 100 /// </summary>
101 /// <param name="obj"></param> 101 /// <param name="obj"></param>
102 /// <returns></returns> 102 /// <returns></returns>
103 public static byte[] LLSDSerialize(object obj) 103 public static byte[] LLSDSerialize(object obj)
104 { 104 {
105 StringWriter sw = new StringWriter(); 105 StringWriter sw = new StringWriter();
106 XmlTextWriter writer = new XmlTextWriter(sw); 106 XmlTextWriter writer = new XmlTextWriter(sw);
107 writer.Formatting = Formatting.None; 107 writer.Formatting = Formatting.None;
108 108
109 writer.WriteStartElement(String.Empty, "llsd", String.Empty); 109 writer.WriteStartElement(String.Empty, "llsd", String.Empty);
110 LLSDWriteOne(writer, obj); 110 LLSDWriteOne(writer, obj);
111 writer.WriteEndElement(); 111 writer.WriteEndElement();
112 112
113 writer.Close(); 113 writer.Close();
114 114
115 return Encoding.UTF8.GetBytes(sw.ToString()); 115 return Encoding.UTF8.GetBytes(sw.ToString());
116 } 116 }
117 117
118 /// <summary> 118 /// <summary>
119 /// 119 ///
120 /// </summary> 120 /// </summary>
121 /// <param name="writer"></param> 121 /// <param name="writer"></param>
122 /// <param name="obj"></param> 122 /// <param name="obj"></param>
123 public static void LLSDWriteOne(XmlTextWriter writer, object obj) 123 public static void LLSDWriteOne(XmlTextWriter writer, object obj)
124 { 124 {
125 if (obj == null) 125 if (obj == null)
126 { 126 {
127 writer.WriteStartElement(String.Empty, "undef", String.Empty); 127 writer.WriteStartElement(String.Empty, "undef", String.Empty);
128 writer.WriteEndElement(); 128 writer.WriteEndElement();
129 return; 129 return;
130 } 130 }
131 131
132 if (obj is string) 132 if (obj is string)
133 { 133 {
134 writer.WriteStartElement(String.Empty, "string", String.Empty); 134 writer.WriteStartElement(String.Empty, "string", String.Empty);
135 writer.WriteString((string) obj); 135 writer.WriteString((string) obj);
136 writer.WriteEndElement(); 136 writer.WriteEndElement();
137 } 137 }
138 else if (obj is int) 138 else if (obj is int)
139 { 139 {
140 writer.WriteStartElement(String.Empty, "integer", String.Empty); 140 writer.WriteStartElement(String.Empty, "integer", String.Empty);
141 writer.WriteString(obj.ToString()); 141 writer.WriteString(obj.ToString());
142 writer.WriteEndElement(); 142 writer.WriteEndElement();
143 } 143 }
144 else if (obj is double) 144 else if (obj is double)
145 { 145 {
146 writer.WriteStartElement(String.Empty, "real", String.Empty); 146 writer.WriteStartElement(String.Empty, "real", String.Empty);
147 writer.WriteString(obj.ToString()); 147 writer.WriteString(obj.ToString());
148 writer.WriteEndElement(); 148 writer.WriteEndElement();
149 } 149 }
150 else if (obj is bool) 150 else if (obj is bool)
151 { 151 {
152 bool b = (bool) obj; 152 bool b = (bool) obj;
153 writer.WriteStartElement(String.Empty, "boolean", String.Empty); 153 writer.WriteStartElement(String.Empty, "boolean", String.Empty);
154 writer.WriteString(b ? "1" : "0"); 154 writer.WriteString(b ? "1" : "0");
155 writer.WriteEndElement(); 155 writer.WriteEndElement();
156 } 156 }
157 else if (obj is ulong) 157 else if (obj is ulong)
158 { 158 {
159 throw new Exception("ulong in LLSD is currently not implemented, fix me!"); 159 throw new Exception("ulong in LLSD is currently not implemented, fix me!");
160 } 160 }
161 else if (obj is UUID) 161 else if (obj is UUID)
162 { 162 {
163 UUID u = (UUID) obj; 163 UUID u = (UUID) obj;
164 writer.WriteStartElement(String.Empty, "uuid", String.Empty); 164 writer.WriteStartElement(String.Empty, "uuid", String.Empty);
165 writer.WriteString(u.ToString()); 165 writer.WriteString(u.ToString());
166 writer.WriteEndElement(); 166 writer.WriteEndElement();
167 } 167 }
168 else if (obj is Hashtable) 168 else if (obj is Hashtable)
169 { 169 {
170 Hashtable h = obj as Hashtable; 170 Hashtable h = obj as Hashtable;
171 writer.WriteStartElement(String.Empty, "map", String.Empty); 171 writer.WriteStartElement(String.Empty, "map", String.Empty);
172 foreach (string key in h.Keys) 172 foreach (string key in h.Keys)
173 { 173 {
174 writer.WriteStartElement(String.Empty, "key", String.Empty); 174 writer.WriteStartElement(String.Empty, "key", String.Empty);
175 writer.WriteString(key); 175 writer.WriteString(key);
176 writer.WriteEndElement(); 176 writer.WriteEndElement();
177 LLSDWriteOne(writer, h[key]); 177 LLSDWriteOne(writer, h[key]);
178 } 178 }
179 writer.WriteEndElement(); 179 writer.WriteEndElement();
180 } 180 }
181 else if (obj is ArrayList) 181 else if (obj is ArrayList)
182 { 182 {
183 ArrayList a = obj as ArrayList; 183 ArrayList a = obj as ArrayList;
184 writer.WriteStartElement(String.Empty, "array", String.Empty); 184 writer.WriteStartElement(String.Empty, "array", String.Empty);
185 foreach (object item in a) 185 foreach (object item in a)
186 { 186 {
187 LLSDWriteOne(writer, item); 187 LLSDWriteOne(writer, item);
188 } 188 }
189 writer.WriteEndElement(); 189 writer.WriteEndElement();
190 } 190 }
191 else if (obj is byte[]) 191 else if (obj is byte[])
192 { 192 {
193 byte[] b = obj as byte[]; 193 byte[] b = obj as byte[];
194 writer.WriteStartElement(String.Empty, "binary", String.Empty); 194 writer.WriteStartElement(String.Empty, "binary", String.Empty);
195 195
196 writer.WriteStartAttribute(String.Empty, "encoding", String.Empty); 196 writer.WriteStartAttribute(String.Empty, "encoding", String.Empty);
197 writer.WriteString("base64"); 197 writer.WriteString("base64");
198 writer.WriteEndAttribute(); 198 writer.WriteEndAttribute();
199 199
200 //// Calculate the length of the base64 output 200 //// Calculate the length of the base64 output
201 //long length = (long)(4.0d * b.Length / 3.0d); 201 //long length = (long)(4.0d * b.Length / 3.0d);
202 //if (length % 4 != 0) length += 4 - (length % 4); 202 //if (length % 4 != 0) length += 4 - (length % 4);
203 203
204 //// Create the char[] for base64 output and fill it 204 //// Create the char[] for base64 output and fill it
205 //char[] tmp = new char[length]; 205 //char[] tmp = new char[length];
206 //int i = Convert.ToBase64CharArray(b, 0, b.Length, tmp, 0); 206 //int i = Convert.ToBase64CharArray(b, 0, b.Length, tmp, 0);
207 207
208 //writer.WriteString(new String(tmp)); 208 //writer.WriteString(new String(tmp));
209 209
210 writer.WriteString(Convert.ToBase64String(b)); 210 writer.WriteString(Convert.ToBase64String(b));
211 writer.WriteEndElement(); 211 writer.WriteEndElement();
212 } 212 }
213 else 213 else
214 { 214 {
215 throw new LLSDSerializeException("Unknown type " + obj.GetType().Name); 215 throw new LLSDSerializeException("Unknown type " + obj.GetType().Name);
216 } 216 }
217 } 217 }
218 218
219 /// <summary> 219 /// <summary>
220 /// 220 ///
221 /// </summary> 221 /// </summary>
222 /// <param name="reader"></param> 222 /// <param name="reader"></param>
223 /// <returns></returns> 223 /// <returns></returns>
224 public static object LLSDParseOne(XmlTextReader reader) 224 public static object LLSDParseOne(XmlTextReader reader)
225 { 225 {
226 SkipWS(reader); 226 SkipWS(reader);
227 if (reader.NodeType != XmlNodeType.Element) 227 if (reader.NodeType != XmlNodeType.Element)
228 throw new LLSDParseException("Expected an element"); 228 throw new LLSDParseException("Expected an element");
229 229
230 string dtype = reader.LocalName; 230 string dtype = reader.LocalName;
231 object ret = null; 231 object ret = null;
232 232
233 switch (dtype) 233 switch (dtype)
234 { 234 {
235 case "undef": 235 case "undef":
236 { 236 {
237 if (reader.IsEmptyElement) 237 if (reader.IsEmptyElement)
238 { 238 {
239 reader.Read(); 239 reader.Read();
240 return null; 240 return null;
241 } 241 }
242 242
243 reader.Read(); 243 reader.Read();
244 SkipWS(reader); 244 SkipWS(reader);
245 ret = null; 245 ret = null;
246 break; 246 break;
247 } 247 }
248 case "boolean": 248 case "boolean":
249 { 249 {
250 if (reader.IsEmptyElement) 250 if (reader.IsEmptyElement)
251 { 251 {
252 reader.Read(); 252 reader.Read();
253 return false; 253 return false;
254 } 254 }
255 255
256 reader.Read(); 256 reader.Read();
257 string s = reader.ReadString().Trim(); 257 string s = reader.ReadString().Trim();
258 258
259 if (s == String.Empty || s == "false" || s == "0") 259 if (s == String.Empty || s == "false" || s == "0")
260 ret = false; 260 ret = false;
261 else if (s == "true" || s == "1") 261 else if (s == "true" || s == "1")
262 ret = true; 262 ret = true;
263 else 263 else
264 throw new LLSDParseException("Bad boolean value " + s); 264 throw new LLSDParseException("Bad boolean value " + s);
265 265
266 break; 266 break;
267 } 267 }
268 case "integer": 268 case "integer":
269 { 269 {
270 if (reader.IsEmptyElement) 270 if (reader.IsEmptyElement)
271 { 271 {
272 reader.Read(); 272 reader.Read();
273 return 0; 273 return 0;
274 } 274 }
275 275
276 reader.Read(); 276 reader.Read();
277 ret = Convert.ToInt32(reader.ReadString().Trim()); 277 ret = Convert.ToInt32(reader.ReadString().Trim());
278 break; 278 break;
279 } 279 }
280 case "real": 280 case "real":
281 { 281 {
282 if (reader.IsEmptyElement) 282 if (reader.IsEmptyElement)
283 { 283 {
284 reader.Read(); 284 reader.Read();
285 return 0.0f; 285 return 0.0f;
286 } 286 }
287 287
288 reader.Read(); 288 reader.Read();
289 ret = Convert.ToDouble(reader.ReadString().Trim()); 289 ret = Convert.ToDouble(reader.ReadString().Trim());
290 break; 290 break;
291 } 291 }
292 case "uuid": 292 case "uuid":
293 { 293 {
294 if (reader.IsEmptyElement) 294 if (reader.IsEmptyElement)
295 { 295 {
296 reader.Read(); 296 reader.Read();
297 return UUID.Zero; 297 return UUID.Zero;
298 } 298 }
299 299
300 reader.Read(); 300 reader.Read();
301 ret = new UUID(reader.ReadString().Trim()); 301 ret = new UUID(reader.ReadString().Trim());
302 break; 302 break;
303 } 303 }
304 case "string": 304 case "string":
305 { 305 {
306 if (reader.IsEmptyElement) 306 if (reader.IsEmptyElement)
307 { 307 {
308 reader.Read(); 308 reader.Read();
309 return String.Empty; 309 return String.Empty;
310 } 310 }
311 311
312 reader.Read(); 312 reader.Read();
313 ret = reader.ReadString(); 313 ret = reader.ReadString();
314 break; 314 break;
315 } 315 }
316 case "binary": 316 case "binary":
317 { 317 {
318 if (reader.IsEmptyElement) 318 if (reader.IsEmptyElement)
319 { 319 {
320 reader.Read(); 320 reader.Read();
321 return new byte[0]; 321 return new byte[0];
322 } 322 }
323 323
324 if (reader.GetAttribute("encoding") != null && 324 if (reader.GetAttribute("encoding") != null &&
325 reader.GetAttribute("encoding") != "base64") 325 reader.GetAttribute("encoding") != "base64")
326 { 326 {
327 throw new LLSDParseException("Unknown encoding: " + reader.GetAttribute("encoding")); 327 throw new LLSDParseException("Unknown encoding: " + reader.GetAttribute("encoding"));
328 } 328 }
329 329
330 reader.Read(); 330 reader.Read();
331 FromBase64Transform b64 = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces); 331 FromBase64Transform b64 = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces);
332 byte[] inp = Encoding.UTF8.GetBytes(reader.ReadString()); 332 byte[] inp = Encoding.UTF8.GetBytes(reader.ReadString());
333 ret = b64.TransformFinalBlock(inp, 0, inp.Length); 333 ret = b64.TransformFinalBlock(inp, 0, inp.Length);
334 break; 334 break;
335 } 335 }
336 case "date": 336 case "date":
337 { 337 {
338 reader.Read(); 338 reader.Read();
339 throw new Exception("LLSD TODO: date"); 339 throw new Exception("LLSD TODO: date");
340 } 340 }
341 case "map": 341 case "map":
342 { 342 {
343 return LLSDParseMap(reader); 343 return LLSDParseMap(reader);
344 } 344 }
345 case "array": 345 case "array":
346 { 346 {
347 return LLSDParseArray(reader); 347 return LLSDParseArray(reader);
348 } 348 }
349 default: 349 default:
350 throw new LLSDParseException("Unknown element <" + dtype + ">"); 350 throw new LLSDParseException("Unknown element <" + dtype + ">");
351 } 351 }
352 352
353 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != dtype) 353 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != dtype)
354 { 354 {
355 throw new LLSDParseException("Expected </" + dtype + ">"); 355 throw new LLSDParseException("Expected </" + dtype + ">");
356 } 356 }
357 357
358 reader.Read(); 358 reader.Read();
359 return ret; 359 return ret;
360 } 360 }
361 361
362 /// <summary> 362 /// <summary>
363 /// 363 ///
364 /// </summary> 364 /// </summary>
365 /// <param name="reader"></param> 365 /// <param name="reader"></param>
366 /// <returns></returns> 366 /// <returns></returns>
367 public static Hashtable LLSDParseMap(XmlTextReader reader) 367 public static Hashtable LLSDParseMap(XmlTextReader reader)
368 { 368 {
369 Hashtable ret = new Hashtable(); 369 Hashtable ret = new Hashtable();
370 370
371 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "map") 371 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "map")
372 throw new LLSDParseException("Expected <map>"); 372 throw new LLSDParseException("Expected <map>");
373 373
374 if (reader.IsEmptyElement) 374 if (reader.IsEmptyElement)
375 { 375 {
376 reader.Read(); 376 reader.Read();
377 return ret; 377 return ret;
378 } 378 }
379 379
380 reader.Read(); 380 reader.Read();
381 381
382 while (true) 382 while (true)
383 { 383 {
384 SkipWS(reader); 384 SkipWS(reader);
385 if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "map") 385 if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "map")
386 { 386 {
387 reader.Read(); 387 reader.Read();
388 break; 388 break;
389 } 389 }
390 390
391 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "key") 391 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "key")
392 throw new LLSDParseException("Expected <key>"); 392 throw new LLSDParseException("Expected <key>");
393 393
394 string key = reader.ReadString(); 394 string key = reader.ReadString();
395 395
396 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "key") 396 if (reader.NodeType != XmlNodeType.EndElement || reader.LocalName != "key")
397 throw new LLSDParseException("Expected </key>"); 397 throw new LLSDParseException("Expected </key>");
398 398
399 reader.Read(); 399 reader.Read();
400 object val = LLSDParseOne(reader); 400 object val = LLSDParseOne(reader);
401 ret[key] = val; 401 ret[key] = val;
402 } 402 }
403 403
404 return ret; // TODO 404 return ret; // TODO
405 } 405 }
406 406
407 /// <summary> 407 /// <summary>
408 /// 408 ///
409 /// </summary> 409 /// </summary>
410 /// <param name="reader"></param> 410 /// <param name="reader"></param>
411 /// <returns></returns> 411 /// <returns></returns>
412 public static ArrayList LLSDParseArray(XmlTextReader reader) 412 public static ArrayList LLSDParseArray(XmlTextReader reader)
413 { 413 {
414 ArrayList ret = new ArrayList(); 414 ArrayList ret = new ArrayList();
415 415
416 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "array") 416 if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "array")
417 throw new LLSDParseException("Expected <array>"); 417 throw new LLSDParseException("Expected <array>");
418 418
419 if (reader.IsEmptyElement) 419 if (reader.IsEmptyElement)
420 { 420 {
421 reader.Read(); 421 reader.Read();
422 return ret; 422 return ret;
423 } 423 }
424 424
425 reader.Read(); 425 reader.Read();
426 426
427 while (true) 427 while (true)
428 { 428 {
429 SkipWS(reader); 429 SkipWS(reader);
430 430
431 if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "array") 431 if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "array")
432 { 432 {
433 reader.Read(); 433 reader.Read();
434 break; 434 break;
435 } 435 }
436 436
437 ret.Insert(ret.Count, LLSDParseOne(reader)); 437 ret.Insert(ret.Count, LLSDParseOne(reader));
438 } 438 }
439 439
440 return ret; // TODO 440 return ret; // TODO
441 } 441 }
442 442
443 /// <summary> 443 /// <summary>
444 /// 444 ///
445 /// </summary> 445 /// </summary>
446 /// <param name="count"></param> 446 /// <param name="count"></param>
447 /// <returns></returns> 447 /// <returns></returns>
448 private static string GetSpaces(int count) 448 private static string GetSpaces(int count)
449 { 449 {
450 StringBuilder b = new StringBuilder(); 450 StringBuilder b = new StringBuilder();
451 for (int i = 0; i < count; i++) b.Append(" "); 451 for (int i = 0; i < count; i++) b.Append(" ");
452 return b.ToString(); 452 return b.ToString();
453 } 453 }
454 454
455 /// <summary> 455 /// <summary>
456 /// 456 ///
457 /// </summary> 457 /// </summary>
458 /// <param name="obj"></param> 458 /// <param name="obj"></param>
459 /// <param name="indent"></param> 459 /// <param name="indent"></param>
460 /// <returns></returns> 460 /// <returns></returns>
461 public static String LLSDDump(object obj, int indent) 461 public static String LLSDDump(object obj, int indent)
462 { 462 {
463 if (obj == null) 463 if (obj == null)
464 { 464 {
465 return GetSpaces(indent) + "- undef\n"; 465 return GetSpaces(indent) + "- undef\n";
466 } 466 }
467 else if (obj is string) 467 else if (obj is string)
468 { 468 {
469 return GetSpaces(indent) + "- string \"" + (string) obj + "\"\n"; 469 return GetSpaces(indent) + "- string \"" + (string) obj + "\"\n";
470 } 470 }
471 else if (obj is int) 471 else if (obj is int)
472 { 472 {
473 return GetSpaces(indent) + "- integer " + obj.ToString() + "\n"; 473 return GetSpaces(indent) + "- integer " + obj.ToString() + "\n";
474 } 474 }
475 else if (obj is double) 475 else if (obj is double)
476 { 476 {
477 return GetSpaces(indent) + "- float " + obj.ToString() + "\n"; 477 return GetSpaces(indent) + "- float " + obj.ToString() + "\n";
478 } 478 }
479 else if (obj is UUID) 479 else if (obj is UUID)
480 { 480 {
481 return GetSpaces(indent) + "- uuid " + ((UUID) obj).ToString() + Environment.NewLine; 481 return GetSpaces(indent) + "- uuid " + ((UUID) obj).ToString() + Environment.NewLine;
482 } 482 }
483 else if (obj is Hashtable) 483 else if (obj is Hashtable)
484 { 484 {
485 StringBuilder ret = new StringBuilder(); 485 StringBuilder ret = new StringBuilder();
486 ret.Append(GetSpaces(indent) + "- map" + Environment.NewLine); 486 ret.Append(GetSpaces(indent) + "- map" + Environment.NewLine);
487 Hashtable map = (Hashtable) obj; 487 Hashtable map = (Hashtable) obj;
488 488
489 foreach (string key in map.Keys) 489 foreach (string key in map.Keys)
490 { 490 {
491 ret.Append(GetSpaces(indent + 2) + "- key \"" + key + "\"" + Environment.NewLine); 491 ret.Append(GetSpaces(indent + 2) + "- key \"" + key + "\"" + Environment.NewLine);
492 ret.Append(LLSDDump(map[key], indent + 3)); 492 ret.Append(LLSDDump(map[key], indent + 3));
493 } 493 }
494 494
495 return ret.ToString(); 495 return ret.ToString();
496 } 496 }
497 else if (obj is ArrayList) 497 else if (obj is ArrayList)
498 { 498 {
499 StringBuilder ret = new StringBuilder(); 499 StringBuilder ret = new StringBuilder();
500 ret.Append(GetSpaces(indent) + "- array\n"); 500 ret.Append(GetSpaces(indent) + "- array\n");
501 ArrayList list = (ArrayList) obj; 501 ArrayList list = (ArrayList) obj;
502 502
503 foreach (object item in list) 503 foreach (object item in list)
504 { 504 {
505 ret.Append(LLSDDump(item, indent + 2)); 505 ret.Append(LLSDDump(item, indent + 2));
506 } 506 }
507 507
508 return ret.ToString(); 508 return ret.ToString();
509 } 509 }
510 else if (obj is byte[]) 510 else if (obj is byte[])
511 { 511 {
512 return GetSpaces(indent) + "- binary\n" + Utils.BytesToHexString((byte[]) obj, GetSpaces(indent)) + 512 return GetSpaces(indent) + "- binary\n" + Utils.BytesToHexString((byte[]) obj, GetSpaces(indent)) +
513 Environment.NewLine; 513 Environment.NewLine;
514 } 514 }
515 else 515 else
516 { 516 {
517 return GetSpaces(indent) + "- unknown type " + obj.GetType().Name + Environment.NewLine; 517 return GetSpaces(indent) + "- unknown type " + obj.GetType().Name + Environment.NewLine;
518 } 518 }
519 } 519 }
520 520
521 public static object ParseTerseLLSD(string llsd) 521 public static object ParseTerseLLSD(string llsd)
522 { 522 {
523 int notused; 523 int notused;
524 return ParseTerseLLSD(llsd, out notused); 524 return ParseTerseLLSD(llsd, out notused);
525 } 525 }
526 526
527 public static object ParseTerseLLSD(string llsd, out int endPos) 527 public static object ParseTerseLLSD(string llsd, out int endPos)
528 { 528 {
529 if (llsd.Length == 0) 529 if (llsd.Length == 0)
530 { 530 {
531 endPos = 0; 531 endPos = 0;
532 return null; 532 return null;
533 } 533 }
534 534
535 // Identify what type of object this is 535 // Identify what type of object this is
536 switch (llsd[0]) 536 switch (llsd[0])
537 { 537 {
538 case '!': 538 case '!':
539 throw new LLSDParseException("Undefined value type encountered"); 539 throw new LLSDParseException("Undefined value type encountered");
540 case '1': 540 case '1':
541 endPos = 1; 541 endPos = 1;
542 return true; 542 return true;
543 case '0': 543 case '0':
544 endPos = 1; 544 endPos = 1;
545 return false; 545 return false;
546 case 'i': 546 case 'i':
547 { 547 {
548 if (llsd.Length < 2) throw new LLSDParseException("Integer value type with no value"); 548 if (llsd.Length < 2) throw new LLSDParseException("Integer value type with no value");
549 int value; 549 int value;
550 endPos = FindEnd(llsd, 1); 550 endPos = FindEnd(llsd, 1);
551 551
552 if (Int32.TryParse(llsd.Substring(1, endPos - 1), out value)) 552 if (Int32.TryParse(llsd.Substring(1, endPos - 1), out value))
553 return value; 553 return value;
554 else 554 else
555 throw new LLSDParseException("Failed to parse integer value type"); 555 throw new LLSDParseException("Failed to parse integer value type");
556 } 556 }
557 case 'r': 557 case 'r':
558 { 558 {
559 if (llsd.Length < 2) throw new LLSDParseException("Real value type with no value"); 559 if (llsd.Length < 2) throw new LLSDParseException("Real value type with no value");
560 double value; 560 double value;
561 endPos = FindEnd(llsd, 1); 561 endPos = FindEnd(llsd, 1);
562 562
563 if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float, 563 if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float,
564 Utils.EnUsCulture.NumberFormat, out value)) 564 Utils.EnUsCulture.NumberFormat, out value))
565 return value; 565 return value;
566 else 566 else
567 throw new LLSDParseException("Failed to parse double value type"); 567 throw new LLSDParseException("Failed to parse double value type");
568 } 568 }
569 case 'u': 569 case 'u':
570 { 570 {
571 if (llsd.Length < 17) throw new LLSDParseException("UUID value type with no value"); 571 if (llsd.Length < 17) throw new LLSDParseException("UUID value type with no value");
572 UUID value; 572 UUID value;
573 endPos = FindEnd(llsd, 1); 573 endPos = FindEnd(llsd, 1);
574 574
575 if (UUID.TryParse(llsd.Substring(1, endPos - 1), out value)) 575 if (UUID.TryParse(llsd.Substring(1, endPos - 1), out value))
576 return value; 576 return value;
577 else 577 else
578 throw new LLSDParseException("Failed to parse UUID value type"); 578 throw new LLSDParseException("Failed to parse UUID value type");
579 } 579 }
580 case 'b': 580 case 'b':
581 //byte[] value = new byte[llsd.Length - 1]; 581 //byte[] value = new byte[llsd.Length - 1];
582 // This isn't the actual binary LLSD format, just the terse format sent 582 // This isn't the actual binary LLSD format, just the terse format sent
583 // at login so I don't even know if there is a binary type 583 // at login so I don't even know if there is a binary type
584 throw new LLSDParseException("Binary value type is unimplemented"); 584 throw new LLSDParseException("Binary value type is unimplemented");
585 case 's': 585 case 's':
586 case 'l': 586 case 'l':
587 if (llsd.Length < 2) throw new LLSDParseException("String value type with no value"); 587 if (llsd.Length < 2) throw new LLSDParseException("String value type with no value");
588 endPos = FindEnd(llsd, 1); 588 endPos = FindEnd(llsd, 1);
589 return llsd.Substring(1, endPos - 1); 589 return llsd.Substring(1, endPos - 1);
590 case 'd': 590 case 'd':
591 // Never seen one before, don't know what the format is 591 // Never seen one before, don't know what the format is
592 throw new LLSDParseException("Date value type is unimplemented"); 592 throw new LLSDParseException("Date value type is unimplemented");
593 case '[': 593 case '[':
594 { 594 {
595 if (llsd.IndexOf(']') == -1) throw new LLSDParseException("Invalid array"); 595 if (llsd.IndexOf(']') == -1) throw new LLSDParseException("Invalid array");
596 596
597 int pos = 0; 597 int pos = 0;
598 ArrayList array = new ArrayList(); 598 ArrayList array = new ArrayList();
599 599
600 while (llsd[pos] != ']') 600 while (llsd[pos] != ']')
601 { 601 {
602 ++pos; 602 ++pos;
603 603
604 // Advance past comma if need be 604 // Advance past comma if need be
605 if (llsd[pos] == ',') ++pos; 605 if (llsd[pos] == ',') ++pos;
606 606
607 // Allow a single whitespace character 607 // Allow a single whitespace character
608 if (pos < llsd.Length && llsd[pos] == ' ') ++pos; 608 if (pos < llsd.Length && llsd[pos] == ' ') ++pos;
609 609
610 int end; 610 int end;
611 array.Add(ParseTerseLLSD(llsd.Substring(pos), out end)); 611 array.Add(ParseTerseLLSD(llsd.Substring(pos), out end));
612 pos += end; 612 pos += end;
613 } 613 }
614 614
615 endPos = pos + 1; 615 endPos = pos + 1;
616 return array; 616 return array;
617 } 617 }
618 case '{': 618 case '{':
619 { 619 {
620 if (llsd.IndexOf('}') == -1) throw new LLSDParseException("Invalid map"); 620 if (llsd.IndexOf('}') == -1) throw new LLSDParseException("Invalid map");
621 621
622 int pos = 0; 622 int pos = 0;
623 Hashtable hashtable = new Hashtable(); 623 Hashtable hashtable = new Hashtable();
624 624
625 while (llsd[pos] != '}') 625 while (llsd[pos] != '}')
626 { 626 {
627 ++pos; 627 ++pos;
628 628
629 // Advance past comma if need be 629 // Advance past comma if need be
630 if (llsd[pos] == ',') ++pos; 630 if (llsd[pos] == ',') ++pos;
631 631
632 // Allow a single whitespace character 632 // Allow a single whitespace character
633 if (pos < llsd.Length && llsd[pos] == ' ') ++pos; 633 if (pos < llsd.Length && llsd[pos] == ' ') ++pos;
634 634
635 if (llsd[pos] != '\'') throw new LLSDParseException("Expected a map key"); 635 if (llsd[pos] != '\'') throw new LLSDParseException("Expected a map key");
636 int endquote = llsd.IndexOf('\'', pos + 1); 636 int endquote = llsd.IndexOf('\'', pos + 1);
637 if (endquote == -1 || (endquote + 1) >= llsd.Length || llsd[endquote + 1] != ':') 637 if (endquote == -1 || (endquote + 1) >= llsd.Length || llsd[endquote + 1] != ':')
638 throw new LLSDParseException("Invalid map format"); 638 throw new LLSDParseException("Invalid map format");
639 string key = llsd.Substring(pos, endquote - pos); 639 string key = llsd.Substring(pos, endquote - pos);
640 key = key.Replace("'", String.Empty); 640 key = key.Replace("'", String.Empty);
641 pos += (endquote - pos) + 2; 641 pos += (endquote - pos) + 2;
642 642
643 int end; 643 int end;
644 hashtable.Add(key, ParseTerseLLSD(llsd.Substring(pos), out end)); 644 hashtable.Add(key, ParseTerseLLSD(llsd.Substring(pos), out end));
645 pos += end; 645 pos += end;
646 } 646 }
647 647
648 endPos = pos + 1; 648 endPos = pos + 1;
649 return hashtable; 649 return hashtable;
650 } 650 }
651 default: 651 default:
652 throw new Exception("Unknown value type"); 652 throw new Exception("Unknown value type");
653 } 653 }
654 } 654 }
655 655
656 private static int FindEnd(string llsd, int start) 656 private static int FindEnd(string llsd, int start)
657 { 657 {
658 int end = llsd.IndexOfAny(new char[] {',', ']', '}'}); 658 int end = llsd.IndexOfAny(new char[] {',', ']', '}'});
659 if (end == -1) end = llsd.Length - 1; 659 if (end == -1) end = llsd.Length - 1;
660 return end; 660 return end;
661 } 661 }
662 662
663 /// <summary> 663 /// <summary>
664 /// 664 ///
665 /// </summary> 665 /// </summary>
666 /// <param name="reader"></param> 666 /// <param name="reader"></param>
667 private static void SkipWS(XmlTextReader reader) 667 private static void SkipWS(XmlTextReader reader)
668 { 668 {
669 while ( 669 while (
670 reader.NodeType == XmlNodeType.Comment || 670 reader.NodeType == XmlNodeType.Comment ||
671 reader.NodeType == XmlNodeType.Whitespace || 671 reader.NodeType == XmlNodeType.Whitespace ||
672 reader.NodeType == XmlNodeType.SignificantWhitespace || 672 reader.NodeType == XmlNodeType.SignificantWhitespace ||
673 reader.NodeType == XmlNodeType.XmlDeclaration) 673 reader.NodeType == XmlNodeType.XmlDeclaration)
674 { 674 {
675 reader.Read(); 675 reader.Read();
676 } 676 }
677 } 677 }
678 } 678 }
679} 679}