From fb2f4f158c42ecfea114eb7cefd9074dc001626f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Dec 2011 22:39:12 +0000 Subject: Refactor RemoteAdminPlugin so that every xmlrpc method calls a common block of code to do password checks, etc., instead of copy/pasting this code into every method --- .../RemoteController/RemoteAdminPlugin.cs | 3911 +++++++++----------- 1 file changed, 1785 insertions(+), 2126 deletions(-) (limited to 'OpenSim/ApplicationPlugins') diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 1b289a6..1da7c35 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -124,37 +124,37 @@ namespace OpenSim.ApplicationPlugins.RemoteController m_httpServer = MainServer.GetHttpServer((uint)port,ipaddr); Dictionary availableMethods = new Dictionary(); - availableMethods["admin_create_region"] = XmlRpcCreateRegionMethod; - availableMethods["admin_delete_region"] = XmlRpcDeleteRegionMethod; - availableMethods["admin_close_region"] = XmlRpcCloseRegionMethod; - availableMethods["admin_modify_region"] = XmlRpcModifyRegionMethod; - availableMethods["admin_region_query"] = XmlRpcRegionQueryMethod; - availableMethods["admin_shutdown"] = XmlRpcShutdownMethod; - availableMethods["admin_broadcast"] = XmlRpcAlertMethod; - availableMethods["admin_restart"] = XmlRpcRestartMethod; - availableMethods["admin_load_heightmap"] = XmlRpcLoadHeightmapMethod; - availableMethods["admin_save_heightmap"] = XmlRpcSaveHeightmapMethod; + availableMethods["admin_create_region"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcCreateRegionMethod); + availableMethods["admin_delete_region"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcDeleteRegionMethod); + availableMethods["admin_close_region"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcCloseRegionMethod); + availableMethods["admin_modify_region"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcModifyRegionMethod); + availableMethods["admin_region_query"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRegionQueryMethod); + availableMethods["admin_shutdown"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcShutdownMethod); + availableMethods["admin_broadcast"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAlertMethod); + availableMethods["admin_restart"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRestartMethod); + availableMethods["admin_load_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadHeightmapMethod); + availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod); // Agent management - availableMethods["admin_teleport_agent"] = XmlRpcTeleportAgentMethod; + availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod); // User management - availableMethods["admin_create_user"] = XmlRpcCreateUserMethod; - availableMethods["admin_create_user_email"] = XmlRpcCreateUserMethod; - availableMethods["admin_exists_user"] = XmlRpcUserExistsMethod; - availableMethods["admin_update_user"] = XmlRpcUpdateUserAccountMethod; + availableMethods["admin_create_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcCreateUserMethod); + availableMethods["admin_create_user_email"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcCreateUserMethod); + availableMethods["admin_exists_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcUserExistsMethod); + availableMethods["admin_update_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcUpdateUserAccountMethod); // Region state management - availableMethods["admin_load_xml"] = XmlRpcLoadXMLMethod; - availableMethods["admin_save_xml"] = XmlRpcSaveXMLMethod; - availableMethods["admin_load_oar"] = XmlRpcLoadOARMethod; - availableMethods["admin_save_oar"] = XmlRpcSaveOARMethod; + availableMethods["admin_load_xml"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadXMLMethod); + availableMethods["admin_save_xml"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveXMLMethod); + availableMethods["admin_load_oar"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadOARMethod); + availableMethods["admin_save_oar"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveOARMethod); // Estate access list management - availableMethods["admin_acl_clear"] = XmlRpcAccessListClear; - availableMethods["admin_acl_add"] = XmlRpcAccessListAdd; - availableMethods["admin_acl_remove"] = XmlRpcAccessListRemove; - availableMethods["admin_acl_list"] = XmlRpcAccessListList; + availableMethods["admin_acl_clear"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListClear); + availableMethods["admin_acl_add"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListAdd); + availableMethods["admin_acl_remove"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListRemove); + availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList); // Either enable full remote functionality or just selected features string enabledMethods = m_config.GetString("enabled_methods", "all"); @@ -164,7 +164,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController // If you just leave the option out! // if (!String.IsNullOrEmpty(enabledMethods)) - availableMethods["admin_console_command"] = XmlRpcConsoleCommandMethod; + availableMethods["admin_console_command"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcConsoleCommandMethod); // The assumption here is that simply enabling Remote Admin as before will produce the same // behavior - enable all methods unless the whitelist is in place for backward-compatibility. @@ -198,34 +198,67 @@ namespace OpenSim.ApplicationPlugins.RemoteController } } - private void FailIfRemoteAdminNotAllowed(string password, string check_ip_address) + /// + /// Invoke an XmlRpc method with the standard actions (password check, etc.) + /// + /// + private XmlRpcResponse InvokeXmlRpcMethod( + XmlRpcRequest request, IPEndPoint remoteClient, Action method) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + response.Value = responseData; + + try + { + Hashtable requestData = (Hashtable) request.Params[0]; + + m_log.Info("[RADMIN]: Request to restart Region."); + CheckStringParameters(requestData, responseData, new string[] {"password"}); + + FailIfRemoteAdminNotAllowed((string)requestData["password"], responseData, remoteClient.Address.ToString()); + + method(request, response, remoteClient); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[RADMIN]: Method {0} failed. Exception {1}{2}", request.MethodName, e.Message, e.StackTrace); + + responseData["success"] = false; + responseData["error"] = e.Message; + } + + return response; + } + + private void FailIfRemoteAdminNotAllowed(string password, Hashtable responseData, string check_ip_address) { if (m_accessIP.Count > 0 && !m_accessIP.Contains(check_ip_address)) { - m_log.WarnFormat("[RADMIN]: Unauthorized acess blocked from IP {0}", check_ip_address); + m_log.WarnFormat("[RADMIN]: Unauthorized access blocked from IP {0}", check_ip_address); + responseData["accepted"] = false; throw new Exception("not authorized"); } if (m_requiredPassword != String.Empty && password != m_requiredPassword) { m_log.WarnFormat("[RADMIN]: Wrong password, blocked access from IP {0}", check_ip_address); + responseData["accepted"] = false; throw new Exception("wrong password"); } } - public XmlRpcResponse XmlRpcRestartMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcRestartMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; try { - Hashtable requestData = (Hashtable) request.Params[0]; - m_log.Info("[RADMIN]: Request to restart Region."); - CheckStringParameters(request, new string[] {"password", "regionID"}); - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + CheckStringParameters(requestData, responseData, new string[] {"regionID"}); UUID regionID = new UUID((string) requestData["regionID"]); @@ -246,231 +279,151 @@ namespace OpenSim.ApplicationPlugins.RemoteController restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); responseData["success"] = true; } - - response.Value = responseData; } catch (Exception e) { - m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace); - responseData["accepted"] = false; - responseData["success"] = false; +// m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace); responseData["rebooting"] = false; - responseData["error"] = e.Message; - response.Value = responseData; + + throw e; } m_log.Info("[RADMIN]: Restart Region request complete"); - return response; } - public XmlRpcResponse XmlRpcAlertMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcAlertMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - m_log.Info("[RADMIN]: Alert request started"); - try - { - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] {"password", "message"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - string message = (string) requestData["message"]; - m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message); + string message = (string) requestData["message"]; + m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message); - responseData["accepted"] = true; - responseData["success"] = true; - response.Value = responseData; - - m_application.SceneManager.ForEachScene( - delegate(Scene scene) - { - IDialogModule dialogModule = scene.RequestModuleInterface(); - if (dialogModule != null) - dialogModule.SendGeneralAlert(message); - }); - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: Broadcasting: failed: {0}", e.Message, e.StackTrace); + responseData["accepted"] = true; + responseData["success"] = true; - responseData["accepted"] = false; - responseData["success"] = false; - responseData["error"] = e.Message; - response.Value = responseData; - } + m_application.SceneManager.ForEachScene( + delegate(Scene scene) + { + IDialogModule dialogModule = scene.RequestModuleInterface(); + if (dialogModule != null) + dialogModule.SendGeneralAlert(message); + }); m_log.Info("[RADMIN]: Alert request complete"); - return response; } - public XmlRpcResponse XmlRpcLoadHeightmapMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcLoadHeightmapMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - m_log.Info("[RADMIN]: Load height maps request started"); - try - { - Hashtable requestData = (Hashtable) request.Params[0]; - - m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}", request); - // foreach (string k in requestData.Keys) - // { - // m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}: >{1}< {2}", - // k, (string)requestData[k], ((string)requestData[k]).Length); - // } + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - CheckStringParameters(request, new string[] {"password", "filename", "regionid"}); +// m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}", request); + // foreach (string k in requestData.Keys) + // { + // m_log.DebugFormat("[RADMIN]: Load Terrain: XmlRpc {0}: >{1}< {2}", + // k, (string)requestData[k], ((string)requestData[k]).Length); + // } - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + CheckStringParameters(requestData, responseData, new string[] {"filename", "regionid"}); - string file = (string) requestData["filename"]; - UUID regionID = (UUID) (string) requestData["regionid"]; - m_log.InfoFormat("[RADMIN]: Terrain Loading: {0}", file); - - responseData["accepted"] = true; - - LoadHeightmap(file, regionID); + string file = (string) requestData["filename"]; + UUID regionID = (UUID) (string) requestData["regionid"]; + m_log.InfoFormat("[RADMIN]: Terrain Loading: {0}", file); - responseData["success"] = false; + responseData["accepted"] = true; - response.Value = responseData; - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: Terrain Loading: failed: {0} {1}", e.Message, e.StackTrace); + LoadHeightmap(file, regionID); - responseData["success"] = false; - responseData["error"] = e.Message; - } + responseData["success"] = false; m_log.Info("[RADMIN]: Load height maps request complete"); - - return response; } - public XmlRpcResponse XmlRpcSaveHeightmapMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcSaveHeightmapMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - m_log.Info("[RADMIN]: Save height maps request started"); - try - { - Hashtable requestData = (Hashtable)request.Params[0]; - - m_log.DebugFormat("[RADMIN]: Save Terrain: XmlRpc {0}", request.ToString()); - - CheckStringParameters(request, new string[] { "password", "filename", "regionid" }); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); +// m_log.DebugFormat("[RADMIN]: Save Terrain: XmlRpc {0}", request.ToString()); - string file = (string)requestData["filename"]; - UUID regionID = (UUID)(string)requestData["regionid"]; - m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file); + CheckStringParameters(requestData, responseData, new string[] { "filename", "regionid" }); - responseData["accepted"] = true; - - Scene region = null; + string file = (string)requestData["filename"]; + UUID regionID = (UUID)(string)requestData["regionid"]; + m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file); - if (!m_application.SceneManager.TryGetScene(regionID, out region)) - throw new Exception("1: unable to get a scene with that name"); + responseData["accepted"] = true; - ITerrainModule terrainModule = region.RequestModuleInterface(); - if (null == terrainModule) throw new Exception("terrain module not available"); - - terrainModule.SaveToFile(file); + Scene region = null; - responseData["success"] = false; + if (!m_application.SceneManager.TryGetScene(regionID, out region)) + throw new Exception("1: unable to get a scene with that name"); - response.Value = responseData; - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: Terrain Saving: failed: {0}", e.Message); - m_log.DebugFormat("[RADMIN]: Terrain Saving: failed: {0}", e.ToString()); + ITerrainModule terrainModule = region.RequestModuleInterface(); + if (null == terrainModule) throw new Exception("terrain module not available"); - responseData["success"] = false; - responseData["error"] = e.Message; + terrainModule.SaveToFile(file); - } + responseData["success"] = false; m_log.Info("[RADMIN]: Save height maps request complete"); - - return response; } - public XmlRpcResponse XmlRpcShutdownMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcShutdownMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: Received Shutdown Administrator Request"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - Hashtable requestData = (Hashtable) request.Params[0]; - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - responseData["accepted"] = true; - response.Value = responseData; - - int timeout = 2000; - string message; + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - if (requestData.ContainsKey("shutdown") - && ((string) requestData["shutdown"] == "delayed") - && requestData.ContainsKey("milliseconds")) - { - timeout = Int32.Parse(requestData["milliseconds"].ToString()); + responseData["accepted"] = true; + response.Value = responseData; - message - = "Region is going down in " + ((int) (timeout/1000)).ToString() - + " second(s). Please save what you are doing and log out."; - } - else - { - message = "Region is going down now."; - } + int timeout = 2000; + string message; - m_application.SceneManager.ForEachScene( - delegate(Scene scene) - { - IDialogModule dialogModule = scene.RequestModuleInterface(); - if (dialogModule != null) - dialogModule.SendGeneralAlert(message); - }); - - // Perform shutdown - System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing - shutdownTimer.AutoReset = false; - shutdownTimer.Elapsed += new ElapsedEventHandler(shutdownTimer_Elapsed); - lock (shutdownTimer) - { - shutdownTimer.Start(); - } + if (requestData.ContainsKey("shutdown") + && ((string) requestData["shutdown"] == "delayed") + && requestData.ContainsKey("milliseconds")) + { + timeout = Int32.Parse(requestData["milliseconds"].ToString()); - responseData["success"] = true; + message + = "Region is going down in " + ((int) (timeout/1000)).ToString() + + " second(s). Please save what you are doing and log out."; } - catch (Exception e) + else { - m_log.ErrorFormat("[RADMIN]: Shutdown: failed: {0} {1}", e.Message, e.StackTrace); + message = "Region is going down now."; + } - responseData["accepted"] = false; - responseData["error"] = e.Message; + m_application.SceneManager.ForEachScene( + delegate(Scene scene) + { + IDialogModule dialogModule = scene.RequestModuleInterface(); + if (dialogModule != null) + dialogModule.SendGeneralAlert(message); + }); - response.Value = responseData; + // Perform shutdown + System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing + shutdownTimer.AutoReset = false; + shutdownTimer.Elapsed += new ElapsedEventHandler(shutdownTimer_Elapsed); + lock (shutdownTimer) + { + shutdownTimer.Start(); } + + responseData["success"] = true; m_log.Info("[RADMIN]: Shutdown Administrator Request complete"); - return response; } private void shutdownTimer_Elapsed(object sender, ElapsedEventArgs e) @@ -541,12 +494,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// name of the newly created region /// /// - public XmlRpcResponse XmlRpcCreateRegionMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcCreateRegionMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: CreateRegion: new request"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; lock (m_requestLock) { @@ -554,255 +507,235 @@ namespace OpenSim.ApplicationPlugins.RemoteController bool m_enableVoiceForNewRegions = m_config.GetBoolean("create_region_enable_voice", false); bool m_publicAccess = m_config.GetBoolean("create_region_public", true); - try + CheckStringParameters(requestData, responseData, new string[] + { + "region_name", + "listen_ip", "external_address", + "estate_name" + }); + CheckIntegerParams(requestData, responseData, new string[] {"region_x", "region_y", "listen_port"}); + + // check whether we still have space left (iff we are using limits) + if (m_regionLimit != 0 && m_application.SceneManager.Scenes.Count >= m_regionLimit) + throw new Exception(String.Format("cannot instantiate new region, server capacity {0} already reached; delete regions first", + m_regionLimit)); + // extract or generate region ID now + Scene scene = null; + UUID regionID = UUID.Zero; + if (requestData.ContainsKey("region_id") && + !String.IsNullOrEmpty((string) requestData["region_id"])) { - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] - { - "password", - "region_name", - "listen_ip", "external_address", - "estate_name" - }); - CheckIntegerParams(request, new string[] {"region_x", "region_y", "listen_port"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - // check whether we still have space left (iff we are using limits) - if (m_regionLimit != 0 && m_application.SceneManager.Scenes.Count >= m_regionLimit) - throw new Exception(String.Format("cannot instantiate new region, server capacity {0} already reached; delete regions first", - m_regionLimit)); - // extract or generate region ID now - Scene scene = null; - UUID regionID = UUID.Zero; - if (requestData.ContainsKey("region_id") && - !String.IsNullOrEmpty((string) requestData["region_id"])) + regionID = (UUID) (string) requestData["region_id"]; + if (m_application.SceneManager.TryGetScene(regionID, out scene)) + throw new Exception( + String.Format("region UUID already in use by region {0}, UUID {1}, <{2},{3}>", + scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, + scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY)); + } + else + { + regionID = UUID.Random(); + m_log.DebugFormat("[RADMIN] CreateRegion: new region UUID {0}", regionID); + } + + // create volatile or persistent region info + RegionInfo region = new RegionInfo(); + + region.RegionID = regionID; + region.originRegionID = regionID; + region.RegionName = (string) requestData["region_name"]; + region.RegionLocX = Convert.ToUInt32(requestData["region_x"]); + region.RegionLocY = Convert.ToUInt32(requestData["region_y"]); + + // check for collisions: region name, region UUID, + // region location + if (m_application.SceneManager.TryGetScene(region.RegionName, out scene)) + throw new Exception( + String.Format("region name already in use by region {0}, UUID {1}, <{2},{3}>", + scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, + scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY)); + + if (m_application.SceneManager.TryGetScene(region.RegionLocX, region.RegionLocY, out scene)) + throw new Exception( + String.Format("region location <{0},{1}> already in use by region {2}, UUID {3}, <{4},{5}>", + region.RegionLocX, region.RegionLocY, + scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, + scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY)); + + region.InternalEndPoint = + new IPEndPoint(IPAddress.Parse((string) requestData["listen_ip"]), 0); + + region.InternalEndPoint.Port = Convert.ToInt32(requestData["listen_port"]); + if (0 == region.InternalEndPoint.Port) throw new Exception("listen_port is 0"); + if (m_application.SceneManager.TryGetScene(region.InternalEndPoint, out scene)) + throw new Exception( + String.Format( + "region internal IP {0} and port {1} already in use by region {2}, UUID {3}, <{4},{5}>", + region.InternalEndPoint.Address, + region.InternalEndPoint.Port, + scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, + scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY)); + + region.ExternalHostName = (string) requestData["external_address"]; + + bool persist = Convert.ToBoolean((string) requestData["persist"]); + if (persist) + { + // default place for region configuration files is in the + // Regions directory of the config dir (aka /bin) + string regionConfigPath = Path.Combine(Util.configDir(), "Regions"); + try { - regionID = (UUID) (string) requestData["region_id"]; - if (m_application.SceneManager.TryGetScene(regionID, out scene)) - throw new Exception( - String.Format("region UUID already in use by region {0}, UUID {1}, <{2},{3}>", - scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, - scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY)); + // OpenSim.ini can specify a different regions dir + IConfig startupConfig = (IConfig) m_configSource.Configs["Startup"]; + regionConfigPath = startupConfig.GetString("regionload_regionsdir", regionConfigPath).Trim(); } - else + catch (Exception) { - regionID = UUID.Random(); - m_log.DebugFormat("[RADMIN] CreateRegion: new region UUID {0}", regionID); + // No INI setting recorded. } - - // create volatile or persistent region info - RegionInfo region = new RegionInfo(); - - region.RegionID = regionID; - region.originRegionID = regionID; - region.RegionName = (string) requestData["region_name"]; - region.RegionLocX = Convert.ToUInt32(requestData["region_x"]); - region.RegionLocY = Convert.ToUInt32(requestData["region_y"]); - - // check for collisions: region name, region UUID, - // region location - if (m_application.SceneManager.TryGetScene(region.RegionName, out scene)) - throw new Exception( - String.Format("region name already in use by region {0}, UUID {1}, <{2},{3}>", - scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, - scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY)); - - if (m_application.SceneManager.TryGetScene(region.RegionLocX, region.RegionLocY, out scene)) - throw new Exception( - String.Format("region location <{0},{1}> already in use by region {2}, UUID {3}, <{4},{5}>", - region.RegionLocX, region.RegionLocY, - scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, - scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY)); - - region.InternalEndPoint = - new IPEndPoint(IPAddress.Parse((string) requestData["listen_ip"]), 0); - - region.InternalEndPoint.Port = Convert.ToInt32(requestData["listen_port"]); - if (0 == region.InternalEndPoint.Port) throw new Exception("listen_port is 0"); - if (m_application.SceneManager.TryGetScene(region.InternalEndPoint, out scene)) - throw new Exception( - String.Format( - "region internal IP {0} and port {1} already in use by region {2}, UUID {3}, <{4},{5}>", - region.InternalEndPoint.Address, - region.InternalEndPoint.Port, - scene.RegionInfo.RegionName, scene.RegionInfo.RegionID, - scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY)); - - region.ExternalHostName = (string) requestData["external_address"]; - - bool persist = Convert.ToBoolean((string) requestData["persist"]); - if (persist) + + string regionIniPath; + + if (requestData.Contains("region_file")) { - // default place for region configuration files is in the - // Regions directory of the config dir (aka /bin) - string regionConfigPath = Path.Combine(Util.configDir(), "Regions"); - try - { - // OpenSim.ini can specify a different regions dir - IConfig startupConfig = (IConfig) m_configSource.Configs["Startup"]; - regionConfigPath = startupConfig.GetString("regionload_regionsdir", regionConfigPath).Trim(); - } - catch (Exception) - { - // No INI setting recorded. - } - - string regionIniPath; - - if (requestData.Contains("region_file")) - { - // Make sure that the file to be created is in a subdirectory of the region storage directory. - string requestedFilePath = Path.Combine(regionConfigPath, (string) requestData["region_file"]); - string requestedDirectory = Path.GetDirectoryName(Path.GetFullPath(requestedFilePath)); - if (requestedDirectory.StartsWith(Path.GetFullPath(regionConfigPath))) - regionIniPath = requestedFilePath; - else - throw new Exception("Invalid location for region file."); - } + // Make sure that the file to be created is in a subdirectory of the region storage directory. + string requestedFilePath = Path.Combine(regionConfigPath, (string) requestData["region_file"]); + string requestedDirectory = Path.GetDirectoryName(Path.GetFullPath(requestedFilePath)); + if (requestedDirectory.StartsWith(Path.GetFullPath(regionConfigPath))) + regionIniPath = requestedFilePath; else - { - regionIniPath = Path.Combine(regionConfigPath, - String.Format( - m_config.GetString("region_file_template", - "{0}x{1}-{2}.ini"), - region.RegionLocX.ToString(), - region.RegionLocY.ToString(), - regionID.ToString(), - region.InternalEndPoint.Port.ToString(), - region.RegionName.Replace(" ", "_").Replace(":", "_"). - Replace("/", "_"))); - } - - m_log.DebugFormat("[RADMIN] CreateRegion: persisting region {0} to {1}", - region.RegionID, regionIniPath); - region.SaveRegionToFile("dynamic region", regionIniPath); + throw new Exception("Invalid location for region file."); } else { - region.Persistent = false; + regionIniPath = Path.Combine(regionConfigPath, + String.Format( + m_config.GetString("region_file_template", + "{0}x{1}-{2}.ini"), + region.RegionLocX.ToString(), + region.RegionLocY.ToString(), + regionID.ToString(), + region.InternalEndPoint.Port.ToString(), + region.RegionName.Replace(" ", "_").Replace(":", "_"). + Replace("/", "_"))); } - - // Set the estate - // Check for an existing estate - List estateIDs = m_application.EstateDataService.GetEstates((string) requestData["estate_name"]); - if (estateIDs.Count < 1) + m_log.DebugFormat("[RADMIN] CreateRegion: persisting region {0} to {1}", + region.RegionID, regionIniPath); + region.SaveRegionToFile("dynamic region", regionIniPath); + } + else + { + region.Persistent = false; + } + + // Set the estate + + // Check for an existing estate + List estateIDs = m_application.EstateDataService.GetEstates((string) requestData["estate_name"]); + if (estateIDs.Count < 1) + { + UUID userID = UUID.Zero; + if (requestData.ContainsKey("estate_owner_uuid")) { - UUID userID = UUID.Zero; - if (requestData.ContainsKey("estate_owner_uuid")) - { - // ok, client wants us to use an explicit UUID - // regardless of what the avatar name provided - userID = new UUID((string) requestData["estate_owner_uuid"]); - - // Check that the specified user exists - Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene; - IUserAccountService accountService = currentOrFirst.UserAccountService; - UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, userID); - - if (user == null) - throw new Exception("Specified user was not found."); - } - else if (requestData.ContainsKey("estate_owner_first") & requestData.ContainsKey("estate_owner_last")) - { - // We need to look up the UUID for the avatar with the provided name. - string ownerFirst = (string) requestData["estate_owner_first"]; - string ownerLast = (string) requestData["estate_owner_last"]; - - Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene; - IUserAccountService accountService = currentOrFirst.UserAccountService; - UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, - ownerFirst, ownerLast); - - // Check that the specified user exists - if (user == null) - throw new Exception("Specified user was not found."); - - userID = user.PrincipalID; - } - else - { - throw new Exception("Estate owner details not provided."); - } + // ok, client wants us to use an explicit UUID + // regardless of what the avatar name provided + userID = new UUID((string) requestData["estate_owner_uuid"]); - // Create a new estate with the name provided - region.EstateSettings = m_application.EstateDataService.CreateNewEstate(); - - region.EstateSettings.EstateName = (string) requestData["estate_name"]; - region.EstateSettings.EstateOwner = userID; - // Persistence does not seem to effect the need to save a new estate - region.EstateSettings.Save(); - - if (!m_application.EstateDataService.LinkRegion(region.RegionID, (int) region.EstateSettings.EstateID)) - throw new Exception("Failed to join estate."); + // Check that the specified user exists + Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene; + IUserAccountService accountService = currentOrFirst.UserAccountService; + UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, userID); + + if (user == null) + throw new Exception("Specified user was not found."); + } + else if (requestData.ContainsKey("estate_owner_first") & requestData.ContainsKey("estate_owner_last")) + { + // We need to look up the UUID for the avatar with the provided name. + string ownerFirst = (string) requestData["estate_owner_first"]; + string ownerLast = (string) requestData["estate_owner_last"]; + + Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene; + IUserAccountService accountService = currentOrFirst.UserAccountService; + UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, + ownerFirst, ownerLast); + + // Check that the specified user exists + if (user == null) + throw new Exception("Specified user was not found."); + + userID = user.PrincipalID; } else { - int estateID = estateIDs[0]; - - region.EstateSettings = m_application.EstateDataService.LoadEstateSettings(region.RegionID, false); - - if (region.EstateSettings.EstateID != estateID) - { - // The region is already part of an estate, but not the one we want. - region.EstateSettings = m_application.EstateDataService.LoadEstateSettings(estateID); - - if (!m_application.EstateDataService.LinkRegion(region.RegionID, estateID)) - throw new Exception("Failed to join estate."); - } + throw new Exception("Estate owner details not provided."); } - // Create the region and perform any initial initialization + // Create a new estate with the name provided + region.EstateSettings = m_application.EstateDataService.CreateNewEstate(); - IScene newScene; - m_application.CreateRegion(region, out newScene); + region.EstateSettings.EstateName = (string) requestData["estate_name"]; + region.EstateSettings.EstateOwner = userID; + // Persistence does not seem to effect the need to save a new estate + region.EstateSettings.Save(); + + if (!m_application.EstateDataService.LinkRegion(region.RegionID, (int) region.EstateSettings.EstateID)) + throw new Exception("Failed to join estate."); + } + else + { + int estateID = estateIDs[0]; - // If an access specification was provided, use it. - // Otherwise accept the default. - newScene.RegionInfo.EstateSettings.PublicAccess = GetBoolean(requestData, "public", m_publicAccess); - newScene.RegionInfo.EstateSettings.Save(); + region.EstateSettings = m_application.EstateDataService.LoadEstateSettings(region.RegionID, false); - // enable voice on newly created region if - // requested by either the XmlRpc request or the - // configuration - if (GetBoolean(requestData, "enable_voice", m_enableVoiceForNewRegions)) + if (region.EstateSettings.EstateID != estateID) { - List parcels = ((Scene)newScene).LandChannel.AllParcels(); + // The region is already part of an estate, but not the one we want. + region.EstateSettings = m_application.EstateDataService.LoadEstateSettings(estateID); - foreach (ILandObject parcel in parcels) - { - parcel.LandData.Flags |= (uint) ParcelFlags.AllowVoiceChat; - parcel.LandData.Flags |= (uint) ParcelFlags.UseEstateVoiceChan; - ((Scene)newScene).LandChannel.UpdateLandObject(parcel.LandData.LocalID, parcel.LandData); - } + if (!m_application.EstateDataService.LinkRegion(region.RegionID, estateID)) + throw new Exception("Failed to join estate."); } + } + + // Create the region and perform any initial initialization - //Load Heightmap if specified to new region - if (requestData.Contains("heightmap_file")) - { - LoadHeightmap((string)requestData["heightmap_file"], region.RegionID); - } + IScene newScene; + m_application.CreateRegion(region, out newScene); - responseData["success"] = true; - responseData["region_name"] = region.RegionName; - responseData["region_uuid"] = region.RegionID.ToString(); + // If an access specification was provided, use it. + // Otherwise accept the default. + newScene.RegionInfo.EstateSettings.PublicAccess = GetBoolean(requestData, "public", m_publicAccess); + newScene.RegionInfo.EstateSettings.Save(); - response.Value = responseData; - } - catch (Exception e) + // enable voice on newly created region if + // requested by either the XmlRpc request or the + // configuration + if (GetBoolean(requestData, "enable_voice", m_enableVoiceForNewRegions)) { - m_log.ErrorFormat("[RADMIN] CreateRegion: failed {0} {1}", e.Message, e.StackTrace); + List parcels = ((Scene)newScene).LandChannel.AllParcels(); - responseData["success"] = false; - responseData["error"] = e.Message; + foreach (ILandObject parcel in parcels) + { + parcel.LandData.Flags |= (uint) ParcelFlags.AllowVoiceChat; + parcel.LandData.Flags |= (uint) ParcelFlags.UseEstateVoiceChan; + ((Scene)newScene).LandChannel.UpdateLandObject(parcel.LandData.LocalID, parcel.LandData); + } + } - response.Value = responseData; + //Load Heightmap if specified to new region + if (requestData.Contains("heightmap_file")) + { + LoadHeightmap((string)requestData["heightmap_file"], region.RegionID); } + responseData["success"] = true; + responseData["region_name"] = region.RegionName; + responseData["region_uuid"] = region.RegionID.ToString(); + m_log.Info("[RADMIN]: CreateRegion: request complete"); - return response; } } @@ -832,46 +765,28 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// error message if success is false /// /// - public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcDeleteRegionMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: DeleteRegion: new request"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; lock (m_requestLock) { - try - { - Hashtable requestData = (Hashtable) request.Params[0]; - CheckStringParameters(request, new string[] {"password", "region_name"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - Scene scene = null; - string regionName = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(regionName, out scene)) - throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); - - m_application.RemoveRegion(scene, true); - - responseData["success"] = true; - responseData["region_name"] = regionName; + CheckStringParameters(requestData, responseData, new string[] {"region_name"}); - response.Value = responseData; - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN] DeleteRegion: failed {0} {1}", e.Message, e.StackTrace); + Scene scene = null; + string regionName = (string) requestData["region_name"]; + if (!m_application.SceneManager.TryGetScene(regionName, out scene)) + throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); - responseData["success"] = false; - responseData["error"] = e.Message; + m_application.RemoveRegion(scene, true); - response.Value = responseData; - } + responseData["success"] = true; + responseData["region_name"] = regionName; m_log.Info("[RADMIN]: DeleteRegion: request complete"); - return response; } } @@ -903,69 +818,52 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// error message if success is false /// /// - public XmlRpcResponse XmlRpcCloseRegionMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcCloseRegionMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: CloseRegion: new request"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; Scene scene = null; lock (m_requestLock) { - try + if (requestData.ContainsKey("region_id") && + !String.IsNullOrEmpty((string) requestData["region_id"])) { - Hashtable requestData = (Hashtable) request.Params[0]; - CheckStringParameters(request, new string[] {"password"}); + // Region specified by UUID + UUID regionID = (UUID) (string) requestData["region_id"]; + if (!m_application.SceneManager.TryGetScene(regionID, out scene)) + throw new Exception(String.Format("region \"{0}\" does not exist", regionID)); - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + m_application.CloseRegion(scene); - if (requestData.ContainsKey("region_id") && - !String.IsNullOrEmpty((string) requestData["region_id"])) - { - // Region specified by UUID - UUID regionID = (UUID) (string) requestData["region_id"]; - if (!m_application.SceneManager.TryGetScene(regionID, out scene)) - throw new Exception(String.Format("region \"{0}\" does not exist", regionID)); + responseData["success"] = true; + responseData["region_id"] = regionID; - m_application.CloseRegion(scene); + response.Value = responseData; + } + else if ( + requestData.ContainsKey("region_name") + && !String.IsNullOrEmpty((string) requestData["region_name"])) + { + // Region specified by name - responseData["success"] = true; - responseData["region_id"] = regionID; - - response.Value = responseData; - } - else if (requestData.ContainsKey("region_name") && - !String.IsNullOrEmpty((string) requestData["region_name"])) - { - // Region specified by name - - string regionName = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(regionName, out scene)) - throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); - - m_application.CloseRegion(scene); + string regionName = (string) requestData["region_name"]; + if (!m_application.SceneManager.TryGetScene(regionName, out scene)) + throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); - responseData["success"] = true; - responseData["region_name"] = regionName; + m_application.CloseRegion(scene); - response.Value = responseData; - } - else - throw new Exception("no region specified"); + responseData["success"] = true; + responseData["region_name"] = regionName; } - catch (Exception e) + else { - m_log.ErrorFormat("[RADMIN]: CloseRegion: failed {0} {1}", e.Message, e.StackTrace); - - responseData["success"] = false; - responseData["error"] = e.Message; - - response.Value = responseData; + throw new Exception("no region specified"); } m_log.Info("[RADMIN]: CloseRegion: request complete"); - return response; } } @@ -1001,70 +899,53 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// error message if success is false /// /// - public XmlRpcResponse XmlRpcModifyRegionMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcModifyRegionMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: ModifyRegion: new request"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; lock (m_requestLock) { - try - { - Hashtable requestData = (Hashtable) request.Params[0]; - CheckStringParameters(request, new string[] {"password", "region_name"}); + CheckStringParameters(requestData, responseData, new string[] {"region_name"}); - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + Scene scene = null; + string regionName = (string) requestData["region_name"]; + if (!m_application.SceneManager.TryGetScene(regionName, out scene)) + throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); - Scene scene = null; - string regionName = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(regionName, out scene)) - throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); + // Modify access + scene.RegionInfo.EstateSettings.PublicAccess = + GetBoolean(requestData,"public", scene.RegionInfo.EstateSettings.PublicAccess); + if (scene.RegionInfo.Persistent) + scene.RegionInfo.EstateSettings.Save(); - // Modify access - scene.RegionInfo.EstateSettings.PublicAccess = - GetBoolean(requestData,"public", scene.RegionInfo.EstateSettings.PublicAccess); - if (scene.RegionInfo.Persistent) - scene.RegionInfo.EstateSettings.Save(); + if (requestData.ContainsKey("enable_voice")) + { + bool enableVoice = GetBoolean(requestData, "enable_voice", true); + List parcels = ((Scene)scene).LandChannel.AllParcels(); - if (requestData.ContainsKey("enable_voice")) + foreach (ILandObject parcel in parcels) { - bool enableVoice = GetBoolean(requestData, "enable_voice", true); - List parcels = ((Scene)scene).LandChannel.AllParcels(); - - foreach (ILandObject parcel in parcels) + if (enableVoice) { - if (enableVoice) - { - parcel.LandData.Flags |= (uint)ParcelFlags.AllowVoiceChat; - parcel.LandData.Flags |= (uint)ParcelFlags.UseEstateVoiceChan; - } - else - { - parcel.LandData.Flags &= ~(uint)ParcelFlags.AllowVoiceChat; - parcel.LandData.Flags &= ~(uint)ParcelFlags.UseEstateVoiceChan; - } - scene.LandChannel.UpdateLandObject(parcel.LandData.LocalID, parcel.LandData); + parcel.LandData.Flags |= (uint)ParcelFlags.AllowVoiceChat; + parcel.LandData.Flags |= (uint)ParcelFlags.UseEstateVoiceChan; + } + else + { + parcel.LandData.Flags &= ~(uint)ParcelFlags.AllowVoiceChat; + parcel.LandData.Flags &= ~(uint)ParcelFlags.UseEstateVoiceChan; } + scene.LandChannel.UpdateLandObject(parcel.LandData.LocalID, parcel.LandData); } - - responseData["success"] = true; - responseData["region_name"] = regionName; - - response.Value = responseData; } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN] ModifyRegion: failed {0} {1}", e.Message, e.StackTrace); - - responseData["success"] = false; - responseData["error"] = e.Message; - response.Value = responseData; - } + responseData["success"] = true; + responseData["region_name"] = regionName; m_log.Info("[RADMIN]: ModifyRegion: request complete"); - return response; } } @@ -1106,28 +987,24 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// /// /// - public XmlRpcResponse XmlRpcCreateUserMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcCreateUserMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: CreateUser: new request"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; lock (m_requestLock) { try { - Hashtable requestData = (Hashtable) request.Params[0]; - // check completeness - CheckStringParameters(request, new string[] + CheckStringParameters(requestData, responseData, new string[] { - "password", "user_firstname", + "user_firstname", "user_lastname", "user_password", }); - CheckIntegerParams(request, new string[] {"start_region_x", "start_region_y"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + CheckIntegerParams(requestData, responseData, new string[] {"start_region_x", "start_region_y"}); // do the job string firstName = (string) requestData["user_firstname"]; @@ -1154,9 +1031,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController GridRegion home = scene.GridService.GetRegionByPosition(scopeID, (int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize)); - if (null == home) { + if (null == home) + { m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", firstName, lastName); - } else { + } + else + { scene.GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); m_log.DebugFormat("[RADMIN]: Set home region {0} for updated user account {1} {2}", home.RegionID, firstName, lastName); } @@ -1168,22 +1048,16 @@ namespace OpenSim.ApplicationPlugins.RemoteController responseData["success"] = true; responseData["avatar_uuid"] = account.PrincipalID.ToString(); - response.Value = responseData; - m_log.InfoFormat("[RADMIN]: CreateUser: User {0} {1} created, UUID {2}", firstName, lastName, account.PrincipalID); } catch (Exception e) { - m_log.ErrorFormat("[RADMIN]: CreateUser: failed: {0} {1}", e.Message, e.StackTrace); - - responseData["success"] = false; responseData["avatar_uuid"] = UUID.Zero.ToString(); - responseData["error"] = e.Message; - response.Value = responseData; + throw e; } + m_log.Info("[RADMIN]: CreateUser: request complete"); - return response; } } @@ -1219,62 +1093,43 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// error message if success is false /// /// - public XmlRpcResponse XmlRpcUserExistsMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcUserExistsMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: UserExists: new request"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - Hashtable requestData = (Hashtable) request.Params[0]; - - // check completeness - CheckStringParameters(request, new string[] {"password", "user_firstname", "user_lastname"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - string firstName = (string) requestData["user_firstname"]; - string lastName = (string) requestData["user_lastname"]; + // check completeness + CheckStringParameters(requestData, responseData, new string[] {"user_firstname", "user_lastname"}); - responseData["user_firstname"] = firstName; - responseData["user_lastname"] = lastName; - - UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; + string firstName = (string) requestData["user_firstname"]; + string lastName = (string) requestData["user_lastname"]; - UserAccount account = m_application.SceneManager.CurrentOrFirstScene.UserAccountService.GetUserAccount(scopeID, firstName, lastName); + responseData["user_firstname"] = firstName; + responseData["user_lastname"] = lastName; - if (null == account) - { - responseData["success"] = false; - responseData["lastlogin"] = 0; - } - else - { - GridUserInfo userInfo = m_application.SceneManager.CurrentOrFirstScene.GridUserService.GetGridUserInfo(account.PrincipalID.ToString()); - if (userInfo != null) - responseData["lastlogin"] = userInfo.Login; - else - responseData["lastlogin"] = 0; + UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; - responseData["success"] = true; - } + UserAccount account = m_application.SceneManager.CurrentOrFirstScene.UserAccountService.GetUserAccount(scopeID, firstName, lastName); - response.Value = responseData; - } - catch (Exception e) + if (null == account) { - m_log.ErrorFormat("[RADMIN]: UserExists: failed: {0} {1}", e.Message, e.StackTrace); - responseData["success"] = false; - responseData["error"] = e.Message; + responseData["lastlogin"] = 0; + } + else + { + GridUserInfo userInfo = m_application.SceneManager.CurrentOrFirstScene.GridUserService.GetGridUserInfo(account.PrincipalID.ToString()); + if (userInfo != null) + responseData["lastlogin"] = userInfo.Login; + else + responseData["lastlogin"] = 0; - response.Value = responseData; + responseData["success"] = true; } m_log.Info("[RADMIN]: UserExists: request complete"); - return response; } /// @@ -1319,27 +1174,23 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// /// /// - public XmlRpcResponse XmlRpcUpdateUserAccountMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private void XmlRpcUpdateUserAccountMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: UpdateUserAccount: new request"); m_log.Warn("[RADMIN]: This method needs update for 0.7"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; lock (m_requestLock) { try { - Hashtable requestData = (Hashtable) request.Params[0]; - // check completeness - CheckStringParameters(request, new string[] { - "password", "user_firstname", + CheckStringParameters(requestData, responseData, new string[] { + "user_firstname", "user_lastname"}); - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - // do the job string firstName = (string) requestData["user_firstname"]; string lastName = (string) requestData["user_lastname"]; @@ -1425,1870 +1276,1678 @@ namespace OpenSim.ApplicationPlugins.RemoteController responseData["success"] = true; responseData["avatar_uuid"] = account.PrincipalID.ToString(); - response.Value = responseData; - m_log.InfoFormat("[RADMIN]: UpdateUserAccount: account for user {0} {1} updated, UUID {2}", firstName, lastName, account.PrincipalID); } catch (Exception e) { - m_log.ErrorFormat("[RADMIN] UpdateUserAccount: failed: {0} {1}", e.Message, e.StackTrace); - - responseData["success"] = false; responseData["avatar_uuid"] = UUID.Zero.ToString(); - responseData["error"] = e.Message; - response.Value = responseData; + throw e; } m_log.Info("[RADMIN]: UpdateUserAccount: request complete"); - return response; } } /// - /// This method is called by the user-create and user-modify methods to establish - /// or change, the user's appearance. Default avatar names can be specified via - /// the config file, but must correspond to avatars in the default appearance - /// file, or pre-existing in the user database. - /// This should probably get moved into somewhere more core eventually. - /// - private void UpdateUserAppearance(Hashtable responseData, Hashtable requestData, UUID userid) + /// Load an OAR file into a region.. + /// + /// incoming XML RPC request + /// + /// XmlRpcLoadOARMethod takes the following XMLRPC + /// parameters + /// + /// parameter namedescription + /// password + /// admin password as set in OpenSim.ini + /// filename + /// file name of the OAR file + /// region_uuid + /// UUID of the region + /// region_name + /// region name + /// merge + /// true if oar should be merged + /// skip-assets + /// true if assets should be skiped + /// + /// + /// region_uuid takes precedence over + /// region_name if both are present; one of both + /// must be present. + /// + /// XmlRpcLoadOARMethod returns + /// + /// namedescription + /// success + /// true or false + /// error + /// error message if success is false + /// + /// + private void XmlRpcLoadOARMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - m_log.DebugFormat("[RADMIN]: updateUserAppearance"); - - string defaultMale = m_config.GetString("default_male", "Default Male"); - string defaultFemale = m_config.GetString("default_female", "Default Female"); - string defaultNeutral = m_config.GetString("default_female", "Default Default"); - string model = String.Empty; + m_log.Info("[RADMIN]: Received Load OAR Administrator Request"); - // Has a gender preference been supplied? + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - if (requestData.Contains("gender")) + lock (m_requestLock) { - switch ((string)requestData["gender"]) + try { - case "m" : - case "male" : - model = defaultMale; - break; - case "f" : - case "female" : - model = defaultFemale; - break; - case "n" : - case "neutral" : - default : - model = defaultNeutral; - break; - } - } - - // Has an explicit model been specified? - - if (requestData.Contains("model") && (String.IsNullOrEmpty((string)requestData["gender"]))) - { - model = (string)requestData["model"]; - } + CheckStringParameters(requestData, responseData, new string[] {"filename"}); - // No appearance attributes were set + string filename = (string) requestData["filename"]; + Scene scene = null; + if (requestData.Contains("region_uuid")) + { + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_application.SceneManager.TryGetScene(region_uuid, out scene)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_application.SceneManager.TryGetScene(region_name, out scene)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + } + else throw new Exception("neither region_name nor region_uuid given"); + + bool mergeOar = false; + bool skipAssets = false; - if (String.IsNullOrEmpty(model)) - { - m_log.DebugFormat("[RADMIN]: Appearance update not requested"); - return; - } + if ((string)requestData["merge"] == "true") + { + mergeOar = true; + } + if ((string)requestData["skip-assets"] == "true") + { + skipAssets = true; + } - m_log.DebugFormat("[RADMIN]: Setting appearance for avatar {0}, using model <{1}>", userid, model); + IRegionArchiverModule archiver = scene.RequestModuleInterface(); + if (archiver != null) + archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty); + else + throw new Exception("Archiver module not present for scene"); - string[] modelSpecifiers = model.Split(); - if (modelSpecifiers.Length != 2) - { - m_log.WarnFormat("[RADMIN]: User appearance not set for {0}. Invalid model name : <{1}>", userid, model); - // modelSpecifiers = dmodel.Split(); - return; - } + responseData["loaded"] = true; + } + catch (Exception e) + { + responseData["loaded"] = false; - Scene scene = m_application.SceneManager.CurrentOrFirstScene; - UUID scopeID = scene.RegionInfo.ScopeID; - UserAccount modelProfile = scene.UserAccountService.GetUserAccount(scopeID, modelSpecifiers[0], modelSpecifiers[1]); + throw e; + } - if (modelProfile == null) - { - m_log.WarnFormat("[RADMIN]: Requested model ({0}) not found. Appearance unchanged", model); - return; + m_log.Info("[RADMIN]: Load OAR Administrator Request complete"); } - - // Set current user's appearance. This bit is easy. The appearance structure is populated with - // actual asset ids, however to complete the magic we need to populate the inventory with the - // assets in question. - - EstablishAppearance(userid, modelProfile.PrincipalID); - - m_log.DebugFormat("[RADMIN]: Finished setting appearance for avatar {0}, using model {1}", - userid, model); } /// - /// This method is called by updateAvatarAppearance once any specified model has been - /// ratified, or an appropriate default value has been adopted. The intended prototype - /// is known to exist, as is the target avatar. - /// - private void EstablishAppearance(UUID destination, UUID source) - { - m_log.DebugFormat("[RADMIN]: Initializing inventory for {0} from {1}", destination, source); - Scene scene = m_application.SceneManager.CurrentOrFirstScene; - - // If the model has no associated appearance we're done. - AvatarAppearance avatarAppearance = scene.AvatarService.GetAppearance(source); - if (avatarAppearance == null) - return; + /// Save a region to an OAR file + /// + /// incoming XML RPC request + /// + /// XmlRpcSaveOARMethod takes the following XMLRPC + /// parameters + /// + /// parameter namedescription + /// password + /// admin password as set in OpenSim.ini + /// filename + /// file name for the OAR file + /// region_uuid + /// UUID of the region + /// region_name + /// region name + /// profile + /// profile url + /// noassets + /// true if no assets should be saved + /// perm + /// C and/or T + /// + /// + /// region_uuid takes precedence over + /// region_name if both are present; one of both + /// must be present. + /// + /// XmlRpcLoadOARMethod returns + /// + /// namedescription + /// success + /// true or false + /// error + /// error message if success is false + /// + /// + private void XmlRpcSaveOARMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Save OAR Administrator Request"); - // Simple appearance copy or copy Clothing and Bodyparts folders? - bool copyFolders = m_config.GetBoolean("copy_folders", false); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - if (!copyFolders) + try { - // Simple copy of wearables and appearance update - try + CheckStringParameters(requestData, responseData, new string[] {"filename"}); + + string filename = (string)requestData["filename"]; + Scene scene = null; + if (requestData.Contains("region_uuid")) { - CopyWearablesAndAttachments(destination, source, avatarAppearance); + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_application.SceneManager.TryGetScene(region_uuid, out scene)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_application.SceneManager.TryGetScene(region_name, out scene)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + } + else throw new Exception("neither region_name nor region_uuid given"); - scene.AvatarService.SetAppearance(destination, avatarAppearance); + Dictionary options = new Dictionary(); + + //if (requestData.Contains("version")) + //{ + // options["version"] = (string)requestData["version"]; + //} + + if (requestData.Contains("profile")) + { + options["profile"] = (string)requestData["profile"]; } - catch (Exception e) + + if (requestData["noassets"] == "true") { - m_log.WarnFormat("[RADMIN]: Error transferring appearance for {0} : {1}", - destination, e.Message); + options["noassets"] = (string)requestData["noassets"] ; } - return; - } + if (requestData.Contains("perm")) + { + options["checkPermissions"] = (string)requestData["perm"]; + } - // Copy Clothing and Bodypart folders and appearance update - try - { - Dictionary inventoryMap = new Dictionary(); - CopyInventoryFolders(destination, source, AssetType.Clothing, inventoryMap, avatarAppearance); - CopyInventoryFolders(destination, source, AssetType.Bodypart, inventoryMap, avatarAppearance); + IRegionArchiverModule archiver = scene.RequestModuleInterface(); - AvatarWearable[] wearables = avatarAppearance.Wearables; + if (archiver != null) + { + scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted; + archiver.ArchiveRegion(filename, options); - for (int i=0; i - /// This method is called by establishAppearance to do a copy all inventory items - /// worn or attached to the Clothing inventory folder of the receiving avatar. - /// In parallel the avatar wearables and attachments are updated. - /// - private void CopyWearablesAndAttachments(UUID destination, UUID source, AvatarAppearance avatarAppearance) + private void RemoteAdminOarSaveCompleted(Guid uuid, string name) { - IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; - - // Get Clothing folder of receiver - InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, AssetType.Clothing); - - if (destinationFolder == null) - throw new Exception("Cannot locate folder(s)"); + m_log.DebugFormat("[RADMIN]: File processing complete for {0}", name); + lock (m_saveOarLock) + Monitor.Pulse(m_saveOarLock); + } - // Missing destination folder? This should *never* be the case - if (destinationFolder.Type != (short)AssetType.Clothing) - { - destinationFolder = new InventoryFolderBase(); - - destinationFolder.ID = UUID.Random(); - destinationFolder.Name = "Clothing"; - destinationFolder.Owner = destination; - destinationFolder.Type = (short)AssetType.Clothing; - destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID; - destinationFolder.Version = 1; - inventoryService.AddFolder(destinationFolder); // store base record - m_log.ErrorFormat("[RADMIN]: Created folder for destination {0}", source); - } + private void XmlRpcLoadXMLMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Load XML Administrator Request"); - // Wearables - AvatarWearable[] wearables = avatarAppearance.Wearables; - AvatarWearable wearable; + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - for (int i = 0; i attachments = avatarAppearance.GetAttachments(); + private void XmlRpcSaveXMLMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Save XML Administrator Request"); - foreach (AvatarAttachment attachment in attachments) + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; + + try { - int attachpoint = attachment.AttachPoint; - UUID itemID = attachment.ItemID; + CheckStringParameters(requestData, responseData, new string[] {"filename"}); - if (itemID != UUID.Zero) + string filename = (string) requestData["filename"]; + if (requestData.Contains("region_uuid")) { - // Get inventory item and copy it - InventoryItemBase item = new InventoryItemBase(itemID, source); - item = inventoryService.GetItem(item); - - if (item != null) - { - InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); - destinationItem.Name = item.Name; - destinationItem.Owner = destination; - destinationItem.Description = item.Description; - destinationItem.InvType = item.InvType; - destinationItem.CreatorId = item.CreatorId; - destinationItem.CreatorIdAsUuid = item.CreatorIdAsUuid; - destinationItem.CreatorData = item.CreatorData; - destinationItem.NextPermissions = item.NextPermissions; - destinationItem.CurrentPermissions = item.CurrentPermissions; - destinationItem.BasePermissions = item.BasePermissions; - destinationItem.EveryOnePermissions = item.EveryOnePermissions; - destinationItem.GroupPermissions = item.GroupPermissions; - destinationItem.AssetType = item.AssetType; - destinationItem.AssetID = item.AssetID; - destinationItem.GroupID = item.GroupID; - destinationItem.GroupOwned = item.GroupOwned; - destinationItem.SalePrice = item.SalePrice; - destinationItem.SaleType = item.SaleType; - destinationItem.Flags = item.Flags; - destinationItem.CreationDate = item.CreationDate; - destinationItem.Folder = destinationFolder.ID; - ApplyNextOwnerPermissions(destinationItem); + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + } + else throw new Exception("neither region_name nor region_uuid given"); - m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); - m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); + responseData["switched"] = true; - // Attach item - avatarAppearance.SetAttachment(attachpoint, destinationItem.ID, destinationItem.AssetID); - m_log.DebugFormat("[RADMIN]: Attached {0}", destinationItem.ID); - } - else - { - m_log.WarnFormat("[RADMIN]: Error transferring {0} to folder {1}", itemID, destinationFolder.ID); - } + string xml_version = "1"; + if (requestData.Contains("xml_version")) + { + xml_version = (string) requestData["xml_version"]; + } + + switch (xml_version) + { + case "1": + m_application.SceneManager.SaveCurrentSceneToXml(filename); + break; + + case "2": + m_application.SceneManager.SaveCurrentSceneToXml2(filename); + break; + + default: + throw new Exception(String.Format("unknown Xml{0} format", xml_version)); } + + responseData["saved"] = true; + } + catch (Exception e) + { + responseData["saved"] = false; + responseData["switched"] = false; + + throw e; } + + m_log.Info("[RADMIN]: Save XML Administrator Request complete"); } - /// - /// This method is called by establishAppearance to copy inventory folders to make - /// copies of Clothing and Bodyparts inventory folders and attaches worn attachments - /// - private void CopyInventoryFolders(UUID destination, UUID source, AssetType assetType, Dictionary inventoryMap, - AvatarAppearance avatarAppearance) + private void XmlRpcRegionQueryMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; + m_log.Info("[RADMIN]: Received Query XML Administrator Request"); - InventoryFolderBase sourceFolder = inventoryService.GetFolderForType(source, assetType); - InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, assetType); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - if (sourceFolder == null || destinationFolder == null) - throw new Exception("Cannot locate folder(s)"); + responseData["success"] = true; - // Missing source folder? This should *never* be the case - if (sourceFolder.Type != (short)assetType) + if (requestData.Contains("region_uuid")) { - sourceFolder = new InventoryFolderBase(); - sourceFolder.ID = UUID.Random(); - if (assetType == AssetType.Clothing) { - sourceFolder.Name = "Clothing"; - } else { - sourceFolder.Name = "Body Parts"; - } - sourceFolder.Owner = source; - sourceFolder.Type = (short)assetType; - sourceFolder.ParentID = inventoryService.GetRootFolder(source).ID; - sourceFolder.Version = 1; - inventoryService.AddFolder(sourceFolder); // store base record - m_log.ErrorFormat("[RADMIN] Created folder for source {0}", source); + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); - // Missing destination folder? This should *never* be the case - if (destinationFolder.Type != (short)assetType) + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + } + else { - destinationFolder = new InventoryFolderBase(); - destinationFolder.ID = UUID.Random(); - if (assetType == AssetType.Clothing) - { - destinationFolder.Name = "Clothing"; - } - else - { - destinationFolder.Name = "Body Parts"; - } - destinationFolder.Owner = destination; - destinationFolder.Type = (short)assetType; - destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID; - destinationFolder.Version = 1; - inventoryService.AddFolder(destinationFolder); // store base record - m_log.ErrorFormat("[RADMIN]: Created folder for destination {0}", source); + throw new Exception("neither region_name nor region_uuid given"); } - InventoryFolderBase extraFolder; - List folders = inventoryService.GetFolderContent(source, sourceFolder.ID).Folders; + Scene scene = m_application.SceneManager.CurrentScene; + int health = scene.GetHealth(); + responseData["health"] = health; - foreach (InventoryFolderBase folder in folders) - { - extraFolder = new InventoryFolderBase(); - extraFolder.ID = UUID.Random(); - extraFolder.Name = folder.Name; - extraFolder.Owner = destination; - extraFolder.Type = folder.Type; - extraFolder.Version = folder.Version; - extraFolder.ParentID = destinationFolder.ID; - inventoryService.AddFolder(extraFolder); + m_log.Info("[RADMIN]: Query XML Administrator Request complete"); + } - m_log.DebugFormat("[RADMIN]: Added folder {0} to folder {1}", extraFolder.ID, sourceFolder.ID); + private void XmlRpcConsoleCommandMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Command XML Administrator Request"); - List items = inventoryService.GetFolderContent(source, folder.ID).Items; + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - foreach (InventoryItemBase item in items) - { - InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); - destinationItem.Name = item.Name; - destinationItem.Owner = destination; - destinationItem.Description = item.Description; - destinationItem.InvType = item.InvType; - destinationItem.CreatorId = item.CreatorId; - destinationItem.CreatorIdAsUuid = item.CreatorIdAsUuid; - destinationItem.CreatorData = item.CreatorData; - destinationItem.NextPermissions = item.NextPermissions; - destinationItem.CurrentPermissions = item.CurrentPermissions; - destinationItem.BasePermissions = item.BasePermissions; - destinationItem.EveryOnePermissions = item.EveryOnePermissions; - destinationItem.GroupPermissions = item.GroupPermissions; - destinationItem.AssetType = item.AssetType; - destinationItem.AssetID = item.AssetID; - destinationItem.GroupID = item.GroupID; - destinationItem.GroupOwned = item.GroupOwned; - destinationItem.SalePrice = item.SalePrice; - destinationItem.SaleType = item.SaleType; - destinationItem.Flags = item.Flags; - destinationItem.CreationDate = item.CreationDate; - destinationItem.Folder = extraFolder.ID; - ApplyNextOwnerPermissions(destinationItem); + CheckStringParameters(requestData, responseData, new string[] {"command"}); - m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); - inventoryMap.Add(item.ID, destinationItem.ID); - m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", destinationItem.ID, extraFolder.ID); + MainConsole.Instance.RunCommand(requestData["command"].ToString()); - // Attach item, if original is attached - int attachpoint = avatarAppearance.GetAttachpoint(item.ID); - if (attachpoint != 0) - { - avatarAppearance.SetAttachment(attachpoint, destinationItem.ID, destinationItem.AssetID); - m_log.DebugFormat("[RADMIN]: Attached {0}", destinationItem.ID); - } - } - } + m_log.Info("[RADMIN]: Command XML Administrator Request complete"); } - /// - /// Apply next owner permissions. - /// - private void ApplyNextOwnerPermissions(InventoryItemBase item) + private void XmlRpcAccessListClear(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) + m_log.Info("[RADMIN]: Received Access List Clear Request"); + + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; + + responseData["success"] = true; + + if (requestData.Contains("region_uuid")) { - if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Modify; + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } - item.CurrentPermissions &= item.NextPermissions; - item.BasePermissions &= item.NextPermissions; - item.EveryOnePermissions &= item.NextPermissions; - // item.OwnerChanged = true; - // item.PermsMask = 0; - // item.PermsGranter = UUID.Zero; - } - - /// - /// This method is called if a given model avatar name can not be found. If the external - /// file has already been loaded once, then control returns immediately. If not, then it - /// looks for a default appearance file. This file contains XML definitions of zero or more named - /// avatars, each avatar can specify zero or more "outfits". Each outfit is a collection - /// of items that together, define a particular ensemble for the avatar. Each avatar should - /// indicate which outfit is the default, and this outfit will be automatically worn. The - /// other outfits are provided to allow "real" avatars a way to easily change their outfits. - /// - private bool CreateDefaultAvatars() - { - // Only load once - if (m_defaultAvatarsLoaded) + else if (requestData.Contains("region_name")) { - return false; + string region_name = (string) requestData["region_name"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } + else throw new Exception("neither region_name nor region_uuid given"); - m_log.DebugFormat("[RADMIN]: Creating default avatar entries"); + Scene scene = m_application.SceneManager.CurrentScene; + scene.RegionInfo.EstateSettings.EstateAccess = new UUID[]{}; - m_defaultAvatarsLoaded = true; + if (scene.RegionInfo.Persistent) + scene.RegionInfo.EstateSettings.Save(); - // Load processing starts here... + m_log.Info("[RADMIN]: Access List Clear Request complete"); + } - try + private void XmlRpcAccessListAdd(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Access List Add Request"); + + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; + + if (requestData.Contains("region_uuid")) { - string defaultAppearanceFileName = null; + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + } + else + { + throw new Exception("neither region_name nor region_uuid given"); + } - //m_config may be null if RemoteAdmin configuration secition is missing or disabled in OpenSim.ini - if (m_config != null) + int addedUsers = 0; + + if (requestData.Contains("users")) + { + UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; + IUserAccountService userService = m_application.SceneManager.CurrentOrFirstScene.UserAccountService; + Scene scene = m_application.SceneManager.CurrentScene; + Hashtable users = (Hashtable) requestData["users"]; + List uuids = new List(); + foreach (string name in users.Values) { - defaultAppearanceFileName = m_config.GetString("default_appearance", "default_appearance.xml"); + string[] parts = name.Split(); + UserAccount account = userService.GetUserAccount(scopeID, parts[0], parts[1]); + if (account != null) + { + uuids.Add(account.PrincipalID); + m_log.DebugFormat("[RADMIN]: adding \"{0}\" to ACL for \"{1}\"", name, scene.RegionInfo.RegionName); + } } - - if (File.Exists(defaultAppearanceFileName)) + List accessControlList = new List(scene.RegionInfo.EstateSettings.EstateAccess); + foreach (UUID uuid in uuids) { - XmlDocument doc = new XmlDocument(); - string name = "*unknown*"; - string email = "anon@anon"; - uint regionXLocation = 1000; - uint regionYLocation = 1000; - string password = UUID.Random().ToString(); // No requirement to sign-in. - UUID ID = UUID.Zero; - AvatarAppearance avatarAppearance; - XmlNodeList avatars; - XmlNodeList assets; - XmlNode perms = null; - bool include = false; - bool select = false; - - Scene scene = m_application.SceneManager.CurrentOrFirstScene; - IInventoryService inventoryService = scene.InventoryService; - IAssetService assetService = scene.AssetService; - - doc.LoadXml(File.ReadAllText(defaultAppearanceFileName)); - - // Load up any included assets. Duplicates will be ignored - assets = doc.GetElementsByTagName("RequiredAsset"); - foreach (XmlNode assetNode in assets) + if (!accessControlList.Contains(uuid)) { - AssetBase asset = new AssetBase(UUID.Random(), GetStringAttribute(assetNode, "name", ""), SByte.Parse(GetStringAttribute(assetNode, "type", "")), UUID.Zero.ToString()); - asset.Description = GetStringAttribute(assetNode,"desc",""); - asset.Local = Boolean.Parse(GetStringAttribute(assetNode,"local","")); - asset.Temporary = Boolean.Parse(GetStringAttribute(assetNode,"temporary","")); - asset.Data = Convert.FromBase64String(assetNode.InnerText); - assetService.Store(asset); + accessControlList.Add(uuid); + addedUsers++; } + } + scene.RegionInfo.EstateSettings.EstateAccess = accessControlList.ToArray(); + if (scene.RegionInfo.Persistent) + scene.RegionInfo.EstateSettings.Save(); + } - avatars = doc.GetElementsByTagName("Avatar"); - - // The document may contain multiple avatars - - foreach (XmlElement avatar in avatars) - { - m_log.DebugFormat("[RADMIN]: Loading appearance for {0}, gender = {1}", - GetStringAttribute(avatar,"name","?"), GetStringAttribute(avatar,"gender","?")); - - // Create the user identified by the avatar entry + responseData["added"] = addedUsers; - try - { - // Only the name value is mandatory - name = GetStringAttribute(avatar,"name",name); - email = GetStringAttribute(avatar,"email",email); - regionXLocation = GetUnsignedAttribute(avatar,"regx",regionXLocation); - regionYLocation = GetUnsignedAttribute(avatar,"regy",regionYLocation); - password = GetStringAttribute(avatar,"password",password); + m_log.Info("[RADMIN]: Access List Add Request complete"); + } - string[] names = name.Split(); - UUID scopeID = scene.RegionInfo.ScopeID; - UserAccount account = scene.UserAccountService.GetUserAccount(scopeID, names[0], names[1]); - if (null == account) - { - account = CreateUser(scopeID, names[0], names[1], password, email); - if (null == account) - { - m_log.ErrorFormat("[RADMIN]: Avatar {0} {1} was not created", names[0], names[1]); - return false; - } - } + private void XmlRpcAccessListRemove(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Access List Remove Request"); - // Set home position + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - GridRegion home = scene.GridService.GetRegionByPosition(scopeID, - (int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize)); - if (null == home) { - m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", names[0], names[1]); - } else { - scene.GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); - m_log.DebugFormat("[RADMIN]: Set home region {0} for updated user account {1} {2}", home.RegionID, names[0], names[1]); - } + responseData["success"] = true; - ID = account.PrincipalID; + if (requestData.Contains("region_uuid")) + { + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_application.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + } + else throw new Exception("neither region_name nor region_uuid given"); - m_log.DebugFormat("[RADMIN]: User {0}[{1}] created or retrieved", name, ID); - include = true; - } - catch (Exception e) - { - m_log.DebugFormat("[RADMIN]: Error creating user {0} : {1}", name, e.Message); - include = false; - } + int removedUsers = 0; - // OK, User has been created OK, now we can install the inventory. - // First retrieve the current inventory (the user may already exist) - // Note that althought he inventory is retrieved, the hierarchy has - // not been interpreted at all. + if (requestData.Contains("users")) + { + UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; + IUserAccountService userService = m_application.SceneManager.CurrentOrFirstScene.UserAccountService; + //UserProfileCacheService ups = m_application.CommunicationsManager.UserProfileCacheService; + Scene scene = m_application.SceneManager.CurrentScene; + Hashtable users = (Hashtable) requestData["users"]; + List uuids = new List(); + foreach (string name in users.Values) + { + string[] parts = name.Split(); + UserAccount account = userService.GetUserAccount(scopeID, parts[0], parts[1]); + if (account != null) + { + uuids.Add(account.PrincipalID); + } + } + List accessControlList = new List(scene.RegionInfo.EstateSettings.EstateAccess); + foreach (UUID uuid in uuids) + { + if (accessControlList.Contains(uuid)) + { + accessControlList.Remove(uuid); + removedUsers++; + } + } + scene.RegionInfo.EstateSettings.EstateAccess = accessControlList.ToArray(); + if (scene.RegionInfo.Persistent) + scene.RegionInfo.EstateSettings.Save(); + } - if (include) - { - // Setup for appearance processing - avatarAppearance = scene.AvatarService.GetAppearance(ID); - if (avatarAppearance == null) - avatarAppearance = new AvatarAppearance(); + responseData["removed"] = removedUsers; - AvatarWearable[] wearables = avatarAppearance.Wearables; - for (int i=0; i folders = inventoryService.GetFolderContent(ID, clothingFolder.ID).Folders; - extraFolder = null; + private void XmlRpcTeleportAgentMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - foreach (InventoryFolderBase folder in folders) - { - if (folder.Name == outfitName) - { - extraFolder = folder; - break; - } - } + UUID agentId; + string regionName = null; + Vector3 pos, lookAt; + ScenePresence sp = null; - // Otherwise, we must create the folder. - if (extraFolder == null) - { - m_log.DebugFormat("[RADMIN]: Creating outfit folder {0} for {1}", outfitName, name); - extraFolder = new InventoryFolderBase(); - extraFolder.ID = UUID.Random(); - extraFolder.Name = outfitName; - extraFolder.Owner = ID; - extraFolder.Type = (short)AssetType.Clothing; - extraFolder.Version = 1; - extraFolder.ParentID = clothingFolder.ID; - inventoryService.AddFolder(extraFolder); - m_log.DebugFormat("[RADMIN]: Adding outfile folder {0} to folder {1}", extraFolder.ID, clothingFolder.ID); - } + if (requestData.Contains("agent_first_name") && requestData.Contains("agent_last_name")) + { + string firstName = requestData["agent_first_name"].ToString(); + string lastName = requestData["agent_last_name"].ToString(); + m_application.SceneManager.TryGetRootScenePresenceByName(firstName, lastName, out sp); - // Now get the pieces that make up the outfit - XmlNodeList items = outfit.GetElementsByTagName("Item"); + if (sp == null) + throw new Exception( + string.Format( + "No agent found with agent_first_name {0} and agent_last_name {1}", firstName, lastName)); + } + else if (requestData.Contains("agent_id")) + { + string rawAgentId = (string)requestData["agent_id"]; - foreach (XmlElement item in items) - { - assetid = UUID.Zero; - XmlNodeList children = item.ChildNodes; - foreach (XmlNode child in children) - { - switch (child.Name) - { - case "Permissions" : - m_log.DebugFormat("[RADMIN]: Permissions specified"); - perms = child; - break; - case "Asset" : - assetid = new UUID(child.InnerText); - break; - } - } + if (!UUID.TryParse(rawAgentId, out agentId)) + throw new Exception(string.Format("agent_id {0} does not have the correct id format", rawAgentId)); - InventoryItemBase inventoryItem = null; + m_application.SceneManager.TryGetRootScenePresence(agentId, out sp); - // Check if asset is in inventory already - inventoryItem = null; - List inventoryItems = inventoryService.GetFolderContent(ID, extraFolder.ID).Items; + if (sp == null) + throw new Exception(string.Format("No agent with agent_id {0} found in this simulator", agentId)); + } + else + { + throw new Exception("No agent_id or agent_first_name and agent_last_name parameters specified"); + } - foreach (InventoryItemBase listItem in inventoryItems) - { - if (listItem.AssetID == assetid) - { - inventoryItem = listItem; - break; - } - } + if (requestData.Contains("region_name")) + regionName = (string)requestData["region_name"]; - // Create inventory item - if (inventoryItem == null) - { - inventoryItem = new InventoryItemBase(UUID.Random(), ID); - inventoryItem.Name = GetStringAttribute(item,"name",""); - inventoryItem.Description = GetStringAttribute(item,"desc",""); - inventoryItem.InvType = GetIntegerAttribute(item,"invtype",-1); - inventoryItem.CreatorId = GetStringAttribute(item,"creatorid",""); - inventoryItem.CreatorIdAsUuid = (UUID)GetStringAttribute(item,"creatoruuid",""); - inventoryItem.CreatorData = GetStringAttribute(item, "creatordata", ""); - inventoryItem.NextPermissions = GetUnsignedAttribute(perms, "next", 0x7fffffff); - inventoryItem.CurrentPermissions = GetUnsignedAttribute(perms,"current",0x7fffffff); - inventoryItem.BasePermissions = GetUnsignedAttribute(perms,"base",0x7fffffff); - inventoryItem.EveryOnePermissions = GetUnsignedAttribute(perms,"everyone",0x7fffffff); - inventoryItem.GroupPermissions = GetUnsignedAttribute(perms,"group",0x7fffffff); - inventoryItem.AssetType = GetIntegerAttribute(item,"assettype",-1); - inventoryItem.AssetID = assetid; // associated asset - inventoryItem.GroupID = (UUID)GetStringAttribute(item,"groupid",""); - inventoryItem.GroupOwned = (GetStringAttribute(item,"groupowned","false") == "true"); - inventoryItem.SalePrice = GetIntegerAttribute(item,"saleprice",0); - inventoryItem.SaleType = (byte)GetIntegerAttribute(item,"saletype",0); - inventoryItem.Flags = GetUnsignedAttribute(item,"flags",0); - inventoryItem.CreationDate = GetIntegerAttribute(item,"creationdate",Util.UnixTimeSinceEpoch()); - inventoryItem.Folder = extraFolder.ID; // Parent folder + pos.X = ParseFloat(requestData, "pos_x", sp.AbsolutePosition.X); + pos.Y = ParseFloat(requestData, "pos_y", sp.AbsolutePosition.Y); + pos.Z = ParseFloat(requestData, "pos_z", sp.AbsolutePosition.Z); + lookAt.X = ParseFloat(requestData, "lookat_x", sp.Lookat.X); + lookAt.Y = ParseFloat(requestData, "lookat_y", sp.Lookat.Y); + lookAt.Z = ParseFloat(requestData, "lookat_z", sp.Lookat.Z); - m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(inventoryItem); - m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", inventoryItem.ID, extraFolder.ID); - } + sp.Scene.RequestTeleportLocation( + sp.ControllingClient, regionName, pos, lookAt, (uint)Constants.TeleportFlags.ViaLocation); - // Attach item, if attachpoint is specified - int attachpoint = GetIntegerAttribute(item,"attachpoint",0); - if (attachpoint != 0) - { - avatarAppearance.SetAttachment(attachpoint, inventoryItem.ID, inventoryItem.AssetID); - m_log.DebugFormat("[RADMIN]: Attached {0}", inventoryItem.ID); - } + // We have no way of telling the failure of the actual teleport + responseData["success"] = true; + } - // Record whether or not the item is to be initially worn - try - { - if (select && (GetStringAttribute(item, "wear", "false") == "true")) - { - avatarAppearance.Wearables[inventoryItem.Flags].Wear(inventoryItem.ID, inventoryItem.AssetID); - } - } - catch (Exception e) - { - m_log.WarnFormat("[RADMIN]: Error wearing item {0} : {1}", inventoryItem.ID, e.Message); - } - } // foreach item in outfit - m_log.DebugFormat("[RADMIN]: Outfit {0} load completed", outfitName); - } // foreach outfit - m_log.DebugFormat("[RADMIN]: Inventory update complete for {0}", name); - scene.AvatarService.SetAppearance(ID, avatarAppearance); - } - catch (Exception e) - { - m_log.WarnFormat("[RADMIN]: Inventory processing incomplete for user {0} : {1}", - name, e.Message); - } - } // End of include - } - m_log.DebugFormat("[RADMIN]: Default avatar loading complete"); - } + /// + /// Parse a float with the given parameter name from a request data hash table. + /// + /// + /// Will throw an exception if parameter is not a float. + /// Will not throw if parameter is not found, passes back default value instead. + /// + /// + /// + /// + /// + private static float ParseFloat(Hashtable requestData, string paramName, float defaultVal) + { + if (requestData.Contains(paramName)) + { + string rawVal = (string)requestData[paramName]; + float val; + + if (!float.TryParse(rawVal, out val)) + throw new Exception(string.Format("{0} {1} is not a valid float", paramName, rawVal)); else - { - m_log.DebugFormat("[RADMIN]: No default avatar information available"); - return false; - } + return val; } - catch (Exception e) + else { - m_log.WarnFormat("[RADMIN]: Exception whilst loading default avatars ; {0}", e.Message); - return false; + return defaultVal; } - - return true; } - /// - /// Load an OAR file into a region.. - /// - /// incoming XML RPC request - /// - /// XmlRpcLoadOARMethod takes the following XMLRPC - /// parameters - /// - /// parameter namedescription - /// password - /// admin password as set in OpenSim.ini - /// filename - /// file name of the OAR file - /// region_uuid - /// UUID of the region - /// region_name - /// region name - /// merge - /// true if oar should be merged - /// skip-assets - /// true if assets should be skiped - /// - /// - /// region_uuid takes precedence over - /// region_name if both are present; one of both - /// must be present. - /// - /// XmlRpcLoadOARMethod returns - /// - /// namedescription - /// success - /// true or false - /// error - /// error message if success is false - /// - /// - public XmlRpcResponse XmlRpcLoadOARMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private static void CheckStringParameters(Hashtable requestData, Hashtable responseData, string[] param) { - m_log.Info("[RADMIN]: Received Load OAR Administrator Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - lock (m_requestLock) + foreach (string parameter in param) { - try + if (!requestData.Contains(parameter)) { - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] { - "password", "filename"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - string filename = (string) requestData["filename"]; - Scene scene = null; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TryGetScene(region_uuid, out scene)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(region_name, out scene)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - } - else throw new Exception("neither region_name nor region_uuid given"); - - bool mergeOar = false; - bool skipAssets = false; - - if ((string)requestData["merge"] == "true") - { - mergeOar = true; - } - if ((string)requestData["skip-assets"] == "true") - { - skipAssets = true; - } - - IRegionArchiverModule archiver = scene.RequestModuleInterface(); - if (archiver != null) - archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty); - else - throw new Exception("Archiver module not present for scene"); - - responseData["loaded"] = true; - - response.Value = responseData; + responseData["accepted"] = false; + throw new Exception(String.Format("missing string parameter {0}", parameter)); } - catch (Exception e) + if (String.IsNullOrEmpty((string) requestData[parameter])) { - m_log.ErrorFormat("[RADMIN]: LoadOAR: {0} {1}", e.Message, e.StackTrace); - - responseData["loaded"] = false; - responseData["error"] = e.Message; - - response.Value = responseData; + responseData["accepted"] = false; + throw new Exception(String.Format("parameter {0} is empty", parameter)); } - - m_log.Info("[RADMIN]: Load OAR Administrator Request complete"); - return response; } } - /// - /// Save a region to an OAR file - /// - /// incoming XML RPC request - /// - /// XmlRpcSaveOARMethod takes the following XMLRPC - /// parameters - /// - /// parameter namedescription - /// password - /// admin password as set in OpenSim.ini - /// filename - /// file name for the OAR file - /// region_uuid - /// UUID of the region - /// region_name - /// region name - /// profile - /// profile url - /// noassets - /// true if no assets should be saved - /// perm - /// C and/or T - /// - /// - /// region_uuid takes precedence over - /// region_name if both are present; one of both - /// must be present. - /// - /// XmlRpcLoadOARMethod returns - /// - /// namedescription - /// success - /// true or false - /// error - /// error message if success is false - /// - /// - public XmlRpcResponse XmlRpcSaveOARMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private static void CheckIntegerParams(Hashtable requestData, Hashtable responseData, string[] param) { - m_log.Info("[RADMIN]: Received Save OAR Administrator Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try + foreach (string parameter in param) { - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] { - "password", "filename"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - string filename = (string) requestData["filename"]; - Scene scene = null; - if (requestData.Contains("region_uuid")) + if (!requestData.Contains(parameter)) { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TryGetScene(region_uuid, out scene)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + responseData["accepted"] = false; + throw new Exception(String.Format("missing integer parameter {0}", parameter)); } - else if (requestData.Contains("region_name")) + } + } + + private bool GetBoolean(Hashtable requestData, string tag, bool defaultValue) + { + // If an access value has been provided, apply it. + if (requestData.Contains(tag)) + { + switch (((string)requestData[tag]).ToLower()) { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(region_name, out scene)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); + case "true" : + case "t" : + case "1" : + return true; + case "false" : + case "f" : + case "0" : + return false; + default : + return defaultValue; } - else throw new Exception("neither region_name nor region_uuid given"); + } + else + return defaultValue; + } - Dictionary options = new Dictionary(); + private int GetIntegerAttribute(XmlNode node, string attribute, int defaultValue) + { + try { return Convert.ToInt32(node.Attributes[attribute].Value); } catch{} + return defaultValue; + } - //if (requestData.Contains("version")) - //{ - // options["version"] = (string)requestData["version"]; - //} + private uint GetUnsignedAttribute(XmlNode node, string attribute, uint defaultValue) + { + try { return Convert.ToUInt32(node.Attributes[attribute].Value); } catch{} + return defaultValue; + } - if (requestData.Contains("profile")) - { - options["profile"] = (string)requestData["profile"]; - } - - if (requestData["noassets"] == "true") - { - options["noassets"] = (string)requestData["noassets"] ; - } - - if (requestData.Contains("perm")) - { - options["checkPermissions"] = (string)requestData["perm"]; - } - - IRegionArchiverModule archiver = scene.RequestModuleInterface(); - - if (archiver != null) - { - scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted; - archiver.ArchiveRegion(filename, options); - - lock (m_saveOarLock) - Monitor.Wait(m_saveOarLock,5000); - - scene.EventManager.OnOarFileSaved -= RemoteAdminOarSaveCompleted; - } - else - { - throw new Exception("Archiver module not present for scene"); - } - - responseData["saved"] = true; - - response.Value = responseData; - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: SaveOAR: {0} {1}", e.Message, e.StackTrace); - - responseData["saved"] = false; - responseData["error"] = e.Message; - - response.Value = responseData; - } - - m_log.Info("[RADMIN]: Save OAR Administrator Request complete"); - return response; + private string GetStringAttribute(XmlNode node, string attribute, string defaultValue) + { + try { return node.Attributes[attribute].Value; } catch{} + return defaultValue; } - private void RemoteAdminOarSaveCompleted(Guid uuid, string name) + public void Dispose() { - m_log.DebugFormat("[RADMIN]: File processing complete for {0}", name); - lock (m_saveOarLock) Monitor.Pulse(m_saveOarLock); } - public XmlRpcResponse XmlRpcLoadXMLMethod(XmlRpcRequest request, IPEndPoint remoteClient) + /// + /// Create a user + /// + /// + /// + /// + /// + /// + private UserAccount CreateUser(UUID scopeID, string firstName, string lastName, string password, string email) { - m_log.Info("[RADMIN]: Received Load XML Administrator Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Scene scene = m_application.SceneManager.CurrentOrFirstScene; + IUserAccountService userAccountService = scene.UserAccountService; + IGridService gridService = scene.GridService; + IAuthenticationService authenticationService = scene.AuthenticationService; + IGridUserService gridUserService = scene.GridUserService; + IInventoryService inventoryService = scene.InventoryService; - lock (m_requestLock) + UserAccount account = userAccountService.GetUserAccount(scopeID, firstName, lastName); + if (null == account) { - try + account = new UserAccount(scopeID, UUID.Random(), firstName, lastName, email); + if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0)) { - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] { - "password", "filename"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - string filename = (string) requestData["filename"]; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + account.ServiceURLs = new Dictionary(); + account.ServiceURLs["HomeURI"] = string.Empty; + account.ServiceURLs["GatekeeperURI"] = string.Empty; + account.ServiceURLs["InventoryServerURI"] = string.Empty; + account.ServiceURLs["AssetServerURI"] = string.Empty; + } - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) + if (userAccountService.StoreUserAccount(account)) + { + bool success; + if (authenticationService != null) { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + success = authenticationService.SetPassword(account.PrincipalID, password); + if (!success) + m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", + firstName, lastName); } - else throw new Exception("neither region_name nor region_uuid given"); - - responseData["switched"] = true; - string xml_version = "1"; - if (requestData.Contains("xml_version")) + GridRegion home = null; + if (gridService != null) { - xml_version = (string) requestData["xml_version"]; + List defaultRegions = gridService.GetDefaultRegions(UUID.Zero); + if (defaultRegions != null && defaultRegions.Count >= 1) + home = defaultRegions[0]; + + if (gridUserService != null && home != null) + gridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); + else + m_log.WarnFormat("[RADMIN]: Unable to set home for account {0} {1}.", + firstName, lastName); } + else + m_log.WarnFormat("[RADMIN]: Unable to retrieve home region for account {0} {1}.", + firstName, lastName); - switch (xml_version) + if (inventoryService != null) { - case "1": - m_application.SceneManager.LoadCurrentSceneFromXml(filename, true, new Vector3(0, 0, 0)); - break; - - case "2": - m_application.SceneManager.LoadCurrentSceneFromXml2(filename); - break; - - default: - throw new Exception(String.Format("unknown Xml{0} format", xml_version)); + success = inventoryService.CreateUserInventory(account.PrincipalID); + if (!success) + m_log.WarnFormat("[RADMIN]: Unable to create inventory for account {0} {1}.", + firstName, lastName); } - responseData["loaded"] = true; - response.Value = responseData; - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN] LoadXml: {0} {1}", e.Message, e.StackTrace); - - responseData["loaded"] = false; - responseData["switched"] = false; - responseData["error"] = e.Message; - - response.Value = responseData; + m_log.InfoFormat("[RADMIN]: Account {0} {1} created successfully", firstName, lastName); + return account; + } else { + m_log.ErrorFormat("[RADMIN]: Account creation failed for account {0} {1}", firstName, lastName); } - - m_log.Info("[RADMIN]: Load XML Administrator Request complete"); - return response; } + else + { + m_log.ErrorFormat("[RADMIN]: A user with the name {0} {1} already exists!", firstName, lastName); + } + return null; } - public XmlRpcResponse XmlRpcSaveXMLMethod(XmlRpcRequest request, IPEndPoint remoteClient) + /// + /// Change password + /// + /// + /// + /// + private bool ChangeUserPassword(string firstName, string lastName, string password) { - m_log.Info("[RADMIN]: Received Save XML Administrator Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Scene scene = m_application.SceneManager.CurrentOrFirstScene; + IUserAccountService userAccountService = scene.UserAccountService; + IAuthenticationService authenticationService = scene.AuthenticationService; - try + UserAccount account = userAccountService.GetUserAccount(UUID.Zero, firstName, lastName); + if (null != account) { - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] { - "password", "filename"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - string filename = (string) requestData["filename"]; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else throw new Exception("neither region_name nor region_uuid given"); - - responseData["switched"] = true; - - string xml_version = "1"; - if (requestData.Contains("xml_version")) - { - xml_version = (string) requestData["xml_version"]; - } + bool success = false; + if (authenticationService != null) + success = authenticationService.SetPassword(account.PrincipalID, password); - switch (xml_version) + if (!success) { - case "1": - m_application.SceneManager.SaveCurrentSceneToXml(filename); - break; - - case "2": - m_application.SceneManager.SaveCurrentSceneToXml2(filename); - break; - - default: - throw new Exception(String.Format("unknown Xml{0} format", xml_version)); + m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", + firstName, lastName); + return false; } - - responseData["saved"] = true; - - response.Value = responseData; + return true; } - catch (Exception e) + else { - m_log.ErrorFormat("[RADMIN]: SaveXml: {0} {1}", e.Message, e.StackTrace); - - responseData["saved"] = false; - responseData["switched"] = false; - responseData["error"] = e.Message; - - response.Value = responseData; + m_log.ErrorFormat("[RADMIN]: No such user"); + return false; } - - m_log.Info("[RADMIN]: Save XML Administrator Request complete"); - return response; } - public XmlRpcResponse XmlRpcRegionQueryMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private bool LoadHeightmap(string file, UUID regionID) { - m_log.Info("[RADMIN]: Received Query XML Administrator Request"); + m_log.InfoFormat("[RADMIN]: Terrain Loading: {0}", file); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Scene region = null; - try + if (!m_application.SceneManager.TryGetScene(regionID, out region)) { - responseData["success"] = true; - - Hashtable requestData = (Hashtable) request.Params[0]; + m_log.InfoFormat("[RADMIN]: unable to get a scene with that name: {0}", regionID.ToString()); + return false; + } - CheckStringParameters(request, new string[] { - "password"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) + ITerrainModule terrainModule = region.RequestModuleInterface(); + if (null == terrainModule) throw new Exception("terrain module not available"); + if (Uri.IsWellFormedUriString(file, UriKind.Absolute)) + { + m_log.Info("[RADMIN]: Terrain path is URL"); + Uri result; + if (Uri.TryCreate(file, UriKind.RelativeOrAbsolute, out result)) { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + // the url is valid + string fileType = file.Substring(file.LastIndexOf('/') + 1); + terrainModule.LoadFromStream(fileType, result); } - else throw new Exception("neither region_name nor region_uuid given"); - - Scene scene = m_application.SceneManager.CurrentScene; - int health = scene.GetHealth(); - responseData["health"] = health; - - response.Value = responseData; } - catch (Exception e) + else { - m_log.InfoFormat("[RADMIN]: RegionQuery: {0}", e.Message); - - responseData["success"] = false; - responseData["error"] = e.Message; - - response.Value = responseData; + terrainModule.LoadFromFile(file); } - m_log.Info("[RADMIN]: Query XML Administrator Request complete"); + m_log.Info("[RADMIN]: Load height maps request complete"); - return response; + return true; } - public XmlRpcResponse XmlRpcConsoleCommandMethod(XmlRpcRequest request, IPEndPoint remoteClient) + + /// + /// This method is called by the user-create and user-modify methods to establish + /// or change, the user's appearance. Default avatar names can be specified via + /// the config file, but must correspond to avatars in the default appearance + /// file, or pre-existing in the user database. + /// This should probably get moved into somewhere more core eventually. + /// + private void UpdateUserAppearance(Hashtable responseData, Hashtable requestData, UUID userid) { - m_log.Info("[RADMIN]: Received Command XML Administrator Request"); + m_log.DebugFormat("[RADMIN]: updateUserAppearance"); - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + string defaultMale = m_config.GetString("default_male", "Default Male"); + string defaultFemale = m_config.GetString("default_female", "Default Female"); + string defaultNeutral = m_config.GetString("default_female", "Default Default"); + string model = String.Empty; - try - { - responseData["success"] = true; + // Has a gender preference been supplied? - Hashtable requestData = (Hashtable) request.Params[0]; + if (requestData.Contains("gender")) + { + switch ((string)requestData["gender"]) + { + case "m" : + case "male" : + model = defaultMale; + break; + case "f" : + case "female" : + model = defaultFemale; + break; + case "n" : + case "neutral" : + default : + model = defaultNeutral; + break; + } + } - CheckStringParameters(request, new string[] { - "password", "command"}); + // Has an explicit model been specified? - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + if (requestData.Contains("model") && (String.IsNullOrEmpty((string)requestData["gender"]))) + { + model = (string)requestData["model"]; + } - MainConsole.Instance.RunCommand(requestData["command"].ToString()); + // No appearance attributes were set - response.Value = responseData; - } - catch (Exception e) + if (String.IsNullOrEmpty(model)) { - m_log.InfoFormat("[RADMIN]: ConsoleCommand: {0}", e.Message); + m_log.DebugFormat("[RADMIN]: Appearance update not requested"); + return; + } - responseData["success"] = false; - responseData["error"] = e.Message; + m_log.DebugFormat("[RADMIN]: Setting appearance for avatar {0}, using model <{1}>", userid, model); - response.Value = responseData; + string[] modelSpecifiers = model.Split(); + if (modelSpecifiers.Length != 2) + { + m_log.WarnFormat("[RADMIN]: User appearance not set for {0}. Invalid model name : <{1}>", userid, model); + // modelSpecifiers = dmodel.Split(); + return; } - m_log.Info("[RADMIN]: Command XML Administrator Request complete"); - return response; - } + Scene scene = m_application.SceneManager.CurrentOrFirstScene; + UUID scopeID = scene.RegionInfo.ScopeID; + UserAccount modelProfile = scene.UserAccountService.GetUserAccount(scopeID, modelSpecifiers[0], modelSpecifiers[1]); - public XmlRpcResponse XmlRpcAccessListClear(XmlRpcRequest request, IPEndPoint remoteClient) - { - m_log.Info("[RADMIN]: Received Access List Clear Request"); + if (modelProfile == null) + { + m_log.WarnFormat("[RADMIN]: Requested model ({0}) not found. Appearance unchanged", model); + return; + } - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + // Set current user's appearance. This bit is easy. The appearance structure is populated with + // actual asset ids, however to complete the magic we need to populate the inventory with the + // assets in question. - try - { - responseData["success"] = true; + EstablishAppearance(userid, modelProfile.PrincipalID); - Hashtable requestData = (Hashtable) request.Params[0]; + m_log.DebugFormat("[RADMIN]: Finished setting appearance for avatar {0}, using model {1}", + userid, model); + } - CheckStringParameters(request, new string[] { - "password"}); + /// + /// This method is called by updateAvatarAppearance once any specified model has been + /// ratified, or an appropriate default value has been adopted. The intended prototype + /// is known to exist, as is the target avatar. + /// + private void EstablishAppearance(UUID destination, UUID source) + { + m_log.DebugFormat("[RADMIN]: Initializing inventory for {0} from {1}", destination, source); + Scene scene = m_application.SceneManager.CurrentOrFirstScene; - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + // If the model has no associated appearance we're done. + AvatarAppearance avatarAppearance = scene.AvatarService.GetAppearance(source); + if (avatarAppearance == null) + return; - if (requestData.Contains("region_uuid")) + // Simple appearance copy or copy Clothing and Bodyparts folders? + bool copyFolders = m_config.GetBoolean("copy_folders", false); + + if (!copyFolders) + { + // Simple copy of wearables and appearance update + try { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); + CopyWearablesAndAttachments(destination, source, avatarAppearance); + + scene.AvatarService.SetAppearance(destination, avatarAppearance); } - else if (requestData.Contains("region_name")) + catch (Exception e) { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + m_log.WarnFormat("[RADMIN]: Error transferring appearance for {0} : {1}", + destination, e.Message); } - else throw new Exception("neither region_name nor region_uuid given"); - - Scene scene = m_application.SceneManager.CurrentScene; - scene.RegionInfo.EstateSettings.EstateAccess = new UUID[]{}; - - if (scene.RegionInfo.Persistent) - scene.RegionInfo.EstateSettings.Save(); - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: Access List Clear Request: {0} {1}", e.Message, e.StackTrace); - responseData["success"] = false; - responseData["error"] = e.Message; - } - finally - { - response.Value = responseData; + return; } - m_log.Info("[RADMIN]: Access List Clear Request complete"); - return response; - } - - public XmlRpcResponse XmlRpcAccessListAdd(XmlRpcRequest request, IPEndPoint remoteClient) - { - m_log.Info("[RADMIN]: Received Access List Add Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - + // Copy Clothing and Bodypart folders and appearance update try { - responseData["success"] = true; - - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] { - "password"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else throw new Exception("neither region_name nor region_uuid given"); + Dictionary inventoryMap = new Dictionary(); + CopyInventoryFolders(destination, source, AssetType.Clothing, inventoryMap, avatarAppearance); + CopyInventoryFolders(destination, source, AssetType.Bodypart, inventoryMap, avatarAppearance); - int addedUsers = 0; + AvatarWearable[] wearables = avatarAppearance.Wearables; - if (requestData.Contains("users")) + for (int i=0; i uuids = new List(); - foreach (string name in users.Values) - { - string[] parts = name.Split(); - UserAccount account = userService.GetUserAccount(scopeID, parts[0], parts[1]); - if (account != null) - { - uuids.Add(account.PrincipalID); - m_log.DebugFormat("[RADMIN]: adding \"{0}\" to ACL for \"{1}\"", name, scene.RegionInfo.RegionName); - } - } - List accessControlList = new List(scene.RegionInfo.EstateSettings.EstateAccess); - foreach (UUID uuid in uuids) + if (inventoryMap.ContainsKey(wearables[i][0].ItemID)) { - if (!accessControlList.Contains(uuid)) - { - accessControlList.Add(uuid); - addedUsers++; - } + AvatarWearable wearable = new AvatarWearable(); + wearable.Wear(inventoryMap[wearables[i][0].ItemID], + wearables[i][0].AssetID); + avatarAppearance.SetWearable(i, wearable); } - scene.RegionInfo.EstateSettings.EstateAccess = accessControlList.ToArray(); - if (scene.RegionInfo.Persistent) - scene.RegionInfo.EstateSettings.Save(); } - responseData["added"] = addedUsers; + scene.AvatarService.SetAppearance(destination, avatarAppearance); } catch (Exception e) { - m_log.ErrorFormat("[RADMIN]: Access List Add Request: {0} {1}", e.Message, e.StackTrace); - - responseData["success"] = false; - responseData["error"] = e.Message; - } - finally - { - response.Value = responseData; + m_log.WarnFormat("[RADMIN]: Error transferring appearance for {0} : {1}", + destination, e.Message); } - m_log.Info("[RADMIN]: Access List Add Request complete"); - return response; + return; } - public XmlRpcResponse XmlRpcAccessListRemove(XmlRpcRequest request, IPEndPoint remoteClient) + /// + /// This method is called by establishAppearance to do a copy all inventory items + /// worn or attached to the Clothing inventory folder of the receiving avatar. + /// In parallel the avatar wearables and attachments are updated. + /// + private void CopyWearablesAndAttachments(UUID destination, UUID source, AvatarAppearance avatarAppearance) { - m_log.Info("[RADMIN]: Received Access List Remove Request"); + IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + // Get Clothing folder of receiver + InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, AssetType.Clothing); - try - { - responseData["success"] = true; + if (destinationFolder == null) + throw new Exception("Cannot locate folder(s)"); - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] { - "password"}); + // Missing destination folder? This should *never* be the case + if (destinationFolder.Type != (short)AssetType.Clothing) + { + destinationFolder = new InventoryFolderBase(); + + destinationFolder.ID = UUID.Random(); + destinationFolder.Name = "Clothing"; + destinationFolder.Owner = destination; + destinationFolder.Type = (short)AssetType.Clothing; + destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID; + destinationFolder.Version = 1; + inventoryService.AddFolder(destinationFolder); // store base record + m_log.ErrorFormat("[RADMIN]: Created folder for destination {0}", source); + } - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + // Wearables + AvatarWearable[] wearables = avatarAppearance.Wearables; + AvatarWearable wearable; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) + for (int i = 0; i uuids = new List(); - foreach (string name in users.Values) + if (item != null) { - string[] parts = name.Split(); - UserAccount account = userService.GetUserAccount(scopeID, parts[0], parts[1]); - if (account != null) - { - uuids.Add(account.PrincipalID); - } + InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); + destinationItem.Name = item.Name; + destinationItem.Owner = destination; + destinationItem.Description = item.Description; + destinationItem.InvType = item.InvType; + destinationItem.CreatorId = item.CreatorId; + destinationItem.CreatorIdAsUuid = item.CreatorIdAsUuid; + destinationItem.CreatorData = item.CreatorData; + destinationItem.NextPermissions = item.NextPermissions; + destinationItem.CurrentPermissions = item.CurrentPermissions; + destinationItem.BasePermissions = item.BasePermissions; + destinationItem.EveryOnePermissions = item.EveryOnePermissions; + destinationItem.GroupPermissions = item.GroupPermissions; + destinationItem.AssetType = item.AssetType; + destinationItem.AssetID = item.AssetID; + destinationItem.GroupID = item.GroupID; + destinationItem.GroupOwned = item.GroupOwned; + destinationItem.SalePrice = item.SalePrice; + destinationItem.SaleType = item.SaleType; + destinationItem.Flags = item.Flags; + destinationItem.CreationDate = item.CreationDate; + destinationItem.Folder = destinationFolder.ID; + ApplyNextOwnerPermissions(destinationItem); + + m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); + m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); + + // Wear item + AvatarWearable newWearable = new AvatarWearable(); + newWearable.Wear(destinationItem.ID, wearable[0].AssetID); + avatarAppearance.SetWearable(i, newWearable); } - List accessControlList = new List(scene.RegionInfo.EstateSettings.EstateAccess); - foreach (UUID uuid in uuids) + else { - if (accessControlList.Contains(uuid)) - { - accessControlList.Remove(uuid); - removedUsers++; - } + m_log.WarnFormat("[RADMIN]: Error transferring {0} to folder {1}", wearable[0].ItemID, destinationFolder.ID); } - scene.RegionInfo.EstateSettings.EstateAccess = accessControlList.ToArray(); - if (scene.RegionInfo.Persistent) - scene.RegionInfo.EstateSettings.Save(); } - - responseData["removed"] = removedUsers; - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: Access List Remove Request: {0} {1}", e.Message, e.StackTrace); - - responseData["success"] = false; - responseData["error"] = e.Message; - } - finally - { - response.Value = responseData; } - m_log.Info("[RADMIN]: Access List Remove Request complete"); - return response; - } - - public XmlRpcResponse XmlRpcAccessListList(XmlRpcRequest request, IPEndPoint remoteClient) - { - m_log.Info("[RADMIN]: Received Access List List Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + // Attachments + List attachments = avatarAppearance.GetAttachments(); - try + foreach (AvatarAttachment attachment in attachments) { - responseData["success"] = true; - - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] { - "password"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + int attachpoint = attachment.AttachPoint; + UUID itemID = attachment.ItemID; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) + if (itemID != UUID.Zero) { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else throw new Exception("neither region_name nor region_uuid given"); + // Get inventory item and copy it + InventoryItemBase item = new InventoryItemBase(itemID, source); + item = inventoryService.GetItem(item); - Scene scene = m_application.SceneManager.CurrentScene; - UUID[] accessControlList = scene.RegionInfo.EstateSettings.EstateAccess; - Hashtable users = new Hashtable(); + if (item != null) + { + InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); + destinationItem.Name = item.Name; + destinationItem.Owner = destination; + destinationItem.Description = item.Description; + destinationItem.InvType = item.InvType; + destinationItem.CreatorId = item.CreatorId; + destinationItem.CreatorIdAsUuid = item.CreatorIdAsUuid; + destinationItem.CreatorData = item.CreatorData; + destinationItem.NextPermissions = item.NextPermissions; + destinationItem.CurrentPermissions = item.CurrentPermissions; + destinationItem.BasePermissions = item.BasePermissions; + destinationItem.EveryOnePermissions = item.EveryOnePermissions; + destinationItem.GroupPermissions = item.GroupPermissions; + destinationItem.AssetType = item.AssetType; + destinationItem.AssetID = item.AssetID; + destinationItem.GroupID = item.GroupID; + destinationItem.GroupOwned = item.GroupOwned; + destinationItem.SalePrice = item.SalePrice; + destinationItem.SaleType = item.SaleType; + destinationItem.Flags = item.Flags; + destinationItem.CreationDate = item.CreationDate; + destinationItem.Folder = destinationFolder.ID; + ApplyNextOwnerPermissions(destinationItem); - foreach (UUID user in accessControlList) - { - UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; - UserAccount account = m_application.SceneManager.CurrentOrFirstScene.UserAccountService.GetUserAccount(scopeID, user); - if (account != null) + m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); + m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); + + // Attach item + avatarAppearance.SetAttachment(attachpoint, destinationItem.ID, destinationItem.AssetID); + m_log.DebugFormat("[RADMIN]: Attached {0}", destinationItem.ID); + } + else { - users[user.ToString()] = account.FirstName + " " + account.LastName; + m_log.WarnFormat("[RADMIN]: Error transferring {0} to folder {1}", itemID, destinationFolder.ID); } } - - responseData["users"] = users; - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: Access List List: {0} {1}", e.Message, e.StackTrace); - - responseData["success"] = false; - responseData["error"] = e.Message; - } - finally - { - response.Value = responseData; } - - m_log.Info("[RADMIN]: Access List List Request complete"); - return response; } - public XmlRpcResponse XmlRpcTeleportAgentMethod(XmlRpcRequest request, IPEndPoint remoteClient) + /// + /// This method is called by establishAppearance to copy inventory folders to make + /// copies of Clothing and Bodyparts inventory folders and attaches worn attachments + /// + private void CopyInventoryFolders(UUID destination, UUID source, AssetType assetType, Dictionary inventoryMap, + AvatarAppearance avatarAppearance) { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - responseData["success"] = true; - - Hashtable requestData = (Hashtable)request.Params[0]; - - CheckStringParameters(request, new string[] {"password"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; - UUID agentId; - string regionName = null; - Vector3 pos, lookAt; - bool agentSpecified = false; - ScenePresence sp = null; + InventoryFolderBase sourceFolder = inventoryService.GetFolderForType(source, assetType); + InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, assetType); - if (requestData.Contains("agent_first_name") && requestData.Contains("agent_last_name")) - { - string firstName = requestData["agent_first_name"].ToString(); - string lastName = requestData["agent_last_name"].ToString(); - m_application.SceneManager.TryGetRootScenePresenceByName(firstName, lastName, out sp); + if (sourceFolder == null || destinationFolder == null) + throw new Exception("Cannot locate folder(s)"); - if (sp == null) - throw new Exception( - string.Format( - "No agent found with agent_first_name {0} and agent_last_name {1}", firstName, lastName)); + // Missing source folder? This should *never* be the case + if (sourceFolder.Type != (short)assetType) + { + sourceFolder = new InventoryFolderBase(); + sourceFolder.ID = UUID.Random(); + if (assetType == AssetType.Clothing) { + sourceFolder.Name = "Clothing"; + } else { + sourceFolder.Name = "Body Parts"; } - else if (requestData.Contains("agent_id")) - { - string rawAgentId = (string)requestData["agent_id"]; - - if (!UUID.TryParse(rawAgentId, out agentId)) - throw new Exception(string.Format("agent_id {0} does not have the correct id format", rawAgentId)); - - m_application.SceneManager.TryGetRootScenePresence(agentId, out sp); + sourceFolder.Owner = source; + sourceFolder.Type = (short)assetType; + sourceFolder.ParentID = inventoryService.GetRootFolder(source).ID; + sourceFolder.Version = 1; + inventoryService.AddFolder(sourceFolder); // store base record + m_log.ErrorFormat("[RADMIN] Created folder for source {0}", source); + } - if (sp == null) - throw new Exception(string.Format("No agent with agent_id {0} found in this simulator", agentId)); + // Missing destination folder? This should *never* be the case + if (destinationFolder.Type != (short)assetType) + { + destinationFolder = new InventoryFolderBase(); + destinationFolder.ID = UUID.Random(); + if (assetType == AssetType.Clothing) + { + destinationFolder.Name = "Clothing"; } else { - throw new Exception("No agent_id or agent_first_name and agent_last_name parameters specified"); + destinationFolder.Name = "Body Parts"; } + destinationFolder.Owner = destination; + destinationFolder.Type = (short)assetType; + destinationFolder.ParentID = inventoryService.GetRootFolder(destination).ID; + destinationFolder.Version = 1; + inventoryService.AddFolder(destinationFolder); // store base record + m_log.ErrorFormat("[RADMIN]: Created folder for destination {0}", source); + } - if (requestData.Contains("region_name")) - regionName = (string)requestData["region_name"]; - - pos.X = ParseFloat(requestData, "pos_x", sp.AbsolutePosition.X); - pos.Y = ParseFloat(requestData, "pos_y", sp.AbsolutePosition.Y); - pos.Z = ParseFloat(requestData, "pos_z", sp.AbsolutePosition.Z); - lookAt.X = ParseFloat(requestData, "lookat_x", sp.Lookat.X); - lookAt.Y = ParseFloat(requestData, "lookat_y", sp.Lookat.Y); - lookAt.Z = ParseFloat(requestData, "lookat_z", sp.Lookat.Z); + InventoryFolderBase extraFolder; + List folders = inventoryService.GetFolderContent(source, sourceFolder.ID).Folders; - sp.Scene.RequestTeleportLocation( - sp.ControllingClient, regionName, pos, lookAt, (uint)Constants.TeleportFlags.ViaLocation); - } - catch (Exception e) + foreach (InventoryFolderBase folder in folders) { - m_log.ErrorFormat("[RADMIN]: admin_teleport_agent exception: {0}{1}", e.Message, e.StackTrace); + extraFolder = new InventoryFolderBase(); + extraFolder.ID = UUID.Random(); + extraFolder.Name = folder.Name; + extraFolder.Owner = destination; + extraFolder.Type = folder.Type; + extraFolder.Version = folder.Version; + extraFolder.ParentID = destinationFolder.ID; + inventoryService.AddFolder(extraFolder); - responseData["success"] = false; - responseData["error"] = e.Message; - } - finally - { - response.Value = responseData; - } + m_log.DebugFormat("[RADMIN]: Added folder {0} to folder {1}", extraFolder.ID, sourceFolder.ID); - return response; - } + List items = inventoryService.GetFolderContent(source, folder.ID).Items; - /// - /// Parse a float with the given parameter name from a request data hash table. - /// - /// - /// Will throw an exception if parameter is not a float. - /// Will not throw if parameter is not found, passes back default value instead. - /// - /// - /// - /// - /// - private static float ParseFloat(Hashtable requestData, string paramName, float defaultVal) - { - if (requestData.Contains(paramName)) - { - string rawVal = (string)requestData[paramName]; - float val; + foreach (InventoryItemBase item in items) + { + InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination); + destinationItem.Name = item.Name; + destinationItem.Owner = destination; + destinationItem.Description = item.Description; + destinationItem.InvType = item.InvType; + destinationItem.CreatorId = item.CreatorId; + destinationItem.CreatorIdAsUuid = item.CreatorIdAsUuid; + destinationItem.CreatorData = item.CreatorData; + destinationItem.NextPermissions = item.NextPermissions; + destinationItem.CurrentPermissions = item.CurrentPermissions; + destinationItem.BasePermissions = item.BasePermissions; + destinationItem.EveryOnePermissions = item.EveryOnePermissions; + destinationItem.GroupPermissions = item.GroupPermissions; + destinationItem.AssetType = item.AssetType; + destinationItem.AssetID = item.AssetID; + destinationItem.GroupID = item.GroupID; + destinationItem.GroupOwned = item.GroupOwned; + destinationItem.SalePrice = item.SalePrice; + destinationItem.SaleType = item.SaleType; + destinationItem.Flags = item.Flags; + destinationItem.CreationDate = item.CreationDate; + destinationItem.Folder = extraFolder.ID; + ApplyNextOwnerPermissions(destinationItem); - if (!float.TryParse(rawVal, out val)) - throw new Exception(string.Format("{0} {1} is not a valid float", paramName, rawVal)); - else - return val; - } - else - { - return defaultVal; - } - } + m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); + inventoryMap.Add(item.ID, destinationItem.ID); + m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", destinationItem.ID, extraFolder.ID); - private static void CheckStringParameters(XmlRpcRequest request, string[] param) - { - Hashtable requestData = (Hashtable) request.Params[0]; - foreach (string parameter in param) - { - if (!requestData.Contains(parameter)) - throw new Exception(String.Format("missing string parameter {0}", parameter)); - if (String.IsNullOrEmpty((string) requestData[parameter])) - throw new Exception(String.Format("parameter {0} is empty", parameter)); + // Attach item, if original is attached + int attachpoint = avatarAppearance.GetAttachpoint(item.ID); + if (attachpoint != 0) + { + avatarAppearance.SetAttachment(attachpoint, destinationItem.ID, destinationItem.AssetID); + m_log.DebugFormat("[RADMIN]: Attached {0}", destinationItem.ID); + } + } } } - private static void CheckIntegerParams(XmlRpcRequest request, string[] param) + /// + /// Apply next owner permissions. + /// + private void ApplyNextOwnerPermissions(InventoryItemBase item) { - Hashtable requestData = (Hashtable) request.Params[0]; - foreach (string parameter in param) + if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) { - if (!requestData.Contains(parameter)) - throw new Exception(String.Format("missing integer parameter {0}", parameter)); + if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Copy; + if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; + if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Modify; } + item.CurrentPermissions &= item.NextPermissions; + item.BasePermissions &= item.NextPermissions; + item.EveryOnePermissions &= item.NextPermissions; + // item.OwnerChanged = true; + // item.PermsMask = 0; + // item.PermsGranter = UUID.Zero; } - private bool GetBoolean(Hashtable requestData, string tag, bool defaultValue) + /// + /// This method is called if a given model avatar name can not be found. If the external + /// file has already been loaded once, then control returns immediately. If not, then it + /// looks for a default appearance file. This file contains XML definitions of zero or more named + /// avatars, each avatar can specify zero or more "outfits". Each outfit is a collection + /// of items that together, define a particular ensemble for the avatar. Each avatar should + /// indicate which outfit is the default, and this outfit will be automatically worn. The + /// other outfits are provided to allow "real" avatars a way to easily change their outfits. + /// + private bool CreateDefaultAvatars() { - // If an access value has been provided, apply it. - if (requestData.Contains(tag)) + // Only load once + if (m_defaultAvatarsLoaded) { - switch (((string)requestData[tag]).ToLower()) - { - case "true" : - case "t" : - case "1" : - return true; - case "false" : - case "f" : - case "0" : - return false; - default : - return defaultValue; - } + return false; } - else - return defaultValue; - } - - private int GetIntegerAttribute(XmlNode node, string attribute, int defaultValue) - { - try { return Convert.ToInt32(node.Attributes[attribute].Value); } catch{} - return defaultValue; - } - private uint GetUnsignedAttribute(XmlNode node, string attribute, uint defaultValue) - { - try { return Convert.ToUInt32(node.Attributes[attribute].Value); } catch{} - return defaultValue; - } - - private string GetStringAttribute(XmlNode node, string attribute, string defaultValue) - { - try { return node.Attributes[attribute].Value; } catch{} - return defaultValue; - } + m_log.DebugFormat("[RADMIN]: Creating default avatar entries"); - public void Dispose() - { - } + m_defaultAvatarsLoaded = true; - /// - /// Create a user - /// - /// - /// - /// - /// - /// - private UserAccount CreateUser(UUID scopeID, string firstName, string lastName, string password, string email) - { - Scene scene = m_application.SceneManager.CurrentOrFirstScene; - IUserAccountService userAccountService = scene.UserAccountService; - IGridService gridService = scene.GridService; - IAuthenticationService authenticationService = scene.AuthenticationService; - IGridUserService gridUserService = scene.GridUserService; - IInventoryService inventoryService = scene.InventoryService; + // Load processing starts here... - UserAccount account = userAccountService.GetUserAccount(scopeID, firstName, lastName); - if (null == account) + try { - account = new UserAccount(scopeID, UUID.Random(), firstName, lastName, email); - if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0)) + string defaultAppearanceFileName = null; + + //m_config may be null if RemoteAdmin configuration secition is missing or disabled in OpenSim.ini + if (m_config != null) { - account.ServiceURLs = new Dictionary(); - account.ServiceURLs["HomeURI"] = string.Empty; - account.ServiceURLs["GatekeeperURI"] = string.Empty; - account.ServiceURLs["InventoryServerURI"] = string.Empty; - account.ServiceURLs["AssetServerURI"] = string.Empty; + defaultAppearanceFileName = m_config.GetString("default_appearance", "default_appearance.xml"); } - if (userAccountService.StoreUserAccount(account)) + if (File.Exists(defaultAppearanceFileName)) { - bool success; - if (authenticationService != null) + XmlDocument doc = new XmlDocument(); + string name = "*unknown*"; + string email = "anon@anon"; + uint regionXLocation = 1000; + uint regionYLocation = 1000; + string password = UUID.Random().ToString(); // No requirement to sign-in. + UUID ID = UUID.Zero; + AvatarAppearance avatarAppearance; + XmlNodeList avatars; + XmlNodeList assets; + XmlNode perms = null; + bool include = false; + bool select = false; + + Scene scene = m_application.SceneManager.CurrentOrFirstScene; + IInventoryService inventoryService = scene.InventoryService; + IAssetService assetService = scene.AssetService; + + doc.LoadXml(File.ReadAllText(defaultAppearanceFileName)); + + // Load up any included assets. Duplicates will be ignored + assets = doc.GetElementsByTagName("RequiredAsset"); + foreach (XmlNode assetNode in assets) { - success = authenticationService.SetPassword(account.PrincipalID, password); - if (!success) - m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", - firstName, lastName); + AssetBase asset = new AssetBase(UUID.Random(), GetStringAttribute(assetNode, "name", ""), SByte.Parse(GetStringAttribute(assetNode, "type", "")), UUID.Zero.ToString()); + asset.Description = GetStringAttribute(assetNode,"desc",""); + asset.Local = Boolean.Parse(GetStringAttribute(assetNode,"local","")); + asset.Temporary = Boolean.Parse(GetStringAttribute(assetNode,"temporary","")); + asset.Data = Convert.FromBase64String(assetNode.InnerText); + assetService.Store(asset); } - GridRegion home = null; - if (gridService != null) - { - List defaultRegions = gridService.GetDefaultRegions(UUID.Zero); - if (defaultRegions != null && defaultRegions.Count >= 1) - home = defaultRegions[0]; + avatars = doc.GetElementsByTagName("Avatar"); - if (gridUserService != null && home != null) - gridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); - else - m_log.WarnFormat("[RADMIN]: Unable to set home for account {0} {1}.", - firstName, lastName); - } - else - m_log.WarnFormat("[RADMIN]: Unable to retrieve home region for account {0} {1}.", - firstName, lastName); + // The document may contain multiple avatars - if (inventoryService != null) + foreach (XmlElement avatar in avatars) { - success = inventoryService.CreateUserInventory(account.PrincipalID); - if (!success) - m_log.WarnFormat("[RADMIN]: Unable to create inventory for account {0} {1}.", - firstName, lastName); - } + m_log.DebugFormat("[RADMIN]: Loading appearance for {0}, gender = {1}", + GetStringAttribute(avatar,"name","?"), GetStringAttribute(avatar,"gender","?")); - m_log.InfoFormat("[RADMIN]: Account {0} {1} created successfully", firstName, lastName); - return account; - } else { - m_log.ErrorFormat("[RADMIN]: Account creation failed for account {0} {1}", firstName, lastName); - } - } - else - { - m_log.ErrorFormat("[RADMIN]: A user with the name {0} {1} already exists!", firstName, lastName); - } - return null; - } + // Create the user identified by the avatar entry - /// - /// Change password - /// - /// - /// - /// - private bool ChangeUserPassword(string firstName, string lastName, string password) - { - Scene scene = m_application.SceneManager.CurrentOrFirstScene; - IUserAccountService userAccountService = scene.UserAccountService; - IAuthenticationService authenticationService = scene.AuthenticationService; + try + { + // Only the name value is mandatory + name = GetStringAttribute(avatar,"name",name); + email = GetStringAttribute(avatar,"email",email); + regionXLocation = GetUnsignedAttribute(avatar,"regx",regionXLocation); + regionYLocation = GetUnsignedAttribute(avatar,"regy",regionYLocation); + password = GetStringAttribute(avatar,"password",password); - UserAccount account = userAccountService.GetUserAccount(UUID.Zero, firstName, lastName); - if (null != account) - { - bool success = false; - if (authenticationService != null) - success = authenticationService.SetPassword(account.PrincipalID, password); + string[] names = name.Split(); + UUID scopeID = scene.RegionInfo.ScopeID; + UserAccount account = scene.UserAccountService.GetUserAccount(scopeID, names[0], names[1]); + if (null == account) + { + account = CreateUser(scopeID, names[0], names[1], password, email); + if (null == account) + { + m_log.ErrorFormat("[RADMIN]: Avatar {0} {1} was not created", names[0], names[1]); + return false; + } + } - if (!success) - { - m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", - firstName, lastName); - return false; - } - return true; - } - else - { - m_log.ErrorFormat("[RADMIN]: No such user"); - return false; - } - } + // Set home position - private bool LoadHeightmap(string file, UUID regionID) - { - m_log.InfoFormat("[RADMIN]: Terrain Loading: {0}", file); + GridRegion home = scene.GridService.GetRegionByPosition(scopeID, + (int)(regionXLocation * Constants.RegionSize), (int)(regionYLocation * Constants.RegionSize)); + if (null == home) { + m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", names[0], names[1]); + } else { + scene.GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); + m_log.DebugFormat("[RADMIN]: Set home region {0} for updated user account {1} {2}", home.RegionID, names[0], names[1]); + } - Scene region = null; + ID = account.PrincipalID; - if (!m_application.SceneManager.TryGetScene(regionID, out region)) - { - m_log.InfoFormat("[RADMIN]: unable to get a scene with that name: {0}", regionID.ToString()); - return false; - } + m_log.DebugFormat("[RADMIN]: User {0}[{1}] created or retrieved", name, ID); + include = true; + } + catch (Exception e) + { + m_log.DebugFormat("[RADMIN]: Error creating user {0} : {1}", name, e.Message); + include = false; + } - ITerrainModule terrainModule = region.RequestModuleInterface(); - if (null == terrainModule) throw new Exception("terrain module not available"); - if (Uri.IsWellFormedUriString(file, UriKind.Absolute)) - { - m_log.Info("[RADMIN]: Terrain path is URL"); - Uri result; - if (Uri.TryCreate(file, UriKind.RelativeOrAbsolute, out result)) + // OK, User has been created OK, now we can install the inventory. + // First retrieve the current inventory (the user may already exist) + // Note that althought he inventory is retrieved, the hierarchy has + // not been interpreted at all. + + if (include) + { + // Setup for appearance processing + avatarAppearance = scene.AvatarService.GetAppearance(ID); + if (avatarAppearance == null) + avatarAppearance = new AvatarAppearance(); + + AvatarWearable[] wearables = avatarAppearance.Wearables; + for (int i=0; i folders = inventoryService.GetFolderContent(ID, clothingFolder.ID).Folders; + extraFolder = null; + + foreach (InventoryFolderBase folder in folders) + { + if (folder.Name == outfitName) + { + extraFolder = folder; + break; + } + } + + // Otherwise, we must create the folder. + if (extraFolder == null) + { + m_log.DebugFormat("[RADMIN]: Creating outfit folder {0} for {1}", outfitName, name); + extraFolder = new InventoryFolderBase(); + extraFolder.ID = UUID.Random(); + extraFolder.Name = outfitName; + extraFolder.Owner = ID; + extraFolder.Type = (short)AssetType.Clothing; + extraFolder.Version = 1; + extraFolder.ParentID = clothingFolder.ID; + inventoryService.AddFolder(extraFolder); + m_log.DebugFormat("[RADMIN]: Adding outfile folder {0} to folder {1}", extraFolder.ID, clothingFolder.ID); + } + + // Now get the pieces that make up the outfit + XmlNodeList items = outfit.GetElementsByTagName("Item"); + + foreach (XmlElement item in items) + { + assetid = UUID.Zero; + XmlNodeList children = item.ChildNodes; + foreach (XmlNode child in children) + { + switch (child.Name) + { + case "Permissions" : + m_log.DebugFormat("[RADMIN]: Permissions specified"); + perms = child; + break; + case "Asset" : + assetid = new UUID(child.InnerText); + break; + } + } + + InventoryItemBase inventoryItem = null; + + // Check if asset is in inventory already + inventoryItem = null; + List inventoryItems = inventoryService.GetFolderContent(ID, extraFolder.ID).Items; + + foreach (InventoryItemBase listItem in inventoryItems) + { + if (listItem.AssetID == assetid) + { + inventoryItem = listItem; + break; + } + } + + // Create inventory item + if (inventoryItem == null) + { + inventoryItem = new InventoryItemBase(UUID.Random(), ID); + inventoryItem.Name = GetStringAttribute(item,"name",""); + inventoryItem.Description = GetStringAttribute(item,"desc",""); + inventoryItem.InvType = GetIntegerAttribute(item,"invtype",-1); + inventoryItem.CreatorId = GetStringAttribute(item,"creatorid",""); + inventoryItem.CreatorIdAsUuid = (UUID)GetStringAttribute(item,"creatoruuid",""); + inventoryItem.CreatorData = GetStringAttribute(item, "creatordata", ""); + inventoryItem.NextPermissions = GetUnsignedAttribute(perms, "next", 0x7fffffff); + inventoryItem.CurrentPermissions = GetUnsignedAttribute(perms,"current",0x7fffffff); + inventoryItem.BasePermissions = GetUnsignedAttribute(perms,"base",0x7fffffff); + inventoryItem.EveryOnePermissions = GetUnsignedAttribute(perms,"everyone",0x7fffffff); + inventoryItem.GroupPermissions = GetUnsignedAttribute(perms,"group",0x7fffffff); + inventoryItem.AssetType = GetIntegerAttribute(item,"assettype",-1); + inventoryItem.AssetID = assetid; // associated asset + inventoryItem.GroupID = (UUID)GetStringAttribute(item,"groupid",""); + inventoryItem.GroupOwned = (GetStringAttribute(item,"groupowned","false") == "true"); + inventoryItem.SalePrice = GetIntegerAttribute(item,"saleprice",0); + inventoryItem.SaleType = (byte)GetIntegerAttribute(item,"saletype",0); + inventoryItem.Flags = GetUnsignedAttribute(item,"flags",0); + inventoryItem.CreationDate = GetIntegerAttribute(item,"creationdate",Util.UnixTimeSinceEpoch()); + inventoryItem.Folder = extraFolder.ID; // Parent folder + + m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(inventoryItem); + m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", inventoryItem.ID, extraFolder.ID); + } + + // Attach item, if attachpoint is specified + int attachpoint = GetIntegerAttribute(item,"attachpoint",0); + if (attachpoint != 0) + { + avatarAppearance.SetAttachment(attachpoint, inventoryItem.ID, inventoryItem.AssetID); + m_log.DebugFormat("[RADMIN]: Attached {0}", inventoryItem.ID); + } + + // Record whether or not the item is to be initially worn + try + { + if (select && (GetStringAttribute(item, "wear", "false") == "true")) + { + avatarAppearance.Wearables[inventoryItem.Flags].Wear(inventoryItem.ID, inventoryItem.AssetID); + } + } + catch (Exception e) + { + m_log.WarnFormat("[RADMIN]: Error wearing item {0} : {1}", inventoryItem.ID, e.Message); + } + } // foreach item in outfit + m_log.DebugFormat("[RADMIN]: Outfit {0} load completed", outfitName); + } // foreach outfit + m_log.DebugFormat("[RADMIN]: Inventory update complete for {0}", name); + scene.AvatarService.SetAppearance(ID, avatarAppearance); + } + catch (Exception e) + { + m_log.WarnFormat("[RADMIN]: Inventory processing incomplete for user {0} : {1}", + name, e.Message); + } + } // End of include + } + m_log.DebugFormat("[RADMIN]: Default avatar loading complete"); + } + else { - // the url is valid - string fileType = file.Substring(file.LastIndexOf('/') + 1); - terrainModule.LoadFromStream(fileType, result); + m_log.DebugFormat("[RADMIN]: No default avatar information available"); + return false; } } - else + catch (Exception e) { - terrainModule.LoadFromFile(file); + m_log.WarnFormat("[RADMIN]: Exception whilst loading default avatars ; {0}", e.Message); + return false; } - m_log.Info("[RADMIN]: Load height maps request complete"); - return true; } } -- cgit v1.1