From 8e542cfa03f9368368a0f73fbcff0d54622b5588 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 6 Dec 2011 21:42:56 +0000 Subject: Stop accidentally setting up the UploadTexture caps handler with the same url for all users This meant that if a user exited the region, the UploadTexture handler would be effectively removed for everyone, causing subsequent failures. This hopefully resolves the recent UploadTexture LLSD problems This was a regression in 5640f2e (Thu Dec 1 23:24:15 2011 +0000) --- .../Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs | 2 -- OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs index e3bf8cf..b7ca703 100644 --- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs @@ -77,8 +77,6 @@ namespace OpenSim.Capabilities.Handlers { try { -// m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + m_regionName); - string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs index e61815f..45d6071 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs @@ -104,7 +104,7 @@ namespace OpenSim.Region.ClientStack.Linden "UploadBakedTexture", new RestStreamHandler( "POST", - "/CAPS/" + m_uploadBakedTexturePath, + "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath, new UploadBakedTextureHandler( caps, m_scene.AssetService, m_persistBakedTextures).UploadBakedTexture)); } -- cgit v1.1 From e6272b8d56dd7856faf374e7ac29460b4e74f1bb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Dec 2011 12:28:42 +0000 Subject: Stop also adding an ordinary http handler when we set up a poll http handler. It appears that this is entirely unnecessary since the poll http handlers are dealt with on a separate code path. --- OpenSim/Framework/Console/RemoteConsole.cs | 10 ++-------- OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 12 +++--------- .../Servers/HttpServer/Interfaces/IHttpServer.cs | 4 ++-- .../Linden/Caps/EventQueue/EventQueueGetModule.cs | 6 ------ .../Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | 17 ++++++----------- 5 files changed, 13 insertions(+), 36 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs index 07de27a..eabb62d 100644 --- a/OpenSim/Framework/Console/RemoteConsole.cs +++ b/OpenSim/Framework/Console/RemoteConsole.cs @@ -232,9 +232,8 @@ namespace OpenSim.Framework.Console string uri = "/ReadResponses/" + sessionID.ToString() + "/"; - m_Server.AddPollServiceHTTPHandler(uri, HandleHttpPoll, - new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, - sessionID)); + m_Server.AddPollServiceHTTPHandler( + uri, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, sessionID)); XmlDocument xmldoc = new XmlDocument(); XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, @@ -266,11 +265,6 @@ namespace OpenSim.Framework.Console return reply; } - private Hashtable HandleHttpPoll(Hashtable request) - { - return new Hashtable(); - } - private Hashtable HandleHttpCloseSession(Hashtable request) { DoExpire(); diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 6bffba5..a8ece79 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -227,21 +227,17 @@ namespace OpenSim.Framework.Servers.HttpServer return new List(m_HTTPHandlers.Keys); } - public bool AddPollServiceHTTPHandler(string methodName, GenericHTTPMethod handler, PollServiceEventArgs args) + public bool AddPollServiceHTTPHandler(string methodName, PollServiceEventArgs args) { - bool pollHandlerResult = false; lock (m_pollHandlers) { if (!m_pollHandlers.ContainsKey(methodName)) { - m_pollHandlers.Add(methodName,args); - pollHandlerResult = true; + m_pollHandlers.Add(methodName, args); + return true; } } - if (pollHandlerResult) - return AddHTTPHandler(methodName, handler); - return false; } @@ -1848,8 +1844,6 @@ namespace OpenSim.Framework.Servers.HttpServer { lock (m_pollHandlers) m_pollHandlers.Remove(path); - - RemoveHTTPHandler(httpMethod, path); } public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs index fd77984..db58f6f 100644 --- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs @@ -77,8 +77,8 @@ namespace OpenSim.Framework.Servers.HttpServer /// true if the handler was successfully registered, false if a handler with the same name already existed. /// bool AddHTTPHandler(string methodName, GenericHTTPMethod handler); - - bool AddPollServiceHTTPHandler(string methodName, GenericHTTPMethod handler, PollServiceEventArgs args); + + bool AddPollServiceHTTPHandler(string methodName, PollServiceEventArgs args); /// /// Adds a LLSD handler, yay. diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 9f27abc..8ba6f61 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -361,7 +361,6 @@ namespace OpenSim.Region.ClientStack.Linden // This will persist this beyond the expiry of the caps handlers MainServer.Instance.AddPollServiceHTTPHandler( capsBase + EventQueueGetUUID.ToString() + "/", - EventQueuePoll, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID)); Random rnd = new Random(Environment.TickCount); @@ -578,11 +577,6 @@ namespace OpenSim.Region.ClientStack.Linden // return responsedata; // } - public Hashtable EventQueuePoll(Hashtable request) - { - return new Hashtable(); - } - // public Hashtable EventQueuePath2(Hashtable request) // { // string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/",""); diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 7377ceb..67d99e0 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -90,11 +90,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp get { return null; } } - private Hashtable HandleHttpPoll(Hashtable request) - { - return new Hashtable(); - } - public string Name { get { return "UrlModule"; } @@ -171,9 +166,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp string uri = "/lslhttp/" + urlcode.ToString() + "/"; - m_HttpServer.AddPollServiceHTTPHandler(uri,HandleHttpPoll, - new PollServiceEventArgs(HttpRequestHandler,HasEvents, GetEvents, NoEvents, - urlcode)); + m_HttpServer.AddPollServiceHTTPHandler( + uri, + new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode)); engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); } @@ -213,9 +208,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp string uri = "/lslhttps/" + urlcode.ToString() + "/"; - m_HttpsServer.AddPollServiceHTTPHandler(uri,HandleHttpPoll, - new PollServiceEventArgs(HttpRequestHandler,HasEvents, GetEvents, NoEvents, - urlcode)); + m_HttpsServer.AddPollServiceHTTPHandler( + uri, + new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode)); engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); } -- cgit v1.1 From a8ed185c00c3c688ae939104cc0cc752a430c168 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Dec 2011 14:55:01 +0000 Subject: properly lock CapsHandlers.m_capsHandlers --- OpenSim/Capabilities/CapsHandlers.cs | 66 ++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 26 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Capabilities/CapsHandlers.cs b/OpenSim/Capabilities/CapsHandlers.cs index a0e9ebc..1709f46 100644 --- a/OpenSim/Capabilities/CapsHandlers.cs +++ b/OpenSim/Capabilities/CapsHandlers.cs @@ -51,11 +51,10 @@ namespace OpenSim.Framework.Capabilities /// supplied BaseHttpServer. /// /// base HTTP server - /// host name of the HTTP - /// server + /// host name of the HTTP server /// HTTP port public CapsHandlers(BaseHttpServer httpListener, string httpListenerHostname, uint httpListenerPort) - : this (httpListener,httpListenerHostname,httpListenerPort, false) + : this(httpListener,httpListenerHostname,httpListenerPort, false) { } @@ -88,44 +87,52 @@ namespace OpenSim.Framework.Capabilities /// handler to be removed public void Remove(string capsName) { - m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path); - m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path); - m_capsHandlers.Remove(capsName); + lock (m_capsHandlers) + { + m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path); + m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path); + m_capsHandlers.Remove(capsName); + } } public bool ContainsCap(string cap) { - return m_capsHandlers.ContainsKey(cap); + lock (m_capsHandlers) + return m_capsHandlers.ContainsKey(cap); } /// /// The indexer allows us to treat the CapsHandlers object /// in an intuitive dictionary like way. /// - /// + /// /// The indexer will throw an exception when you try to /// retrieve a cap handler for a cap that is not contained in /// CapsHandlers. - /// + /// public IRequestHandler this[string idx] { get { - return m_capsHandlers[idx]; + lock (m_capsHandlers) + return m_capsHandlers[idx]; } set { - if (m_capsHandlers.ContainsKey(idx)) + lock (m_capsHandlers) { - m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[idx].Path); - m_capsHandlers.Remove(idx); + if (m_capsHandlers.ContainsKey(idx)) + { + m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[idx].Path); + m_capsHandlers.Remove(idx); + } + + if (null == value) return; + + m_capsHandlers[idx] = value; + m_httpListener.AddStreamHandler(value); } - - if (null == value) return; - - m_capsHandlers[idx] = value; - m_httpListener.AddStreamHandler(value); } } @@ -137,9 +144,12 @@ namespace OpenSim.Framework.Capabilities { get { - string[] __keys = new string[m_capsHandlers.Keys.Count]; - m_capsHandlers.Keys.CopyTo(__keys, 0); - return __keys; + lock (m_capsHandlers) + { + string[] __keys = new string[m_capsHandlers.Keys.Count]; + m_capsHandlers.Keys.CopyTo(__keys, 0); + return __keys; + } } } @@ -157,15 +167,19 @@ namespace OpenSim.Framework.Capabilities protocol = "https://"; string baseUrl = protocol + m_httpListenerHostName + ":" + m_httpListenerPort.ToString(); - foreach (string capsName in m_capsHandlers.Keys) + + lock (m_capsHandlers) { - if (excludeSeed && "SEED" == capsName) - continue; + foreach (string capsName in m_capsHandlers.Keys) + { + if (excludeSeed && "SEED" == capsName) + continue; - caps[capsName] = baseUrl + m_capsHandlers[capsName].Path; + caps[capsName] = baseUrl + m_capsHandlers[capsName].Path; + } } return caps; } } -} +} \ No newline at end of file -- cgit v1.1 From 33c6067098a452eec36721b833668f9662b99100 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Wed, 7 Dec 2011 11:21:50 -0500 Subject: Trigger a Jenkins build --- OpenSim/Region/Application/OpenSimBase.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index bae44ee..55ba18a 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -62,6 +62,7 @@ namespace OpenSim // These are the names of the plugin-points extended by this // class during system startup. + // private const string PLUGIN_ASSET_CACHE = "/OpenSim/AssetCache"; private const string PLUGIN_ASSET_SERVER_CLIENT = "/OpenSim/AssetClient"; -- cgit v1.1 From 415b7b7ec4be9f87e7d5b65000e092d3372a4391 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Dec 2011 17:31:57 +0000 Subject: Implement XMLRPCAdmin command admin_teleport_agent. This allows someone with access to this command on the XMLRPCAdmin interface to teleport an avatar to an arbitrary region and/or position. --- .../RemoteController/RemoteAdminPlugin.cs | 113 +++++++++++++++++++++ OpenSim/Framework/IScene.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +- OpenSim/Region/Framework/Scenes/SceneBase.cs | 6 ++ OpenSim/Region/Framework/Scenes/SceneManager.cs | 33 ++++++ 5 files changed, 157 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index a634f1c..1b289a6 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -134,16 +134,22 @@ namespace OpenSim.ApplicationPlugins.RemoteController availableMethods["admin_restart"] = XmlRpcRestartMethod; availableMethods["admin_load_heightmap"] = XmlRpcLoadHeightmapMethod; availableMethods["admin_save_heightmap"] = XmlRpcSaveHeightmapMethod; + + // Agent management + availableMethods["admin_teleport_agent"] = XmlRpcTeleportAgentMethod; + // User management availableMethods["admin_create_user"] = XmlRpcCreateUserMethod; availableMethods["admin_create_user_email"] = XmlRpcCreateUserMethod; availableMethods["admin_exists_user"] = XmlRpcUserExistsMethod; availableMethods["admin_update_user"] = XmlRpcUpdateUserAccountMethod; + // Region state management availableMethods["admin_load_xml"] = XmlRpcLoadXMLMethod; availableMethods["admin_save_xml"] = XmlRpcSaveXMLMethod; availableMethods["admin_load_oar"] = XmlRpcLoadOARMethod; availableMethods["admin_save_oar"] = XmlRpcSaveOARMethod; + // Estate access list management availableMethods["admin_acl_clear"] = XmlRpcAccessListClear; availableMethods["admin_acl_add"] = XmlRpcAccessListAdd; @@ -2965,6 +2971,112 @@ namespace OpenSim.ApplicationPlugins.RemoteController return response; } + public XmlRpcResponse XmlRpcTeleportAgentMethod(XmlRpcRequest request, IPEndPoint remoteClient) + { + 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()); + + UUID agentId; + string regionName = null; + Vector3 pos, lookAt; + bool agentSpecified = false; + ScenePresence sp = null; + + 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 (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"]; + + 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); + + 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"); + } + + 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); + + sp.Scene.RequestTeleportLocation( + sp.ControllingClient, regionName, pos, lookAt, (uint)Constants.TeleportFlags.ViaLocation); + } + catch (Exception e) + { + m_log.ErrorFormat("[RADMIN]: admin_teleport_agent exception: {0}{1}", e.Message, e.StackTrace); + + responseData["success"] = false; + responseData["error"] = e.Message; + } + finally + { + response.Value = responseData; + } + + return response; + } + + /// + /// 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 + return val; + } + else + { + return defaultVal; + } + } + private static void CheckStringParameters(XmlRpcRequest request, string[] param) { Hashtable requestData = (Hashtable) request.Params[0]; @@ -3144,6 +3256,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController return false; } } + private bool LoadHeightmap(string file, UUID regionID) { m_log.InfoFormat("[RADMIN]: Terrain Loading: {0}", file); diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index 76b731f..7b0fe37 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs @@ -90,9 +90,9 @@ namespace OpenSim.Framework /// /// Is the agent denoted by the given agentID a child presence in this scene? /// - /// + /// /// Used by ClientView when a 'kick everyone' or 'estate message' occurs - /// + /// /// AvatarID to lookup /// true if the presence is a child agent, false if the presence is a root exception /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 3ac6327..604f035 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4206,7 +4206,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void ForEachRootScenePresence(Action action) { - if(m_sceneGraph != null) + if (m_sceneGraph != null) { m_sceneGraph.ForEachAvatar(action); } @@ -4286,9 +4286,9 @@ namespace OpenSim.Region.Framework.Scenes return m_sceneGraph.GetGroupByPrim(localID); } - public override bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar) + public override bool TryGetScenePresence(UUID agentID, out ScenePresence sp) { - return m_sceneGraph.TryGetScenePresence(avatarId, out avatar); + return m_sceneGraph.TryGetScenePresence(agentID, out sp); } public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 0336fe5..a633c72 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -191,6 +191,12 @@ namespace OpenSim.Region.Framework.Scenes return false; } + /// + /// Try to get a scene presence from the scene + /// + /// + /// null if there is no scene presence with the given agent id + /// true if there was a scene presence with the given id, false otherwise. public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence); #endregion diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index 82458e2..0491205 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs @@ -545,6 +545,23 @@ namespace OpenSim.Region.Framework.Scenes return false; } + public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar) + { + lock (m_localScenes) + { + foreach (Scene scene in m_localScenes) + { + avatar = scene.GetScenePresence(avatarId); + + if (avatar != null && !avatar.IsChildAgent) + return true; + } + } + + avatar = null; + return false; + } + public bool TryGetAvatarsScene(UUID avatarId, out Scene scene) { ScenePresence avatar = null; @@ -590,6 +607,22 @@ namespace OpenSim.Region.Framework.Scenes return false; } + public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp) + { + lock (m_localScenes) + { + foreach (Scene scene in m_localScenes) + { + sp = scene.GetScenePresence(firstName, lastName); + if (sp != null && !sp.IsChildAgent) + return true; + } + } + + sp = null; + return false; + } + public void ForEachScene(Action action) { lock (m_localScenes) -- cgit v1.1 From 3d95015686cafd7e5510d649fc58328c9565768b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Dec 2011 18:43:48 +0000 Subject: On an Exception in Scene.RemoveClient(), always remove the client (and SP) structure so that logout on unexpired packets isn't retriggered, causing the same exception --- OpenSim/Region/Framework/Scenes/Scene.cs | 47 +++++++++++++++++++------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 604f035..87af206 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3104,29 +3104,38 @@ namespace OpenSim.Region.Framework.Scenes // Avatar is already disposed :/ } - m_eventManager.TriggerOnRemovePresence(agentID); - - if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) - AttachmentsModule.SaveChangedAttachments(avatar); - - ForEachClient( - delegate(IClientAPI client) + try + { + m_eventManager.TriggerOnRemovePresence(agentID); + + if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) + AttachmentsModule.SaveChangedAttachments(avatar); + + ForEachClient( + delegate(IClientAPI client) + { + //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway + try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } + catch (NullReferenceException) { } + }); + + IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); + if (agentTransactions != null) { - //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } - catch (NullReferenceException) { } - }); - - IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); - if (agentTransactions != null) + agentTransactions.RemoveAgentAssetTransactions(agentID); + } + } + finally { - agentTransactions.RemoveAgentAssetTransactions(agentID); + // Always clean these structures up so that any failure above doesn't cause them to remain in the + // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering + // the same cleanup exception continually. + // TODO: This should probably extend to the whole method, but we don't want to also catch the NRE + // since this would hide the underlying failure and other associated problems. + m_sceneGraph.RemoveScenePresence(agentID); + m_clientManager.Remove(agentID); } - // Remove the avatar from the scene - m_sceneGraph.RemoveScenePresence(agentID); - m_clientManager.Remove(agentID); - try { avatar.Close(); -- cgit v1.1 From eda770e978c09c756d15ba62dbbf6ee34a61b2f5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Dec 2011 21:15:55 +0000 Subject: Remove unused SceneManager.TryGetAvatarsScene() It makes far more sense anyway to use TryGetRootScenePresence().Scene, in common with the rest of the code This method could also return any scene for child or root agents, depending in which order the scenes happened to lie in the list --- OpenSim/Region/Framework/Scenes/SceneManager.cs | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index 0491205..d73a959 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs @@ -562,26 +562,6 @@ namespace OpenSim.Region.Framework.Scenes return false; } - public bool TryGetAvatarsScene(UUID avatarId, out Scene scene) - { - ScenePresence avatar = null; - - lock (m_localScenes) - { - foreach (Scene mScene in m_localScenes) - { - if (mScene.TryGetScenePresence(avatarId, out avatar)) - { - scene = mScene; - return true; - } - } - } - - scene = null; - return false; - } - public void CloseScene(Scene scene) { lock (m_localScenes) -- cgit v1.1 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') 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 From 2b4de8f8817e823221aad6a753fe31b1bbb73c58 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Dec 2011 22:40:23 +0000 Subject: Have admin_load_heighmap and admin_save_heightmap xmlrpcadmin methods return success = true on success rather than false --- OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 1da7c35..8a1718f 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -339,7 +339,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController LoadHeightmap(file, regionID); - responseData["success"] = false; + responseData["success"] = true; m_log.Info("[RADMIN]: Load height maps request complete"); } @@ -371,7 +371,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController terrainModule.SaveToFile(file); - responseData["success"] = false; + responseData["success"] = true; m_log.Info("[RADMIN]: Save height maps request complete"); } -- cgit v1.1 From dae58e093700b3afaa3e09ccbe1f52a329316303 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Dec 2011 22:42:05 +0000 Subject: Remove warning in admin_save_oar xmlrpc method where noassets == true was comparing against an object rather than a string --- OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 8a1718f..64b2a52 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -1464,7 +1464,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController options["profile"] = (string)requestData["profile"]; } - if (requestData["noassets"] == "true") + if (requestData["noassets"].ToString() == "true") { options["noassets"] = (string)requestData["noassets"] ; } -- cgit v1.1 From 603ad905e19f9ebaab39a1b926cc41093a224151 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 8 Dec 2011 03:53:09 +0000 Subject: Adapt to justincc's remote admin refactor --- .../RemoteController/RemoteAdminPlugin.cs | 3970 +++++++++----------- 1 file changed, 1810 insertions(+), 2160 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 256a971..1cc0da2 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -124,38 +124,38 @@ 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_dialog"] = XmlRpcDialogMethod; - 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_dialog"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcDialogMethod); + 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"); @@ -165,7 +165,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. @@ -199,34 +199,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"]); @@ -237,6 +270,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (!m_application.SceneManager.TryGetScene(regionID, out rebootedScene)) throw new Exception("region not found"); + responseData["rebooting"] = true; + string message; List times = new List(); @@ -275,78 +310,51 @@ namespace OpenSim.ApplicationPlugins.RemoteController notice = false; } - responseData["rebooting"] = true; - IRestartModule restartModule = rebootedScene.RequestModuleInterface(); if (restartModule != null) { restartModule.ScheduleRestart(UUID.Zero, message, times.ToArray(), notice); 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); - - responseData["accepted"] = true; - responseData["success"] = true; - response.Value = responseData; + string message = (string) requestData["message"]; + m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message); - 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 XmlRpcDialogMethod(XmlRpcRequest request, IPEndPoint remoteClient) + + public void XmlRpcDialogMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + Hashtable responseData = (Hashtable)response.Value; m_log.Info("[RADMIN]: Dialog request started"); @@ -354,19 +362,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController { Hashtable requestData = (Hashtable)request.Params[0]; - CheckStringParameters(request, new string[] { "password", "from", "message" }); - - if (m_requiredPassword != String.Empty && - (!requestData.Contains("password") || (string)requestData["password"] != m_requiredPassword)) - throw new Exception("wrong password"); - string message = (string)requestData["message"]; string fromuuid = (string)requestData["from"]; m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message); responseData["accepted"] = true; responseData["success"] = true; - response.Value = responseData; m_application.SceneManager.ForEachScene( delegate(Scene scene) @@ -384,197 +385,139 @@ namespace OpenSim.ApplicationPlugins.RemoteController responseData["accepted"] = false; responseData["success"] = false; responseData["error"] = e.Message; - response.Value = responseData; } 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()); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - CheckStringParameters(request, new string[] { "password", "filename", "regionid" }); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - - string file = (string)requestData["filename"]; - UUID regionID = (UUID)(string)requestData["regionid"]; - m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file); - - responseData["accepted"] = true; +// m_log.DebugFormat("[RADMIN]: Save Terrain: XmlRpc {0}", request.ToString()); - Scene region = null; + CheckStringParameters(requestData, responseData, new string[] { "filename", "regionid" }); - if (!m_application.SceneManager.TryGetScene(regionID, out region)) - throw new Exception("1: unable to get a scene with that name"); + string file = (string)requestData["filename"]; + UUID regionID = (UUID)(string)requestData["regionid"]; + m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file); - ITerrainModule terrainModule = region.RequestModuleInterface(); - if (null == terrainModule) throw new Exception("terrain module not available"); + responseData["accepted"] = true; - 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(); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - try - { - Hashtable requestData = (Hashtable) request.Params[0]; + responseData["accepted"] = true; + response.Value = responseData; - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + int timeout = 2000; + string message; - responseData["accepted"] = true; - response.Value = responseData; + if (requestData.ContainsKey("shutdown") + && ((string) requestData["shutdown"] == "delayed") + && requestData.ContainsKey("milliseconds")) + { + timeout = Int32.Parse(requestData["milliseconds"].ToString()); - int timeout = 2000; - string message; + 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."; + } - if (requestData.ContainsKey("shutdown") - && ((string) requestData["shutdown"] == "delayed") - && requestData.ContainsKey("milliseconds")) - { - timeout = Int32.Parse(requestData["milliseconds"].ToString()); + if (requestData.ContainsKey("noticetype") + && ((string) requestData["noticetype"] == "dialog")) + { + m_application.SceneManager.ForEachScene( - message - = "Region is going down in " + ((int) (timeout/1000)).ToString() - + " second(s). Please save what you are doing and log out."; - } - else + delegate(Scene scene) { - message = "Region is going down now."; - } - - if (requestData.ContainsKey("noticetype") - && ((string) requestData["noticetype"] == "dialog")) + IDialogModule dialogModule = scene.RequestModuleInterface(); + if (dialogModule != null) + dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message); + }); + } + else + { + if (!requestData.ContainsKey("noticetype") + || ((string)requestData["noticetype"] != "none")) { m_application.SceneManager.ForEachScene( delegate(Scene scene) - { - IDialogModule dialogModule = scene.RequestModuleInterface(); - if (dialogModule != null) - dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message); - }); - } - else - { - if (!requestData.ContainsKey("noticetype") - || ((string)requestData["noticetype"] != "none")) { - 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(); + IDialogModule dialogModule = scene.RequestModuleInterface(); + if (dialogModule != null) + dialogModule.SendGeneralAlert(message); + }); } - - responseData["success"] = true; } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: Shutdown: failed: {0} {1}", e.Message, e.StackTrace); - responseData["accepted"] = false; - responseData["error"] = e.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) @@ -645,12 +588,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) { @@ -658,255 +601,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(); + + 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(); - IScene newScene; - m_application.CreateRegion(region, out newScene); + 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; } } @@ -936,46 +859,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; } } @@ -1007,69 +912,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)); - - m_application.CloseRegion(scene); - - 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 + responseData["success"] = true; + responseData["region_id"] = regionID; - 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)); + response.Value = responseData; + } + else if ( + requestData.ContainsKey("region_name") + && !String.IsNullOrEmpty((string) requestData["region_name"])) + { + // Region specified by name - 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; } } @@ -1105,70 +993,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; } } @@ -1210,28 +1081,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"]; @@ -1258,9 +1125,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); } @@ -1272,22 +1142,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; } } @@ -1323,62 +1187,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()); - - string firstName = (string) requestData["user_firstname"]; - string lastName = (string) requestData["user_lastname"]; + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - responseData["user_firstname"] = firstName; - responseData["user_lastname"] = lastName; + // check completeness + CheckStringParameters(requestData, responseData, new string[] {"user_firstname", "user_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; } /// @@ -1423,27 +1268,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"]; @@ -1529,1874 +1370,1683 @@ 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; - } - } + CheckStringParameters(requestData, responseData, new string[] {"filename"}); - // Has an explicit model been specified? + 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 (requestData.Contains("model") && (String.IsNullOrEmpty((string)requestData["gender"]))) - { - model = (string)requestData["model"]; - } + if ((string)requestData["merge"] == "true") + { + mergeOar = true; + } + if ((string)requestData["skip-assets"] == "true") + { + skipAssets = true; + } - // No appearance attributes were set + IRegionArchiverModule archiver = scene.RequestModuleInterface(); + if (archiver != null) + archiver.DearchiveRegion(filename, mergeOar, skipAssets, Guid.Empty); + else + throw new Exception("Archiver module not present for scene"); - if (String.IsNullOrEmpty(model)) - { - m_log.DebugFormat("[RADMIN]: Appearance update not requested"); - return; - } + responseData["loaded"] = true; + } + catch (Exception e) + { + responseData["loaded"] = false; - m_log.DebugFormat("[RADMIN]: Setting appearance for avatar {0}, using model <{1}>", userid, model); + throw e; + } - 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; - } - - Scene scene = m_application.SceneManager.CurrentOrFirstScene; - UUID scopeID = scene.RegionInfo.ScopeID; - UserAccount modelProfile = scene.UserAccountService.GetUserAccount(scopeID, modelSpecifiers[0], modelSpecifiers[1]); - - 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) + /// 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.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; + 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(); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + } + else throw new Exception("neither region_name nor region_uuid given"); - foreach (AvatarAttachment attachment in attachments) - { - int attachpoint = attachment.AttachPoint; - UUID itemID = attachment.ItemID; + responseData["switched"] = true; - if (itemID != UUID.Zero) - { - // Get inventory item and copy it - InventoryItemBase item = new InventoryItemBase(itemID, source); - item = inventoryService.GetItem(item); + string xml_version = "1"; + if (requestData.Contains("xml_version")) + { + xml_version = (string) requestData["xml_version"]; + } - if (item != null) + switch (xml_version) { - 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); + case "1": + m_application.SceneManager.LoadCurrentSceneFromXml(filename, true, new Vector3(0, 0, 0)); + break; - m_application.SceneManager.CurrentOrFirstScene.AddInventoryItem(destinationItem); - m_log.DebugFormat("[RADMIN]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID); + case "2": + m_application.SceneManager.LoadCurrentSceneFromXml2(filename); + break; - // 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); + default: + throw new Exception(String.Format("unknown Xml{0} format", xml_version)); } + + responseData["loaded"] = true; + } + catch (Exception e) + { + responseData["loaded"] = false; + responseData["switched"] = false; + + throw e; } + + m_log.Info("[RADMIN]: Load 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 XmlRpcSaveXMLMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; - - InventoryFolderBase sourceFolder = inventoryService.GetFolderForType(source, assetType); - InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, assetType); + m_log.Info("[RADMIN]: Received Save XML Administrator Request"); - if (sourceFolder == null || destinationFolder == null) - throw new Exception("Cannot locate folder(s)"); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - // Missing source folder? This should *never* be the case - if (sourceFolder.Type != (short)assetType) + try { - 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); - } + CheckStringParameters(requestData, responseData, new string[] {"filename"}); - // 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) + string filename = (string) requestData["filename"]; + if (requestData.Contains("region_uuid")) { - destinationFolder.Name = "Clothing"; + 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 + else if (requestData.Contains("region_name")) { - destinationFolder.Name = "Body Parts"; + 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); } - 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); - } - - InventoryFolderBase extraFolder; - List folders = inventoryService.GetFolderContent(source, sourceFolder.ID).Folders; - - 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); + else throw new Exception("neither region_name nor region_uuid given"); - m_log.DebugFormat("[RADMIN]: Added folder {0} to folder {1}", extraFolder.ID, sourceFolder.ID); + responseData["switched"] = true; - List items = inventoryService.GetFolderContent(source, folder.ID).Items; + string xml_version = "1"; + if (requestData.Contains("xml_version")) + { + xml_version = (string) requestData["xml_version"]; + } - foreach (InventoryItemBase item in items) + switch (xml_version) { - 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); + case "1": + m_application.SceneManager.SaveCurrentSceneToXml(filename); + break; - 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); + case "2": + m_application.SceneManager.SaveCurrentSceneToXml2(filename); + break; - // 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); - } + 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"); } - /// - /// Apply next owner permissions. - /// - private void ApplyNextOwnerPermissions(InventoryItemBase item) + private void XmlRpcRegionQueryMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) { - if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) + m_log.Info("[RADMIN]: Received Query XML Administrator 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; - } + 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)); - /// - /// 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) + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + } + else { - return false; + throw new Exception("neither region_name nor region_uuid given"); } - m_log.DebugFormat("[RADMIN]: Creating default avatar entries"); + Scene scene = m_application.SceneManager.CurrentScene; - m_defaultAvatarsLoaded = true; + int flags; + string text; + int health = scene.GetHealth(out flags, out text); + responseData["health"] = health; + responseData["flags"] = flags; + responseData["message"] = text; - // Load processing starts here... + m_log.Info("[RADMIN]: Query XML Administrator Request complete"); + } - try - { - string defaultAppearanceFileName = null; + private void XmlRpcConsoleCommandMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Command XML Administrator Request"); - //m_config may be null if RemoteAdmin configuration secition is missing or disabled in OpenSim.ini - if (m_config != null) - { - defaultAppearanceFileName = m_config.GetString("default_appearance", "default_appearance.xml"); - } + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - if (File.Exists(defaultAppearanceFileName)) - { - 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; + CheckStringParameters(requestData, responseData, new string[] {"command"}); - Scene scene = m_application.SceneManager.CurrentOrFirstScene; - IInventoryService inventoryService = scene.InventoryService; - IAssetService assetService = scene.AssetService; + MainConsole.Instance.RunCommand(requestData["command"].ToString()); - doc.LoadXml(File.ReadAllText(defaultAppearanceFileName)); + m_log.Info("[RADMIN]: Command XML Administrator Request complete"); + } - // Load up any included assets. Duplicates will be ignored - assets = doc.GetElementsByTagName("RequiredAsset"); - foreach (XmlNode assetNode in assets) - { - 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); - } + private void XmlRpcAccessListClear(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Access List Clear Request"); - avatars = doc.GetElementsByTagName("Avatar"); + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; - // The document may contain multiple avatars + responseData["success"] = true; - foreach (XmlElement avatar in avatars) + 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"); + + Scene scene = m_application.SceneManager.CurrentScene; + scene.RegionInfo.EstateSettings.EstateAccess = new UUID[]{}; + + if (scene.RegionInfo.Persistent) + scene.RegionInfo.EstateSettings.Save(); + + m_log.Info("[RADMIN]: Access List Clear Request complete"); + } + + 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")) + { + 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"); + } + + 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) + { + string[] parts = name.Split(); + UserAccount account = userService.GetUserAccount(scopeID, parts[0], parts[1]); + if (account != null) { - m_log.DebugFormat("[RADMIN]: Loading appearance for {0}, gender = {1}", - GetStringAttribute(avatar,"name","?"), GetStringAttribute(avatar,"gender","?")); + 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 (!accessControlList.Contains(uuid)) + { + accessControlList.Add(uuid); + addedUsers++; + } + } + scene.RegionInfo.EstateSettings.EstateAccess = accessControlList.ToArray(); + if (scene.RegionInfo.Persistent) + scene.RegionInfo.EstateSettings.Save(); + } - // 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 - - 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); - } + 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); - // 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 - { - m_log.DebugFormat("[RADMIN]: No default avatar information available"); - return false; - } - } - catch (Exception e) - { - m_log.WarnFormat("[RADMIN]: Exception whilst loading default avatars ; {0}", e.Message); - return false; - } + sp.Scene.RequestTeleportLocation( + sp.ControllingClient, regionName, pos, lookAt, (uint)Constants.TeleportFlags.ViaLocation); - return true; + // We have no way of telling the failure of the actual teleport + responseData["success"] = true; } /// - /// Load an OAR file into a region.. - /// - /// incoming XML RPC request + /// Parse a float with the given parameter name from a request data hash table. + /// /// - /// 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 - /// + /// Will throw an exception if parameter is not a float. + /// Will not throw if parameter is not found, passes back default value instead. /// - public XmlRpcResponse XmlRpcLoadOARMethod(XmlRpcRequest request, IPEndPoint remoteClient) + /// + /// + /// + /// + private static float ParseFloat(Hashtable requestData, string paramName, float defaultVal) { - m_log.Info("[RADMIN]: Received Load OAR Administrator Request"); + if (requestData.Contains(paramName)) + { + string rawVal = (string)requestData[paramName]; + float val; - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + 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; + } + } - lock (m_requestLock) + private static void CheckStringParameters(Hashtable requestData, Hashtable responseData, string[] param) + { + 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")) - { - 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")) + if (!requestData.Contains(parameter)) { - 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)); + responseData["accepted"] = false; + throw new Exception(String.Format("missing integer parameter {0}", parameter)); } - else throw new Exception("neither region_name nor region_uuid given"); - - Dictionary options = new Dictionary(); + } + } - //if (requestData.Contains("version")) - //{ - // options["version"] = (string)requestData["version"]; - //} - - 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 + 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()) { - throw new Exception("Archiver module not present for scene"); + case "true" : + case "t" : + case "1" : + return true; + case "false" : + case "f" : + case "0" : + return false; + default : + return defaultValue; } - - 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; + else + return defaultValue; + } - response.Value = responseData; - } + private int GetIntegerAttribute(XmlNode node, string attribute, int defaultValue) + { + try { return Convert.ToInt32(node.Attributes[attribute].Value); } catch{} + return defaultValue; + } - m_log.Info("[RADMIN]: Save OAR Administrator Request complete"); - return response; + private uint GetUnsignedAttribute(XmlNode node, string attribute, uint defaultValue) + { + try { return Convert.ToUInt32(node.Attributes[attribute].Value); } catch{} + return defaultValue; } - private void RemoteAdminOarSaveCompleted(Guid uuid, string name) + private string GetStringAttribute(XmlNode node, string attribute, string defaultValue) { - m_log.DebugFormat("[RADMIN]: File processing complete for {0}", name); - lock (m_saveOarLock) Monitor.Pulse(m_saveOarLock); + try { return node.Attributes[attribute].Value; } catch{} + return defaultValue; } - public XmlRpcResponse XmlRpcLoadXMLMethod(XmlRpcRequest request, IPEndPoint remoteClient) + public void Dispose() { - m_log.Info("[RADMIN]: Received Load XML Administrator Request"); + } - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + /// + /// 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; - 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()); + account.ServiceURLs = new Dictionary(); + account.ServiceURLs["HomeURI"] = string.Empty; + account.ServiceURLs["GatekeeperURI"] = string.Empty; + account.ServiceURLs["InventoryServerURI"] = string.Empty; + account.ServiceURLs["AssetServerURI"] = string.Empty; + } - string filename = (string) requestData["filename"]; - if (requestData.Contains("region_uuid")) + if (userAccountService.StoreUserAccount(account)) + { + bool success; + if (authenticationService != 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()); + success = authenticationService.SetPassword(account.PrincipalID, password); + if (!success) + m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", + firstName, lastName); } - else if (requestData.Contains("region_name")) + + GridRegion home = null; + if (gridService != 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)); + List defaultRegions = gridService.GetDefaultRegions(UUID.Zero); + if (defaultRegions != null && defaultRegions.Count >= 1) + home = defaultRegions[0]; - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); + 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 throw new Exception("neither region_name nor region_uuid given"); - - responseData["switched"] = true; + else + m_log.WarnFormat("[RADMIN]: Unable to retrieve home region for account {0} {1}.", + firstName, lastName); - string xml_version = "1"; - if (requestData.Contains("xml_version")) + if (inventoryService != null) { - xml_version = (string) requestData["xml_version"]; + success = inventoryService.CreateUserInventory(account.PrincipalID); + if (!success) + m_log.WarnFormat("[RADMIN]: Unable to create inventory for account {0} {1}.", + firstName, lastName); } - switch (xml_version) - { - case "1": - m_application.SceneManager.LoadCurrentSceneFromXml(filename, true, new Vector3(0, 0, 0)); - break; + 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; + } - case "2": - m_application.SceneManager.LoadCurrentSceneFromXml2(filename); - break; + /// + /// 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; - default: - throw new Exception(String.Format("unknown Xml{0} format", xml_version)); - } + UserAccount account = userAccountService.GetUserAccount(UUID.Zero, firstName, lastName); + if (null != account) + { + bool success = false; + if (authenticationService != null) + success = authenticationService.SetPassword(account.PrincipalID, password); - responseData["loaded"] = true; - response.Value = responseData; - } - catch (Exception e) + if (!success) { - 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.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", + firstName, lastName); + return false; } - - m_log.Info("[RADMIN]: Load XML Administrator Request complete"); - return response; + return true; + } + else + { + m_log.ErrorFormat("[RADMIN]: No such user"); + return false; } } - public XmlRpcResponse XmlRpcSaveXMLMethod(XmlRpcRequest request, IPEndPoint remoteClient) + private bool LoadHeightmap(string file, UUID regionID) { - m_log.Info("[RADMIN]: Received Save 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)) { - Hashtable requestData = (Hashtable) request.Params[0]; - - CheckStringParameters(request, new string[] { - "password", "filename"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + m_log.InfoFormat("[RADMIN]: unable to get a scene with that name: {0}", regionID.ToString()); + return false; + } - 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")) + 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"); - - responseData["switched"] = true; - - 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; - - response.Value = responseData; } - 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; + terrainModule.LoadFromFile(file); } - m_log.Info("[RADMIN]: Save XML Administrator Request complete"); - return response; - } - - public XmlRpcResponse XmlRpcRegionQueryMethod(XmlRpcRequest request, IPEndPoint remoteClient) - { - m_log.Info("[RADMIN]: Received Query XML Administrator Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + m_log.Info("[RADMIN]: Load height maps request complete"); - try - { - responseData["success"] = true; + return true; + } - Hashtable requestData = (Hashtable) request.Params[0]; - CheckStringParameters(request, new string[] { - "password"}); + /// + /// 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.DebugFormat("[RADMIN]: updateUserAppearance"); - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + 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; - 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())); + // Has a gender preference been supplied? - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) + if (requestData.Contains("gender")) + { + switch ((string)requestData["gender"]) { - 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); + case "m" : + case "male" : + model = defaultMale; + break; + case "f" : + case "female" : + model = defaultFemale; + break; + case "n" : + case "neutral" : + default : + model = defaultNeutral; + break; } - else throw new Exception("neither region_name nor region_uuid given"); - - Scene scene = m_application.SceneManager.CurrentScene; - int flags; - string text; - int health = scene.GetHealth(out flags, out text); - responseData["health"] = health; - responseData["flags"] = flags; - responseData["message"] = text; - - response.Value = responseData; } - catch (Exception e) - { - m_log.InfoFormat("[RADMIN]: RegionQuery: {0}", e.Message); - responseData["success"] = false; - responseData["error"] = e.Message; + // Has an explicit model been specified? - response.Value = responseData; + if (requestData.Contains("model") && (String.IsNullOrEmpty((string)requestData["gender"]))) + { + model = (string)requestData["model"]; } - m_log.Info("[RADMIN]: Query XML Administrator Request complete"); - - return response; - } - - public XmlRpcResponse XmlRpcConsoleCommandMethod(XmlRpcRequest request, IPEndPoint remoteClient) - { - m_log.Info("[RADMIN]: Received Command XML Administrator Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); + // No appearance attributes were set - try + if (String.IsNullOrEmpty(model)) { - responseData["success"] = true; - - Hashtable requestData = (Hashtable) request.Params[0]; + m_log.DebugFormat("[RADMIN]: Appearance update not requested"); + return; + } - CheckStringParameters(request, new string[] { - "password", "command"}); + m_log.DebugFormat("[RADMIN]: Setting appearance for avatar {0}, using model <{1}>", userid, model); - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + 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; + } - MainConsole.Instance.RunCommand(requestData["command"].ToString()); + Scene scene = m_application.SceneManager.CurrentOrFirstScene; + UUID scopeID = scene.RegionInfo.ScopeID; + UserAccount modelProfile = scene.UserAccountService.GetUserAccount(scopeID, modelSpecifiers[0], modelSpecifiers[1]); - response.Value = responseData; - } - catch (Exception e) + if (modelProfile == null) { - m_log.InfoFormat("[RADMIN]: ConsoleCommand: {0}", e.Message); + m_log.WarnFormat("[RADMIN]: Requested model ({0}) not found. Appearance unchanged", model); + return; + } - responseData["success"] = false; - responseData["error"] = e.Message; + // 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. - response.Value = responseData; - } + EstablishAppearance(userid, modelProfile.PrincipalID); - m_log.Info("[RADMIN]: Command XML Administrator Request complete"); - return response; + m_log.DebugFormat("[RADMIN]: Finished setting appearance for avatar {0}, using model {1}", + userid, model); } - public XmlRpcResponse XmlRpcAccessListClear(XmlRpcRequest request, IPEndPoint remoteClient) + /// + /// 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.Info("[RADMIN]: Received Access List Clear Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - responseData["success"] = true; - - Hashtable requestData = (Hashtable) request.Params[0]; + m_log.DebugFormat("[RADMIN]: Initializing inventory for {0} from {1}", destination, source); + Scene scene = m_application.SceneManager.CurrentOrFirstScene; - CheckStringParameters(request, new string[] { - "password"}); + // If the model has no associated appearance we're done. + AvatarAppearance avatarAppearance = scene.AvatarService.GetAppearance(source); + if (avatarAppearance == null) + return; - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + // Simple appearance copy or copy Clothing and Bodyparts folders? + bool copyFolders = m_config.GetBoolean("copy_folders", false); - if (requestData.Contains("region_uuid")) + 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(); + return; } - catch (Exception e) + + // Copy Clothing and Bodypart folders and appearance update + try { - m_log.ErrorFormat("[RADMIN]: Access List Clear Request: {0} {1}", e.Message, e.StackTrace); + Dictionary inventoryMap = new Dictionary(); + CopyInventoryFolders(destination, source, AssetType.Clothing, inventoryMap, avatarAppearance); + CopyInventoryFolders(destination, source, AssetType.Bodypart, inventoryMap, avatarAppearance); - responseData["success"] = false; - responseData["error"] = e.Message; + AvatarWearable[] wearables = avatarAppearance.Wearables; + + 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) { - m_log.Info("[RADMIN]: Received Access List Add Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - responseData["success"] = true; - - Hashtable requestData = (Hashtable) request.Params[0]; + IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; - CheckStringParameters(request, new string[] { - "password"}); + // Get Clothing folder of receiver + InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, AssetType.Clothing); - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + if (destinationFolder == null) + throw new Exception("Cannot locate folder(s)"); - 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"); + // 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); + } - int addedUsers = 0; + // Wearables + AvatarWearable[] wearables = avatarAppearance.Wearables; + AvatarWearable wearable; - if (requestData.Contains("users")) + for (int i = 0; i uuids = new List(); - foreach (string name in users.Values) + // Get inventory item and copy it + InventoryItemBase item = new InventoryItemBase(wearable[0].ItemID, source); + item = inventoryService.GetItem(item); + + if (item != null) { - 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); - } + 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.Add(uuid); - addedUsers++; - } + 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["added"] = addedUsers; - } - 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.Info("[RADMIN]: Access List Add Request complete"); - return response; - } - - public XmlRpcResponse XmlRpcAccessListRemove(XmlRpcRequest request, IPEndPoint remoteClient) - { - m_log.Info("[RADMIN]: Received Access List Remove 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"); - - int removedUsers = 0; + // Get inventory item and copy it + InventoryItemBase item = new InventoryItemBase(itemID, source); + item = inventoryService.GetItem(item); - 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) + 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); + + // Attach item + avatarAppearance.SetAttachment(attachpoint, destinationItem.ID, destinationItem.AssetID); + m_log.DebugFormat("[RADMIN]: Attached {0}", destinationItem.ID); } - 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}", 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) + /// + /// 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) { - m_log.Info("[RADMIN]: Received Access List List Request"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - responseData["success"] = true; - - Hashtable requestData = (Hashtable) request.Params[0]; + IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; - CheckStringParameters(request, new string[] { - "password"}); + InventoryFolderBase sourceFolder = inventoryService.GetFolderForType(source, assetType); + InventoryFolderBase destinationFolder = inventoryService.GetFolderForType(destination, assetType); - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + if (sourceFolder == null || destinationFolder == null) + throw new Exception("Cannot locate folder(s)"); - 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()); + // 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("region_name")) + 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); + } + + // 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) { - 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); + destinationFolder.Name = "Clothing"; } - else throw new Exception("neither region_name nor region_uuid given"); - - Scene scene = m_application.SceneManager.CurrentScene; - UUID[] accessControlList = scene.RegionInfo.EstateSettings.EstateAccess; - Hashtable users = new Hashtable(); - - foreach (UUID user in accessControlList) + else { - UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; - UserAccount account = m_application.SceneManager.CurrentOrFirstScene.UserAccountService.GetUserAccount(scopeID, user); - if (account != null) - { - users[user.ToString()] = account.FirstName + " " + account.LastName; - } + destinationFolder.Name = "Body Parts"; } - - responseData["users"] = users; + 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); } - 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; - } + InventoryFolderBase extraFolder; + List folders = inventoryService.GetFolderContent(source, sourceFolder.ID).Folders; - m_log.Info("[RADMIN]: Access List List Request complete"); - return response; - } - - public XmlRpcResponse XmlRpcTeleportAgentMethod(XmlRpcRequest request, IPEndPoint remoteClient) - { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try + foreach (InventoryFolderBase folder in folders) { - responseData["success"] = true; - - Hashtable requestData = (Hashtable)request.Params[0]; - - CheckStringParameters(request, new string[] {"password"}); - - FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + 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); - UUID agentId; - string regionName = null; - Vector3 pos, lookAt; - bool agentSpecified = false; - ScenePresence sp = null; + m_log.DebugFormat("[RADMIN]: Added folder {0} to folder {1}", extraFolder.ID, sourceFolder.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); + List items = inventoryService.GetFolderContent(source, folder.ID).Items; - 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")) + foreach (InventoryItemBase item in items) { - 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)); + 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); - m_application.SceneManager.TryGetRootScenePresence(agentId, out sp); + 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); - 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"); + // 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); + } } - - 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); - - sp.Scene.RequestTeleportLocation( - sp.ControllingClient, regionName, pos, lookAt, (uint)Constants.TeleportFlags.ViaLocation); - } - catch (Exception e) - { - m_log.ErrorFormat("[RADMIN]: admin_teleport_agent exception: {0}{1}", e.Message, e.StackTrace); - - responseData["success"] = false; - responseData["error"] = e.Message; - } - finally - { - response.Value = responseData; } - - return response; } /// - /// Parse a float with the given parameter name from a request data hash table. + /// Apply next owner permissions. /// - /// - /// 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) + private void ApplyNextOwnerPermissions(InventoryItemBase item) { - 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 - return val; - } - else + if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) { - return defaultVal; + 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 static void CheckStringParameters(XmlRpcRequest request, string[] param) + /// + /// 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() { - Hashtable requestData = (Hashtable) request.Params[0]; - foreach (string parameter in param) + // Only load once + if (m_defaultAvatarsLoaded) { - 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)); + return false; } - } - private static void CheckIntegerParams(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 integer parameter {0}", parameter)); - } - } + m_log.DebugFormat("[RADMIN]: Creating default avatar entries"); - private bool GetBoolean(Hashtable requestData, string tag, bool defaultValue) - { - // If an access value has been provided, apply it. - if (requestData.Contains(tag)) + m_defaultAvatarsLoaded = true; + + // Load processing starts here... + + try { - switch (((string)requestData[tag]).ToLower()) + string defaultAppearanceFileName = null; + + //m_config may be null if RemoteAdmin configuration secition is missing or disabled in OpenSim.ini + if (m_config != null) { - case "true" : - case "t" : - case "1" : - return true; - case "false" : - case "f" : - case "0" : - return false; - default : - return defaultValue; + defaultAppearanceFileName = m_config.GetString("default_appearance", "default_appearance.xml"); } - } - else - return defaultValue; - } - private int GetIntegerAttribute(XmlNode node, string attribute, int defaultValue) - { - try { return Convert.ToInt32(node.Attributes[attribute].Value); } catch{} - return defaultValue; - } + if (File.Exists(defaultAppearanceFileName)) + { + 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; - private uint GetUnsignedAttribute(XmlNode node, string attribute, uint defaultValue) - { - try { return Convert.ToUInt32(node.Attributes[attribute].Value); } catch{} - return defaultValue; - } + Scene scene = m_application.SceneManager.CurrentOrFirstScene; + IInventoryService inventoryService = scene.InventoryService; + IAssetService assetService = scene.AssetService; - private string GetStringAttribute(XmlNode node, string attribute, string defaultValue) - { - try { return node.Attributes[attribute].Value; } catch{} - return defaultValue; - } + doc.LoadXml(File.ReadAllText(defaultAppearanceFileName)); - public void Dispose() - { - } + // Load up any included assets. Duplicates will be ignored + assets = doc.GetElementsByTagName("RequiredAsset"); + foreach (XmlNode assetNode in assets) + { + 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); + } - /// - /// 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; + avatars = doc.GetElementsByTagName("Avatar"); - UserAccount account = userAccountService.GetUserAccount(scopeID, firstName, lastName); - if (null == account) - { - account = new UserAccount(scopeID, UUID.Random(), firstName, lastName, email); - if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0)) - { - account.ServiceURLs = new Dictionary(); - account.ServiceURLs["HomeURI"] = string.Empty; - account.ServiceURLs["GatekeeperURI"] = string.Empty; - account.ServiceURLs["InventoryServerURI"] = string.Empty; - account.ServiceURLs["AssetServerURI"] = string.Empty; - } + // The document may contain multiple avatars - if (userAccountService.StoreUserAccount(account)) - { - bool success; - if (authenticationService != null) + foreach (XmlElement avatar in avatars) { - success = authenticationService.SetPassword(account.PrincipalID, password); - if (!success) - m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", - firstName, lastName); - } + m_log.DebugFormat("[RADMIN]: Loading appearance for {0}, gender = {1}", + GetStringAttribute(avatar,"name","?"), GetStringAttribute(avatar,"gender","?")); - GridRegion home = null; - if (gridService != null) - { - List defaultRegions = gridService.GetDefaultRegions(UUID.Zero); - if (defaultRegions != null && defaultRegions.Count >= 1) - home = defaultRegions[0]; + // Create the user identified by the avatar entry - 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); + 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); - if (inventoryService != null) - { - success = inventoryService.CreateUserInventory(account.PrincipalID); - if (!success) - m_log.WarnFormat("[RADMIN]: Unable to create inventory for account {0} {1}.", - firstName, lastName); - } + 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; + } + } - 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; - } + // Set home position - /// - /// 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; + 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]); + } - UserAccount account = userAccountService.GetUserAccount(UUID.Zero, firstName, lastName); - if (null != account) - { - bool success = false; - if (authenticationService != null) - success = authenticationService.SetPassword(account.PrincipalID, password); + ID = account.PrincipalID; - 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; - } - } + 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; + } - private bool LoadHeightmap(string file, UUID regionID) - { - m_log.InfoFormat("[RADMIN]: Terrain Loading: {0}", file); + // 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. - Scene region = null; + if (include) + { + // Setup for appearance processing + avatarAppearance = scene.AvatarService.GetAppearance(ID); + if (avatarAppearance == null) + avatarAppearance = new AvatarAppearance(); - 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; - } + AvatarWearable[] wearables = avatarAppearance.Wearables; + for (int i=0; i(); - 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)) + try + { + // m_log.DebugFormat("[RADMIN] {0} folders, {1} items in inventory", + // uic.folders.Count, uic.items.Count); + + InventoryFolderBase clothingFolder = inventoryService.GetFolderForType(ID, AssetType.Clothing); + + // This should *never* be the case + if (clothingFolder == null || clothingFolder.Type != (short)AssetType.Clothing) + { + clothingFolder = new InventoryFolderBase(); + clothingFolder.ID = UUID.Random(); + clothingFolder.Name = "Clothing"; + clothingFolder.Owner = ID; + clothingFolder.Type = (short)AssetType.Clothing; + clothingFolder.ParentID = inventoryService.GetRootFolder(ID).ID; + clothingFolder.Version = 1; + inventoryService.AddFolder(clothingFolder); // store base record + m_log.ErrorFormat("[RADMIN]: Created clothing folder for {0}/{1}", name, ID); + } + + // OK, now we have an inventory for the user, read in the outfits from the + // default appearance XMl file. + + XmlNodeList outfits = avatar.GetElementsByTagName("Ensemble"); + InventoryFolderBase extraFolder; + string outfitName; + UUID assetid; + + foreach (XmlElement outfit in outfits) + { + m_log.DebugFormat("[RADMIN]: Loading outfit {0} for {1}", + GetStringAttribute(outfit,"name","?"), GetStringAttribute(avatar,"name","?")); + + outfitName = GetStringAttribute(outfit,"name",""); + select = (GetStringAttribute(outfit,"default","no") == "yes"); + + // If the folder already exists, re-use it. The defaults may + // change over time. Augment only. + + List 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