diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 5a7446f3d1..d9badcd90a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -32,14 +32,35 @@ using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
+using System;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Reflection;
+using System.IO;
+using System.Web;
+using System.Xml;
+using log4net;
using Mono.Addins;
+using OpenMetaverse.Messages.Linden;
+using OpenMetaverse.StructuredData;
+using OpenSim.Framework.Capabilities;
+using OpenSim.Framework.Servers;
+using OpenSim.Framework.Servers.HttpServer;
+using Caps = OpenSim.Framework.Capabilities.Caps;
+using OSDArray = OpenMetaverse.StructuredData.OSDArray;
+using OSDMap = OpenMetaverse.StructuredData.OSDMap;
+
namespace OpenSim.Region.CoreModules.Avatar.Gods
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")]
public class GodsModule : INonSharedRegionModule, IGodsModule
{
+ private static readonly ILog m_log =
+ LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
/// Special UUID for actions that apply to all agents
private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb");
@@ -65,6 +86,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
m_scene = scene;
m_scene.RegisterModuleInterface(this);
m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
+ m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
+ scene.EventManager.OnIncomingInstantMessage +=
+ OnIncomingInstantMessage;
}
public void RemoveRegion(Scene scene)
@@ -98,6 +122,47 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
client.OnRequestGodlikePowers -= RequestGodlikePowers;
}
+ private void OnRegisterCaps(UUID agentID, Caps caps)
+ {
+ string uri = "/CAPS/" + UUID.Random();
+
+ caps.RegisterHandler("UntrustedSimulatorMessage",
+ new RestStreamHandler("POST", uri,
+ HandleUntrustedSimulatorMessage));
+ }
+
+ private string HandleUntrustedSimulatorMessage(string request,
+ string path, string param, IOSHttpRequest httpRequest,
+ IOSHttpResponse httpResponse)
+ {
+ OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
+
+ string message = osd["message"].AsString();
+
+ if (message == "GodKickUser")
+ {
+ OSDMap body = (OSDMap)osd["body"];
+ OSDArray userInfo = (OSDArray)body["UserInfo"];
+ OSDMap userData = (OSDMap)userInfo[0];
+
+ UUID agentID = userData["AgentID"].AsUUID();
+ UUID godID = userData["GodID"].AsUUID();
+ UUID godSessionID = userData["GodSessionID"].AsUUID();
+ uint kickFlags = userData["KickFlags"].AsUInteger();
+ string reason = userData["Reason"].AsString();
+ ScenePresence god = m_scene.GetScenePresence(godID);
+ if (god == null || god.ControllingClient.SessionId != godSessionID)
+ return String.Empty;
+
+ KickUser(godID, godSessionID, agentID, kickFlags, Util.StringToBytes1024(reason));
+ }
+ else
+ {
+ m_log.ErrorFormat("[GOD]: Unhandled UntrustedSimulatorMessage: {0}", message);
+ }
+ return String.Empty;
+ }
+
public void RequestGodlikePowers(
UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient)
{
@@ -146,76 +211,86 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
/// The message to send to the user after it's been turned into a field
public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason)
{
- UUID kickUserID = ALL_AGENTS;
-
+ if (!m_scene.Permissions.IsGod(godID))
+ return;
+
ScenePresence sp = m_scene.GetScenePresence(agentID);
- if (sp != null || agentID == kickUserID)
+ if (sp == null && agentID != ALL_AGENTS)
{
- if (m_scene.Permissions.IsGod(godID))
+ IMessageTransferModule transferModule =
+ m_scene.RequestModuleInterface();
+ if (transferModule != null)
{
- if (kickflags == 0)
- {
- if (agentID == kickUserID)
- {
- string reasonStr = Utils.BytesToString(reason);
-
- m_scene.ForEachClient(
- delegate(IClientAPI controller)
- {
- if (controller.AgentId != godID)
- controller.Kick(reasonStr);
- }
- );
-
- // This is a bit crude. It seems the client will be null before it actually stops the thread
- // The thread will kill itself eventually :/
- // Is there another way to make sure *all* clients get this 'inter region' message?
- m_scene.ForEachRootClient(
- delegate(IClientAPI client)
- {
- if (client.AgentId != godID)
- {
- client.Close();
- }
- }
- );
- }
- else
- {
- m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent);
-
- sp.ControllingClient.Kick(Utils.BytesToString(reason));
- sp.ControllingClient.Close();
- }
- }
-
- if (kickflags == 1)
- {
- sp.AllowMovement = false;
- if (DialogModule != null)
- {
- DialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
- DialogModule.SendAlertToUser(godID, "User Frozen");
- }
- }
-
- if (kickflags == 2)
- {
- sp.AllowMovement = true;
- if (DialogModule != null)
- {
- DialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
- DialogModule.SendAlertToUser(godID, "User Unfrozen");
- }
- }
+ m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID);
+ transferModule.SendInstantMessage(new GridInstantMessage(
+ m_scene, godID, "God", agentID, (byte)250, false,
+ Utils.BytesToString(reason), UUID.Zero, true,
+ new Vector3(), new byte[] {(byte)kickflags}, true),
+ delegate(bool success) {} );
}
- else
+ return;
+ }
+
+ switch (kickflags)
+ {
+ case 0:
+ if (sp != null)
{
- if (DialogModule != null)
- DialogModule.SendAlertToUser(godID, "Kick request denied");
+ KickPresence(sp, Utils.BytesToString(reason));
}
+ else if (agentID == ALL_AGENTS)
+ {
+ m_scene.ForEachRootScenePresence(
+ delegate(ScenePresence p)
+ {
+ if (p.UUID != godID && (!m_scene.Permissions.IsGod(p.UUID)))
+ KickPresence(p, Utils.BytesToString(reason));
+ }
+ );
+ }
+ break;
+ case 1:
+ if (sp != null)
+ {
+ sp.AllowMovement = false;
+ m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
+ m_dialogModule.SendAlertToUser(godID, "User Frozen");
+ }
+ break;
+ case 2:
+ if (sp != null)
+ {
+ sp.AllowMovement = true;
+ m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
+ m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void KickPresence(ScenePresence sp, string reason)
+ {
+ if (sp.IsChildAgent)
+ return;
+ sp.ControllingClient.Kick(reason);
+ sp.MakeChildAgent();
+ sp.ControllingClient.Close();
+ }
+
+ private void OnIncomingInstantMessage(GridInstantMessage msg)
+ {
+ if (msg.dialog == (uint)250) // Nonlocal kick
+ {
+ UUID agentID = new UUID(msg.toAgentID);
+ string reason = msg.message;
+ UUID godID = new UUID(msg.fromAgentID);
+ uint kickMode = (uint)msg.binaryBucket[0];
+
+ KickUser(godID, UUID.Zero, agentID, kickMode, Util.StringToBytes1024(reason));
}
}
}
-}
\ No newline at end of file
+}