From 1abbad71b4603245e5481c11e3ce55f57b64935f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 5 May 2015 20:59:09 -0700 Subject: Refactored some code that is used in two different dlls related to SOP rewriting. Also added some unit tests that relate to mantis #7514 --- .../External/ExternalRepresentationUtils.cs | 184 ++++++++++++++++++++- 1 file changed, 183 insertions(+), 1 deletion(-) (limited to 'OpenSim/Framework/Serialization') diff --git a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs index 6debf65..64de18b 100644 --- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs +++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs @@ -125,7 +125,8 @@ namespace OpenSim.Framework.Serialization.External /// The service for retrieving user account information /// The scope of the user account information (Grid ID) /// The SceneObjectPart represented in XML2 - public static string RewriteSOP(string xml, string homeURL, IUserAccountService userService, UUID scopeID) + [Obsolete("This method is deprecated. Use RewriteSOP instead.")] + public static string RewriteSOP_Old(string xml, string homeURL, IUserAccountService userService, UUID scopeID) { if (xml == string.Empty || homeURL == string.Empty || userService == null) return xml; @@ -173,6 +174,187 @@ namespace OpenSim.Framework.Serialization.External } } + /// + /// Takes a XML representation of a SceneObjectPart and returns another XML representation + /// with creator data added to it. + /// + /// The SceneObjectPart represented in XML2 + /// An identifier for the component that's calling this function + /// The URL of the user agents service (home) for the creator + /// The service for retrieving user account information + /// The scope of the user account information (Grid ID) + /// The SceneObjectPart represented in XML2 + public static string RewriteSOP(string xmlData, string sceneName, string homeURL, IUserAccountService userService, UUID scopeID) + { + // Console.WriteLine("Input XML [{0}]", xmlData); + if (xmlData == string.Empty || homeURL == string.Empty || userService == null) + return xmlData; + + using (StringWriter sw = new StringWriter()) + using (XmlTextWriter writer = new XmlTextWriter(sw)) + using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) + using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) + { + TransformXml(reader, writer, sceneName, homeURL, userService, scopeID); + + // Console.WriteLine("Output: [{0}]", sw.ToString()); + + return sw.ToString(); + } + } + + protected static void TransformXml(XmlReader reader, XmlWriter writer, string sceneName, string homeURI, IUserAccountService userAccountService, UUID scopeID) + { + // m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML"); + + int sopDepth = -1; + UserAccount creator = null; + bool hasCreatorData = false; + + while (reader.Read()) + { + // Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name); + + switch (reader.NodeType) + { + case XmlNodeType.Attribute: + // Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name); + writer.WriteAttributeString(reader.Name, reader.Value); + break; + + case XmlNodeType.CDATA: + writer.WriteCData(reader.Value); + break; + + case XmlNodeType.Comment: + writer.WriteComment(reader.Value); + break; + + case XmlNodeType.DocumentType: + writer.WriteDocType(reader.Name, reader.Value, null, null); + break; + + case XmlNodeType.Element: + // m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name); + + writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI); + + if (reader.HasAttributes) + { + while (reader.MoveToNextAttribute()) + writer.WriteAttributeString(reader.Name, reader.Value); + + reader.MoveToElement(); + } + + if (reader.LocalName == "SceneObjectPart") + { + if (sopDepth < 0) + { + sopDepth = reader.Depth; + // m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth); + } + } + else + { + if (sopDepth >= 0 && reader.Depth == sopDepth + 1) + { + if (reader.Name == "CreatorID") + { + reader.Read(); + if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID") + { + reader.Read(); + + if (reader.NodeType == XmlNodeType.Text) + { + UUID uuid = UUID.Zero; + UUID.TryParse(reader.Value, out uuid); + creator = userAccountService.GetUserAccount(scopeID, uuid); + writer.WriteElementString("UUID", reader.Value); + reader.Read(); + } + else + { + // If we unexpected run across mixed content in this node, still carry on + // transforming the subtree (this replicates earlier behaviour). + TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID); + } + } + else + { + // If we unexpected run across mixed content in this node, still carry on + // transforming the subtree (this replicates earlier behaviour). + TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID); + } + } + else if (reader.Name == "CreatorData") + { + reader.Read(); + if (reader.NodeType == XmlNodeType.Text) + { + hasCreatorData = true; + writer.WriteString(reader.Value); + } + else + { + // If we unexpected run across mixed content in this node, still carry on + // transforming the subtree (this replicates earlier behaviour). + TransformXml(reader, writer, sceneName, homeURI, userAccountService, scopeID); + } + } + } + } + + if (reader.IsEmptyElement) + { + // m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name); + writer.WriteEndElement(); + } + + break; + + case XmlNodeType.EndElement: + // m_log.DebugFormat("Depth {0} at EndElement", reader.Depth); + if (sopDepth == reader.Depth) + { + if (!hasCreatorData && creator != null) + writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", homeURI, creator.FirstName, creator.LastName)); + + // m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth"); + sopDepth = -1; + creator = null; + hasCreatorData = false; + } + writer.WriteEndElement(); + break; + + case XmlNodeType.EntityReference: + writer.WriteEntityRef(reader.Name); + break; + + case XmlNodeType.ProcessingInstruction: + writer.WriteProcessingInstruction(reader.Name, reader.Value); + break; + + case XmlNodeType.Text: + writer.WriteString(reader.Value); + break; + + case XmlNodeType.XmlDeclaration: + // For various reasons, not all serializations have xml declarations (or consistent ones) + // and as it's embedded inside a byte stream we don't need it anyway, so ignore. + break; + + default: + m_log.WarnFormat( + "[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}", + reader.NodeType, sceneName); + break; + } + } + } + public static string CalcCreatorData(string homeURL, string name) { return homeURL + ";" + name; -- cgit v1.1