aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/SLUtil.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/SLUtil.cs')
-rw-r--r--OpenSim/Framework/SLUtil.cs430
1 files changed, 319 insertions, 111 deletions
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index 537de7a..e66d5be 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -25,13 +25,9 @@
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 OpenMetaverse;
28using System; 29using System;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33using log4net;
34using OpenMetaverse;
35 31
36namespace OpenSim.Framework 32namespace OpenSim.Framework
37{ 33{
@@ -39,12 +35,36 @@ namespace OpenSim.Framework
39 { 35 {
40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 36// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 37
38 /// <summary>
39 /// Asset types used only in OpenSim.
40 /// To avoid clashing with the code numbers used in Second Life, use only negative numbers here.
41 /// </summary>
42 public enum OpenSimAssetType : sbyte
43 {
44 Material = -2
45 }
46
47
42 #region SL / file extension / content-type conversions 48 #region SL / file extension / content-type conversions
43 49
50 /// <summary>
51 /// Returns the Enum entry corresponding to the given code, regardless of whether it belongs
52 /// to the AssetType or OpenSimAssetType enums.
53 /// </summary>
54 public static object AssetTypeFromCode(sbyte assetType)
55 {
56 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
57 return (OpenMetaverse.AssetType)assetType;
58 else if (Enum.IsDefined(typeof(OpenSimAssetType), assetType))
59 return (OpenSimAssetType)assetType;
60 else
61 return OpenMetaverse.AssetType.Unknown;
62 }
63
44 private class TypeMapping 64 private class TypeMapping
45 { 65 {
46 private sbyte assetType; 66 private sbyte assetType;
47 private InventoryType inventoryType; 67 private sbyte inventoryType;
48 private string contentType; 68 private string contentType;
49 private string contentType2; 69 private string contentType2;
50 private string extension; 70 private string extension;
@@ -56,15 +76,10 @@ namespace OpenSim.Framework
56 76
57 public object AssetType 77 public object AssetType
58 { 78 {
59 get { 79 get { return AssetTypeFromCode(assetType); }
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else
63 return OpenMetaverse.AssetType.Unknown;
64 }
65 } 80 }
66 81
67 public InventoryType InventoryType 82 public sbyte InventoryType
68 { 83 {
69 get { return inventoryType; } 84 get { return inventoryType; }
70 } 85 }
@@ -84,7 +99,7 @@ namespace OpenSim.Framework
84 get { return extension; } 99 get { return extension; }
85 } 100 }
86 101
87 private TypeMapping(sbyte assetType, InventoryType inventoryType, string contentType, string contentType2, string extension) 102 private TypeMapping(sbyte assetType, sbyte inventoryType, string contentType, string contentType2, string extension)
88 { 103 {
89 this.assetType = assetType; 104 this.assetType = assetType;
90 this.inventoryType = inventoryType; 105 this.inventoryType = inventoryType;
@@ -93,13 +108,28 @@ namespace OpenSim.Framework
93 this.extension = extension; 108 this.extension = extension;
94 } 109 }
95 110
96 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string contentType2, string extension) 111 public TypeMapping(AssetType assetType, sbyte inventoryType, string contentType, string contentType2, string extension)
97 : this((sbyte)assetType, inventoryType, contentType, contentType2, extension) 112 : this((sbyte)assetType, inventoryType, contentType, contentType2, extension)
98 { 113 {
99 } 114 }
100 115
116 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string contentType2, string extension)
117 : this((sbyte)assetType, (sbyte)inventoryType, contentType, contentType2, extension)
118 {
119 }
120
101 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string extension) 121 public TypeMapping(AssetType assetType, InventoryType inventoryType, string contentType, string extension)
102 : this((sbyte)assetType, inventoryType, contentType, null, extension) 122 : this((sbyte)assetType, (sbyte)inventoryType, contentType, null, extension)
123 {
124 }
125
126 public TypeMapping(AssetType assetType, FolderType inventoryType, string contentType, string extension)
127 : this((sbyte)assetType, (sbyte)inventoryType, contentType, null, extension)
128 {
129 }
130
131 public TypeMapping(OpenSimAssetType assetType, InventoryType inventoryType, string contentType, string extension)
132 : this((sbyte)assetType, (sbyte)inventoryType, contentType, null, extension)
103 { 133 {
104 } 134 }
105 } 135 }
@@ -125,51 +155,65 @@ namespace OpenSim.Framework
125 new TypeMapping(AssetType.Object, InventoryType.Object, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"), 155 new TypeMapping(AssetType.Object, InventoryType.Object, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
126 new TypeMapping(AssetType.Object, InventoryType.Attachment, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"), 156 new TypeMapping(AssetType.Object, InventoryType.Attachment, "application/vnd.ll.primitive", "application/x-metaverse-primitive", "primitive"),
127 new TypeMapping(AssetType.Notecard, InventoryType.Notecard, "application/vnd.ll.notecard", "application/x-metaverse-notecard", "notecard"), 157 new TypeMapping(AssetType.Notecard, InventoryType.Notecard, "application/vnd.ll.notecard", "application/x-metaverse-notecard", "notecard"),
128 new TypeMapping(AssetType.Folder, InventoryType.Folder, "application/vnd.ll.folder", "folder"),
129 new TypeMapping(AssetType.RootFolder, InventoryType.RootCategory, "application/vnd.ll.rootfolder", "rootfolder"),
130 new TypeMapping(AssetType.LSLText, InventoryType.LSL, "application/vnd.ll.lsltext", "application/x-metaverse-lsl", "lsl"), 158 new TypeMapping(AssetType.LSLText, InventoryType.LSL, "application/vnd.ll.lsltext", "application/x-metaverse-lsl", "lsl"),
131 new TypeMapping(AssetType.LSLBytecode, InventoryType.LSL, "application/vnd.ll.lslbyte", "application/x-metaverse-lso", "lso"), 159 new TypeMapping(AssetType.LSLBytecode, InventoryType.LSL, "application/vnd.ll.lslbyte", "application/x-metaverse-lso", "lso"),
132 new TypeMapping(AssetType.Bodypart, InventoryType.Wearable, "application/vnd.ll.bodypart", "application/x-metaverse-bodypart", "bodypart"), 160 new TypeMapping(AssetType.Bodypart, InventoryType.Wearable, "application/vnd.ll.bodypart", "application/x-metaverse-bodypart", "bodypart"),
133 new TypeMapping(AssetType.TrashFolder, InventoryType.Folder, "application/vnd.ll.trashfolder", "trashfolder"),
134 new TypeMapping(AssetType.SnapshotFolder, InventoryType.Folder, "application/vnd.ll.snapshotfolder", "snapshotfolder"),
135 new TypeMapping(AssetType.LostAndFoundFolder, InventoryType.Folder, "application/vnd.ll.lostandfoundfolder", "lostandfoundfolder"),
136 new TypeMapping(AssetType.Animation, InventoryType.Animation, "application/vnd.ll.animation", "application/x-metaverse-animation", "animation"), 161 new TypeMapping(AssetType.Animation, InventoryType.Animation, "application/vnd.ll.animation", "application/x-metaverse-animation", "animation"),
137 new TypeMapping(AssetType.Gesture, InventoryType.Gesture, "application/vnd.ll.gesture", "application/x-metaverse-gesture", "gesture"), 162 new TypeMapping(AssetType.Gesture, InventoryType.Gesture, "application/vnd.ll.gesture", "application/x-metaverse-gesture", "gesture"),
138 new TypeMapping(AssetType.Simstate, InventoryType.Snapshot, "application/x-metaverse-simstate", "simstate"), 163 new TypeMapping(AssetType.Simstate, InventoryType.Snapshot, "application/x-metaverse-simstate", "simstate"),
139 new TypeMapping(AssetType.FavoriteFolder, InventoryType.Unknown, "application/vnd.ll.favoritefolder", "favoritefolder"),
140 new TypeMapping(AssetType.Link, InventoryType.Unknown, "application/vnd.ll.link", "link"), 164 new TypeMapping(AssetType.Link, InventoryType.Unknown, "application/vnd.ll.link", "link"),
141 new TypeMapping(AssetType.LinkFolder, InventoryType.Unknown, "application/vnd.ll.linkfolder", "linkfolder"), 165 new TypeMapping(AssetType.LinkFolder, InventoryType.Unknown, "application/vnd.ll.linkfolder", "linkfolder"),
142 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"), 166 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm"),
143 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"), 167
144 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"), 168 // The next few items are about inventory folders
145 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm") 169 new TypeMapping(AssetType.Folder, FolderType.None, "application/vnd.ll.folder", "folder"),
170 new TypeMapping(AssetType.Folder, FolderType.Root, "application/vnd.ll.rootfolder", "rootfolder"),
171 new TypeMapping(AssetType.Folder, FolderType.Trash, "application/vnd.ll.trashfolder", "trashfolder"),
172 new TypeMapping(AssetType.Folder, FolderType.Snapshot, "application/vnd.ll.snapshotfolder", "snapshotfolder"),
173 new TypeMapping(AssetType.Folder, FolderType.LostAndFound, "application/vnd.ll.lostandfoundfolder", "lostandfoundfolder"),
174 new TypeMapping(AssetType.Folder, FolderType.Favorites, "application/vnd.ll.favoritefolder", "favoritefolder"),
175 new TypeMapping(AssetType.Folder, FolderType.CurrentOutfit, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
176 new TypeMapping(AssetType.Folder, FolderType.Outfit, "application/vnd.ll.outfitfolder", "outfitfolder"),
177 new TypeMapping(AssetType.Folder, FolderType.MyOutfits, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
178
179 // This next mappping is an asset to inventory item mapping.
180 // Note: LL stores folders as assets of type Folder = 8, and it has a corresponding InventoryType = 8
181 // OpenSim doesn't store folders as assets, so this mapping should only be used when parsing things from the viewer to the server
182 new TypeMapping(AssetType.Folder, InventoryType.Folder, "application/vnd.ll.folder", "folder"),
183
184 // OpenSim specific
185 new TypeMapping(OpenSimAssetType.Material, InventoryType.Unknown, "application/llsd+xml", "material")
146 }; 186 };
147 187
148 private static Dictionary<sbyte, string> asset2Content; 188 private static Dictionary<sbyte, string> asset2Content;
149 private static Dictionary<sbyte, string> asset2Extension; 189 private static Dictionary<sbyte, string> asset2Extension;
150 private static Dictionary<InventoryType, string> inventory2Content; 190 private static Dictionary<sbyte, string> inventory2Content;
151 private static Dictionary<string, sbyte> content2Asset; 191 private static Dictionary<string, sbyte> content2Asset;
152 private static Dictionary<string, InventoryType> content2Inventory; 192 private static Dictionary<string, sbyte> content2Inventory;
153 193
154 static SLUtil() 194 static SLUtil()
155 { 195 {
156 asset2Content = new Dictionary<sbyte, string>(); 196 asset2Content = new Dictionary<sbyte, string>();
157 asset2Extension = new Dictionary<sbyte, string>(); 197 asset2Extension = new Dictionary<sbyte, string>();
158 inventory2Content = new Dictionary<InventoryType, string>(); 198 inventory2Content = new Dictionary<sbyte, string>();
159 content2Asset = new Dictionary<string, sbyte>(); 199 content2Asset = new Dictionary<string, sbyte>();
160 content2Inventory = new Dictionary<string, InventoryType>(); 200 content2Inventory = new Dictionary<string, sbyte>();
161 201
162 foreach (TypeMapping mapping in MAPPINGS) 202 foreach (TypeMapping mapping in MAPPINGS)
163 { 203 {
164 sbyte assetType = mapping.AssetTypeCode; 204 sbyte assetType = mapping.AssetTypeCode;
165 if (!asset2Content.ContainsKey(assetType)) 205 if (!asset2Content.ContainsKey(assetType))
166 asset2Content.Add(assetType, mapping.ContentType); 206 asset2Content.Add(assetType, mapping.ContentType);
207
167 if (!asset2Extension.ContainsKey(assetType)) 208 if (!asset2Extension.ContainsKey(assetType))
168 asset2Extension.Add(assetType, mapping.Extension); 209 asset2Extension.Add(assetType, mapping.Extension);
210
169 if (!inventory2Content.ContainsKey(mapping.InventoryType)) 211 if (!inventory2Content.ContainsKey(mapping.InventoryType))
170 inventory2Content.Add(mapping.InventoryType, mapping.ContentType); 212 inventory2Content.Add(mapping.InventoryType, mapping.ContentType);
213
171 if (!content2Asset.ContainsKey(mapping.ContentType)) 214 if (!content2Asset.ContainsKey(mapping.ContentType))
172 content2Asset.Add(mapping.ContentType, assetType); 215 content2Asset.Add(mapping.ContentType, assetType);
216
173 if (!content2Inventory.ContainsKey(mapping.ContentType)) 217 if (!content2Inventory.ContainsKey(mapping.ContentType))
174 content2Inventory.Add(mapping.ContentType, mapping.InventoryType); 218 content2Inventory.Add(mapping.ContentType, mapping.InventoryType);
175 219
@@ -194,8 +238,8 @@ namespace OpenSim.Framework
194 public static string SLInvTypeToContentType(int invType) 238 public static string SLInvTypeToContentType(int invType)
195 { 239 {
196 string contentType; 240 string contentType;
197 if (!inventory2Content.TryGetValue((InventoryType)invType, out contentType)) 241 if (!inventory2Content.TryGetValue((sbyte)invType, out contentType))
198 contentType = inventory2Content[InventoryType.Unknown]; 242 contentType = inventory2Content[(sbyte)InventoryType.Unknown];
199 return contentType; 243 return contentType;
200 } 244 }
201 245
@@ -209,9 +253,9 @@ namespace OpenSim.Framework
209 253
210 public static sbyte ContentTypeToSLInvType(string contentType) 254 public static sbyte ContentTypeToSLInvType(string contentType)
211 { 255 {
212 InventoryType invType; 256 sbyte invType;
213 if (!content2Inventory.TryGetValue(contentType, out invType)) 257 if (!content2Inventory.TryGetValue(contentType, out invType))
214 invType = InventoryType.Unknown; 258 invType = (sbyte)InventoryType.Unknown;
215 return (sbyte)invType; 259 return (sbyte)invType;
216 } 260 }
217 261
@@ -225,106 +269,270 @@ namespace OpenSim.Framework
225 269
226 #endregion SL / file extension / content-type conversions 270 #endregion SL / file extension / content-type conversions
227 271
228 /// <summary> 272 private class NotecardReader
229 /// Parse a notecard in Linden format to a string of ordinary text.
230 /// </summary>
231 /// <param name="rawInput"></param>
232 /// <returns></returns>
233 public static string ParseNotecardToString(string rawInput)
234 { 273 {
235 string[] output = ParseNotecardToList(rawInput).ToArray(); 274 private string rawInput;
275 private int lineNumber;
236 276
237// foreach (string line in output) 277 public int LineNumber
238// m_log.DebugFormat("[PARSE NOTECARD]: ParseNotecardToString got line {0}", line); 278 {
239 279 get
240 return string.Join("\n", output); 280 {
281 return lineNumber;
282 }
283 }
284
285 public NotecardReader(string _rawInput)
286 {
287 rawInput = (string)_rawInput.Clone();
288 lineNumber = 0;
289 }
290
291 public string getLine()
292 {
293 if(rawInput.Length == 0)
294 {
295 throw new NotANotecardFormatException(lineNumber + 1);
296 }
297
298 int pos = rawInput.IndexOf('\n');
299 if(pos < 0)
300 {
301 pos = rawInput.Length;
302 }
303
304 /* cut line from rest */
305 ++lineNumber;
306 string line = rawInput.Substring(0, pos);
307 if (pos + 1 >= rawInput.Length)
308 {
309 rawInput = string.Empty;
310 }
311 else
312 {
313 rawInput = rawInput.Substring(pos + 1);
314 }
315 /* clean up line from double spaces and tabs */
316 line = line.Replace("\t", " ");
317 while(line.IndexOf(" ") >= 0)
318 {
319 line = line.Replace(" ", " ");
320 }
321 return line.Replace("\r", "").Trim();
322 }
323
324 public string getBlock(int length)
325 {
326 /* cut line from rest */
327 if(length > rawInput.Length)
328 {
329 throw new NotANotecardFormatException(lineNumber);
330 }
331 string line = rawInput.Substring(0, length);
332 rawInput = rawInput.Substring(length);
333 return line;
334 }
241 } 335 }
242 336
243 /// <summary> 337 public class NotANotecardFormatException : Exception
244 /// Parse a notecard in Linden format to a list of ordinary lines. 338 {
245 /// </summary> 339 public int lineNumber;
246 /// <param name="rawInput"></param> 340 public NotANotecardFormatException(int _lineNumber)
247 /// <returns></returns> 341 : base()
248 public static List<string> ParseNotecardToList(string rawInput) 342 {
343 lineNumber = _lineNumber;
344 }
345 }
346
347 private static void skipSection(NotecardReader reader)
249 { 348 {
250 string[] input = rawInput.Replace("\r", "").Split('\n'); 349 if (reader.getLine() != "{")
251 int idx = 0; 350 throw new NotANotecardFormatException(reader.LineNumber);
252 int level = 0;
253 List<string> output = new List<string>();
254 string[] words;
255 351
256 while (idx < input.Length) 352 string line;
353 while ((line = reader.getLine()) != "}")
257 { 354 {
258 if (input[idx] == "{") 355 if(line.IndexOf('{')>=0)
356 {
357 throw new NotANotecardFormatException(reader.LineNumber);
358 }
359 }
360 }
361
362 private static void skipInventoryItem(NotecardReader reader)
363 {
364 if (reader.getLine() != "{")
365 throw new NotANotecardFormatException(reader.LineNumber);
366
367 string line;
368 while((line = reader.getLine()) != "}")
369 {
370 string[] data = line.Split(' ');
371 if(data.Length == 0)
259 { 372 {
260 level++;
261 idx++;
262 continue; 373 continue;
263 } 374 }
375 if(data[0] == "permissions")
376 {
377 skipSection(reader);
378 }
379 else if(data[0] == "sale_info")
380 {
381 skipSection(reader);
382 }
383 else if (line.IndexOf('{') >= 0)
384 {
385 throw new NotANotecardFormatException(reader.LineNumber);
386 }
387 }
388 }
389
390 private static void skipInventoryItems(NotecardReader reader)
391 {
392 if(reader.getLine() != "{")
393 {
394 throw new NotANotecardFormatException(reader.LineNumber);
395 }
264 396
265 if (input[idx]== "}") 397 string line;
398 while((line = reader.getLine()) != "}")
399 {
400 string[] data = line.Split(' ');
401 if(data.Length == 0)
266 { 402 {
267 level--;
268 idx++;
269 continue; 403 continue;
270 } 404 }
271 405
272 switch (level) 406 if(data[0] == "inv_item")
407 {
408 skipInventoryItem(reader);
409 }
410 else if (line.IndexOf('{') >= 0)
411 {
412 throw new NotANotecardFormatException(reader.LineNumber);
413 }
414
415 }
416 }
417
418 private static void skipInventory(NotecardReader reader)
419 {
420 if (reader.getLine() != "{")
421 throw new NotANotecardFormatException(reader.LineNumber);
422
423 string line;
424 while((line = reader.getLine()) != "}")
425 {
426 string[] data = line.Split(' ');
427 if(data[0] == "count")
273 { 428 {
274 case 0: 429 int count = Int32.Parse(data[1]);
275 words = input[idx].Split(' '); // Linden text ver 430 for(int i = 0; i < count; ++i)
276 // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard)
277 if (words.Length < 3)
278 return output;
279
280 int version = int.Parse(words[3]);
281 if (version != 2)
282 return output;
283 break;
284 case 1:
285 words = input[idx].Split(' ');
286 if (words[0] == "LLEmbeddedItems")
287 break;
288 if (words[0] == "Text")
289 { 431 {
290 int len = int.Parse(words[2]); 432 skipInventoryItems(reader);
291 idx++; 433 }
434 }
435 else if (line.IndexOf('{') >= 0)
436 {
437 throw new NotANotecardFormatException(reader.LineNumber);
438 }
439 }
440 }
441
442 private static string readNotecardText(NotecardReader reader)
443 {
444 if (reader.getLine() != "{")
445 throw new NotANotecardFormatException(reader.LineNumber);
446
447 string notecardString = string.Empty;
448 string line;
449 while((line = reader.getLine()) != "}")
450 {
451 string[] data = line.Split(' ');
452 if (data.Length == 0)
453 {
454 continue;
455 }
292 456
293 int count = -1; 457 if (data[0] == "LLEmbeddedItems")
458 {
459 skipInventory(reader);
460 }
461 else if(data[0] == "Text" && data.Length == 3)
462 {
463 int length = Int32.Parse(data[2]);
464 notecardString = reader.getBlock(length);
465 }
466 else if (line.IndexOf('{') >= 0)
467 {
468 throw new NotANotecardFormatException(reader.LineNumber);
469 }
294 470
295 while (count < len && idx < input.Length) 471 }
296 { 472 return notecardString;
297 // int l = input[idx].Length; 473 }
298 string ln = input[idx];
299 474
300 int need = len-count-1; 475 private static string readNotecard(byte[] rawInput)
301 if (ln.Length > need) 476 {
302 ln = ln.Substring(0, need); 477 string rawIntermedInput = string.Empty;
303 478
304// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", ln); 479 /* make up a Raw Encoding here */
305 output.Add(ln); 480 foreach(byte c in rawInput)
306 count += ln.Length + 1; 481 {
307 idx++; 482 char d = (char)c;
308 } 483 rawIntermedInput += d;
484 }
309 485
310 return output; 486 NotecardReader reader = new NotecardReader(rawIntermedInput);
311 } 487 string line;
312 break; 488 try
313 case 2: 489 {
314 words = input[idx].Split(' '); // count 490 line = reader.getLine();
315 if (words[0] == "count") 491 }
316 { 492 catch(Exception)
317 int c = int.Parse(words[1]); 493 {
318 if (c > 0) 494 return System.Text.Encoding.UTF8.GetString(rawInput);
319 return output; 495 }
320 break; 496 string[] versioninfo = line.Split(' ');
321 } 497 if(versioninfo.Length < 3)
322 break; 498 {
499 return System.Text.Encoding.UTF8.GetString(rawInput);
500 }
501 else if(versioninfo[0] != "Linden" || versioninfo[1] != "text")
502 {
503 return System.Text.Encoding.UTF8.GetString(rawInput);
504 }
505 else
506 {
507 /* now we actually decode the Encoding, before we needed it in raw */
508 string o = readNotecardText(reader);
509 byte[] a = new byte[o.Length];
510 for(int i = 0; i < o.Length; ++i)
511 {
512 a[i] = (byte)o[i];
323 } 513 }
324 idx++; 514 return System.Text.Encoding.UTF8.GetString(a);
325 } 515 }
326 516 }
327 return output; 517
518 /// <summary>
519 /// Parse a notecard in Linden format to a string of ordinary text.
520 /// </summary>
521 /// <param name="rawInput"></param>
522 /// <returns></returns>
523 public static string ParseNotecardToString(byte[] rawInput)
524 {
525 return readNotecard(rawInput);
526 }
527
528 /// <summary>
529 /// Parse a notecard in Linden format to a list of ordinary lines.
530 /// </summary>
531 /// <param name="rawInput"></param>
532 /// <returns></returns>
533 public static string[] ParseNotecardToArray(byte[] rawInput)
534 {
535 return readNotecard(rawInput).Replace("\r", "").Split('\n');
328 } 536 }
329 } 537 }
330} 538}