diff --git a/LibreMetaverse.StructuredData/LLSD/XmlLLSD.cs b/LibreMetaverse.StructuredData/LLSD/XmlLLSD.cs
index ca53f055..e3c168c9 100644
--- a/LibreMetaverse.StructuredData/LLSD/XmlLLSD.cs
+++ b/LibreMetaverse.StructuredData/LLSD/XmlLLSD.cs
@@ -38,29 +38,52 @@ namespace OpenMetaverse.StructuredData
///
public static partial class OSDParser
{
+ private static string linden_lab_loves_bad_pi = " LLSD/";
+
///
- ///
+ /// Deserialize LLSD/XML stream
///
- ///
+ /// a containing the serialized data
///
public static OSD DeserializeLLSDXml(Stream xmlStream)
{
+ // XmlReader don't take no shit from nobody. Parse out Linden Lab's bad PI.
+ bool match = true;
+ for (int i = 0; i < linden_lab_loves_bad_pi.Length; ++i)
+ {
+ if (xmlStream.ReadByte() != linden_lab_loves_bad_pi[i])
+ {
+ match = false;
+ break;
+ }
+ }
+ if (match)
+ {
+ // read until the linebreak >
+ while (xmlStream.ReadByte() != '\n')
+ { }
+ } else {
+ xmlStream.Seek(0, SeekOrigin.Begin);
+ }
+
XmlReaderSettings settings = new XmlReaderSettings
{
ValidationType = ValidationType.None,
CheckCharacters = false,
IgnoreComments = true,
- IgnoreProcessingInstructions = true,
- DtdProcessing = DtdProcessing.Prohibit
+ IgnoreProcessingInstructions = false,
+ DtdProcessing = DtdProcessing.Ignore
};
using (XmlReader xrd = XmlReader.Create(xmlStream))
+ {
return DeserializeLLSDXml(xrd);
+ }
}
///
- ///
+ /// Deserialize LLSD/XML stream
///
- ///
+ /// Data as a byte array
///
public static OSD DeserializeLLSDXml(byte[] xmlData)
{
@@ -68,9 +91,9 @@ namespace OpenMetaverse.StructuredData
}
///
- ///
+ /// Deserialize LLSD/XML stream
///
- ///
+ /// Serialized data as a
///
public static OSD DeserializeLLSDXml(string xmlData)
{
@@ -79,9 +102,9 @@ namespace OpenMetaverse.StructuredData
}
///
- ///
+ /// Deserialize LLSD/XML stream
///
- ///
+ /// Serialized data as a
///
public static OSD DeserializeLLSDXml(XmlReader xmlData)
{
@@ -95,17 +118,18 @@ namespace OpenMetaverse.StructuredData
return ret;
}
- catch
+ catch (XmlException ex)
{
+ string exs = ex.ToString();
return new OSD();
}
}
///
- ///
+ /// Serialize an OSD object in LLSD/XML
///
- ///
- ///
+ /// OSD object to serialize
+ /// Serialized data as a byte aray
public static byte[] SerializeLLSDXmlBytes(OSD data)
{
return Encoding.UTF8.GetBytes(SerializeLLSDXmlString(data));
@@ -119,7 +143,7 @@ namespace OpenMetaverse.StructuredData
public static string SerializeLLSDXmlString(OSD data)
{
StringWriter sw = new StringWriter();
- using(XmlTextWriter writer = new XmlTextWriter(sw))
+ using (XmlTextWriter writer = new XmlTextWriter(sw))
{
writer.Formatting = Formatting.None;
diff --git a/LibreMetaverse.StructuredData/StructuredData.cs b/LibreMetaverse.StructuredData/StructuredData.cs
index f9df46c6..73dbb20b 100644
--- a/LibreMetaverse.StructuredData/StructuredData.cs
+++ b/LibreMetaverse.StructuredData/StructuredData.cs
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2006-2016, openmetaverse.co
+ * Copyright (c) 2021, Sjofn LLC.
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
@@ -1246,7 +1247,7 @@ namespace OpenMetaverse.StructuredData
public static OSD Deserialize(Stream stream)
{
- if (!stream.CanSeek) throw new OSDException("Cannot deserialize structured data from unseekable streams");
+ if (!stream.CanSeek) { throw new OSDException("Cannot deserialize structured data from unseekable streams"); }
byte[] headerData = new byte[14];
stream.Read(headerData, 0, 14);
diff --git a/LibreMetaverse.Tests/XmlLLSDTests.cs b/LibreMetaverse.Tests/XmlLLSDTests.cs
index f895131b..863188e5 100644
--- a/LibreMetaverse.Tests/XmlLLSDTests.cs
+++ b/LibreMetaverse.Tests/XmlLLSDTests.cs
@@ -180,6 +180,32 @@ namespace OpenMetaverse.Tests
Assert.AreEqual(map["NAME"].AsString(), "Hippotropolis");
}
+ ///
+ /// Test LLSD with a silly Linden Lab PI.
+ ///
+ [Test]
+ public void DeserializeSillyPI()
+ {
+ string testSD = @" LLSD/XML ?>\n
+
+
+ \n";
+
+ byte[] bytes = Encoding.UTF8.GetBytes(testSD);
+ OSD theSD = OSDParser.DeserializeLLSDXml(bytes);
+
+ Assert.IsTrue(theSD is OSDMap);
+ OSDMap map = (OSDMap)theSD;
+
+ Assert.AreEqual(map["MINUTES"].AsInteger(), 5);
+ Assert.AreEqual(map["NAME"].AsString(), "Hippotropolis");
+ }
+
///
/// Test that various Real representations are parsed correctly.
///