/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSimulator Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.IO; using System.Threading; using System.Collections; using System.Collections.Generic; using System.Security.Policy; using System.Reflection; using System.Globalization; using System.Xml; using OpenMetaverse; using log4net; using Nini.Config; using Amib.Threading; using OpenSim.Framework; using OpenSim.Region.CoreModules; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; using OpenSim.Region.ScriptEngine.Shared.ScriptBase; using OpenSim.Region.ScriptEngine.Shared.CodeTools; using OpenSim.Region.ScriptEngine.Interfaces; namespace OpenSim.Region.ScriptEngine.Shared.Instance { public class ScriptSerializer { public static string Serialize(ScriptInstance instance) { bool running = instance.Running; XmlDocument xmldoc = new XmlDocument(); XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, "", ""); xmldoc.AppendChild(xmlnode); XmlElement rootElement = xmldoc.CreateElement("", "ScriptState", ""); xmldoc.AppendChild(rootElement); XmlElement state = xmldoc.CreateElement("", "State", ""); state.AppendChild(xmldoc.CreateTextNode(instance.State)); rootElement.AppendChild(state); XmlElement run = xmldoc.CreateElement("", "Running", ""); run.AppendChild(xmldoc.CreateTextNode( running.ToString())); rootElement.AppendChild(run); Dictionary<string, Object> vars = instance.GetVars(); XmlElement variables = xmldoc.CreateElement("", "Variables", ""); foreach (KeyValuePair<string, Object> var in vars) WriteTypedValue(xmldoc, variables, "Variable", var.Key, var.Value); rootElement.AppendChild(variables); XmlElement queue = xmldoc.CreateElement("", "Queue", ""); int count = instance.EventQueue.Count; while (count > 0) { EventParams ep = (EventParams)instance.EventQueue.Dequeue(); instance.EventQueue.Enqueue(ep); count--; XmlElement item = xmldoc.CreateElement("", "Item", ""); XmlAttribute itemEvent = xmldoc.CreateAttribute("", "event", ""); itemEvent.Value = ep.EventName; item.Attributes.Append(itemEvent); XmlElement parms = xmldoc.CreateElement("", "Params", ""); foreach (Object o in ep.Params) WriteTypedValue(xmldoc, parms, "Param", String.Empty, o); item.AppendChild(parms); XmlElement detect = xmldoc.CreateElement("", "Detected", ""); foreach (DetectParams det in ep.DetectParams) { XmlElement objectElem = xmldoc.CreateElement("", "Object", ""); XmlAttribute pos = xmldoc.CreateAttribute("", "pos", ""); pos.Value = det.OffsetPos.ToString(); objectElem.Attributes.Append(pos); XmlAttribute d_linkNum = xmldoc.CreateAttribute("", "linkNum", ""); d_linkNum.Value = det.LinkNum.ToString(); objectElem.Attributes.Append(d_linkNum); XmlAttribute d_group = xmldoc.CreateAttribute("", "group", ""); d_group.Value = det.Group.ToString(); objectElem.Attributes.Append(d_group); XmlAttribute d_name = xmldoc.CreateAttribute("", "name", ""); d_name.Value = det.Name.ToString(); objectElem.Attributes.Append(d_name); XmlAttribute d_owner = xmldoc.CreateAttribute("", "owner", ""); d_owner.Value = det.Owner.ToString(); objectElem.Attributes.Append(d_owner); XmlAttribute d_position = xmldoc.CreateAttribute("", "position", ""); d_position.Value = det.Position.ToString(); objectElem.Attributes.Append(d_position); XmlAttribute d_rotation = xmldoc.CreateAttribute("", "rotation", ""); d_rotation.Value = det.Rotation.ToString(); objectElem.Attributes.Append(d_rotation); XmlAttribute d_type = xmldoc.CreateAttribute("", "type", ""); d_type.Value = det.Type.ToString(); objectElem.Attributes.Append(d_type); XmlAttribute d_velocity = xmldoc.CreateAttribute("", "velocity", ""); d_velocity.Value = det.Velocity.ToString(); objectElem.Attributes.Append(d_velocity); objectElem.AppendChild( xmldoc.CreateTextNode(det.Key.ToString())); detect.AppendChild(objectElem); } item.AppendChild(detect); queue.AppendChild(item); } rootElement.AppendChild(queue); XmlNode plugins = xmldoc.CreateElement("", "Plugins", ""); DumpList(xmldoc, plugins, new LSL_Types.list(instance.PluginData)); rootElement.AppendChild(plugins); if (instance.ScriptTask != null) { if (instance.ScriptTask.PermsMask != 0 && instance.ScriptTask.PermsGranter != UUID.Zero) { XmlNode permissions = xmldoc.CreateElement("", "Permissions", ""); XmlAttribute granter = xmldoc.CreateAttribute("", "granter", ""); granter.Value = instance.ScriptTask.PermsGranter.ToString(); permissions.Attributes.Append(granter); XmlAttribute mask = xmldoc.CreateAttribute("", "mask", ""); mask.Value = instance.ScriptTask.PermsMask.ToString(); permissions.Attributes.Append(mask); rootElement.AppendChild(permissions); } } if (instance.MinEventDelay > 0.0) { XmlElement eventDelay = xmldoc.CreateElement("", "MinEventDelay", ""); eventDelay.AppendChild(xmldoc.CreateTextNode(instance.MinEventDelay.ToString())); rootElement.AppendChild(eventDelay); } return xmldoc.InnerXml; } public static void Deserialize(string xml, ScriptInstance instance) { XmlDocument doc = new XmlDocument(); Dictionary<string, object> vars = instance.GetVars(); instance.PluginData = new Object[0]; doc.LoadXml(xml); XmlNodeList rootL = doc.GetElementsByTagName("ScriptState"); if (rootL.Count != 1) { return; } XmlNode rootNode = rootL[0]; if (rootNode != null) { object varValue; XmlNodeList partL = rootNode.ChildNodes; foreach (XmlNode part in partL) { switch (part.Name) { case "State": instance.State=part.InnerText; break; case "Running": instance.Running=bool.Parse(part.InnerText); break; case "Variables": XmlNodeList varL = part.ChildNodes; foreach (XmlNode var in varL) { string varName; varValue=ReadTypedValue(var, out varName); if (vars.ContainsKey(varName)) vars[varName] = varValue; } instance.SetVars(vars); break; case "Queue": XmlNodeList itemL = part.ChildNodes; foreach (XmlNode item in itemL) { List<Object> parms = new List<Object>(); List<DetectParams> detected = new List<DetectParams>(); string eventName = item.Attributes.GetNamedItem("event").Value; XmlNodeList eventL = item.ChildNodes; foreach (XmlNode evt in eventL) { switch (evt.Name) { case "Params": XmlNodeList prms = evt.ChildNodes; foreach (XmlNode pm in prms) parms.Add(ReadTypedValue(pm)); break; case "Detected": XmlNodeList detL = evt.ChildNodes; foreach (XmlNode det in detL) { string vect = det.Attributes.GetNamedItem( "pos").Value; LSL_Types.Vector3 v = new LSL_Types.Vector3(vect); int d_linkNum=0; UUID d_group = UUID.Zero; string d_name = String.Empty; UUID d_owner = UUID.Zero; LSL_Types.Vector3 d_position = new LSL_Types.Vector3(); LSL_Types.Quaternion d_rotation = new LSL_Types.Quaternion(); int d_type = 0; LSL_Types.Vector3 d_velocity = new LSL_Types.Vector3(); try { string tmp; tmp = det.Attributes.GetNamedItem( "linkNum").Value; int.TryParse(tmp, out d_linkNum); tmp = det.Attributes.GetNamedItem( "group").Value; UUID.TryParse(tmp, out d_group); d_name = det.Attributes.GetNamedItem( "name").Value; tmp = det.Attributes.GetNamedItem( "owner").Value; UUID.TryParse(tmp, out d_owner); tmp = det.Attributes.GetNamedItem( "position").Value; d_position = new LSL_Types.Vector3(tmp); tmp = det.Attributes.GetNamedItem( "rotation").Value; d_rotation = new LSL_Types.Quaternion(tmp); tmp = det.Attributes.GetNamedItem( "type").Value; int.TryParse(tmp, out d_type); tmp = det.Attributes.GetNamedItem( "velocity").Value; d_velocity = new LSL_Types.Vector3(tmp); } catch (Exception) // Old version XML { } UUID uuid = new UUID(); UUID.TryParse(det.InnerText, out uuid); DetectParams d = new DetectParams(); d.Key = uuid; d.OffsetPos = v; d.LinkNum = d_linkNum; d.Group = d_group; d.Name = d_name; d.Owner = d_owner; d.Position = d_position; d.Rotation = d_rotation; d.Type = d_type; d.Velocity = d_velocity; detected.Add(d); } break; } } EventParams ep = new EventParams( eventName, parms.ToArray(), detected.ToArray()); instance.EventQueue.Enqueue(ep); } break; case "Plugins": instance.PluginData = ReadList(part).Data; break; case "Permissions": string tmpPerm; int mask = 0; tmpPerm = part.Attributes.GetNamedItem("mask").Value; if (tmpPerm != null) { int.TryParse(tmpPerm, out mask); if (mask != 0) { tmpPerm = part.Attributes.GetNamedItem("granter").Value; if (tmpPerm != null) { UUID granter = new UUID(); UUID.TryParse(tmpPerm, out granter); if (granter != UUID.Zero) { instance.ScriptTask.PermsMask = mask; instance.ScriptTask.PermsGranter = granter; } } } } break; case "MinEventDelay": double minEventDelay = 0.0; double.TryParse(part.InnerText, NumberStyles.Float, Culture.NumberFormatInfo, out minEventDelay); instance.MinEventDelay = minEventDelay; break; } } } } private static void DumpList(XmlDocument doc, XmlNode parent, LSL_Types.list l) { foreach (Object o in l.Data) WriteTypedValue(doc, parent, "ListItem", "", o); } private static LSL_Types.list ReadList(XmlNode parent) { List<Object> olist = new List<Object>(); XmlNodeList itemL = parent.ChildNodes; foreach (XmlNode item in itemL) olist.Add(ReadTypedValue(item)); return new LSL_Types.list(olist.ToArray()); } private static void WriteTypedValue(XmlDocument doc, XmlNode parent, string tag, string name, object value) { Type t=value.GetType(); XmlAttribute typ = doc.CreateAttribute("", "type", ""); XmlNode n = doc.CreateElement("", tag, ""); if (value is LSL_Types.list) { typ.Value = "list"; n.Attributes.Append(typ); DumpList(doc, n, (LSL_Types.list) value); if (name != String.Empty) { XmlAttribute nam = doc.CreateAttribute("", "name", ""); nam.Value = name; n.Attributes.Append(nam); } parent.AppendChild(n); return; } n.AppendChild(doc.CreateTextNode(value.ToString())); typ.Value = t.ToString(); n.Attributes.Append(typ); if (name != String.Empty) { XmlAttribute nam = doc.CreateAttribute("", "name", ""); nam.Value = name; n.Attributes.Append(nam); } parent.AppendChild(n); } private static object ReadTypedValue(XmlNode tag, out string name) { name = tag.Attributes.GetNamedItem("name").Value; return ReadTypedValue(tag); } private static object ReadTypedValue(XmlNode tag) { Object varValue; string assembly; string itemType = tag.Attributes.GetNamedItem("type").Value; if (itemType == "list") return ReadList(tag); if (itemType == "OpenMetaverse.UUID") { UUID val = new UUID(); UUID.TryParse(tag.InnerText, out val); return val; } Type itemT = Type.GetType(itemType); if (itemT == null) { Object[] args = new Object[] { tag.InnerText }; assembly = itemType+", OpenSim.Region.ScriptEngine.Shared"; itemT = Type.GetType(assembly); if (itemT == null) return null; varValue = Activator.CreateInstance(itemT, args); if (varValue == null) return null; } else { varValue = Convert.ChangeType(tag.InnerText, itemT); } return varValue; } } }