diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs | 211 |
1 files changed, 149 insertions, 62 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index 5a7446f..9fa9be1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs | |||
@@ -32,6 +32,24 @@ using OpenMetaverse; | |||
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Region.Framework.Scenes; | 33 | using OpenSim.Region.Framework.Scenes; |
34 | using OpenSim.Region.Framework.Interfaces; | 34 | using OpenSim.Region.Framework.Interfaces; |
35 | using System; | ||
36 | using System.Reflection; | ||
37 | using System.Collections; | ||
38 | using System.Collections.Specialized; | ||
39 | using System.Reflection; | ||
40 | using System.IO; | ||
41 | using System.Web; | ||
42 | using System.Xml; | ||
43 | using log4net; | ||
44 | using Mono.Addins; | ||
45 | using OpenMetaverse.Messages.Linden; | ||
46 | using OpenMetaverse.StructuredData; | ||
47 | using OpenSim.Framework.Capabilities; | ||
48 | using OpenSim.Framework.Servers; | ||
49 | using OpenSim.Framework.Servers.HttpServer; | ||
50 | using Caps = OpenSim.Framework.Capabilities.Caps; | ||
51 | using OSDArray = OpenMetaverse.StructuredData.OSDArray; | ||
52 | using OSDMap = OpenMetaverse.StructuredData.OSDMap; | ||
35 | 53 | ||
36 | using Mono.Addins; | 54 | using Mono.Addins; |
37 | 55 | ||
@@ -40,11 +58,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
40 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")] | 58 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")] |
41 | public class GodsModule : INonSharedRegionModule, IGodsModule | 59 | public class GodsModule : INonSharedRegionModule, IGodsModule |
42 | { | 60 | { |
61 | private static readonly ILog m_log = | ||
62 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
63 | |||
43 | /// <summary>Special UUID for actions that apply to all agents</summary> | 64 | /// <summary>Special UUID for actions that apply to all agents</summary> |
44 | private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); | 65 | private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); |
45 | 66 | ||
46 | protected Scene m_scene; | 67 | protected Scene m_scene; |
47 | protected IDialogModule m_dialogModule; | 68 | protected IDialogModule m_dialogModule; |
69 | |||
70 | protected Dictionary<UUID, string> m_capsDict = | ||
71 | new Dictionary<UUID, string>(); | ||
72 | |||
48 | protected IDialogModule DialogModule | 73 | protected IDialogModule DialogModule |
49 | { | 74 | { |
50 | get | 75 | get |
@@ -65,6 +90,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
65 | m_scene = scene; | 90 | m_scene = scene; |
66 | m_scene.RegisterModuleInterface<IGodsModule>(this); | 91 | m_scene.RegisterModuleInterface<IGodsModule>(this); |
67 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; | 92 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; |
93 | m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; | ||
94 | m_scene.EventManager.OnClientClosed += OnClientClosed; | ||
95 | scene.EventManager.OnIncomingInstantMessage += | ||
96 | OnIncomingInstantMessage; | ||
68 | } | 97 | } |
69 | 98 | ||
70 | public void RemoveRegion(Scene scene) | 99 | public void RemoveRegion(Scene scene) |
@@ -98,6 +127,54 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
98 | client.OnRequestGodlikePowers -= RequestGodlikePowers; | 127 | client.OnRequestGodlikePowers -= RequestGodlikePowers; |
99 | } | 128 | } |
100 | 129 | ||
130 | private void OnClientClosed(UUID agentID, Scene scene) | ||
131 | { | ||
132 | m_capsDict.Remove(agentID); | ||
133 | } | ||
134 | |||
135 | private void OnRegisterCaps(UUID agentID, Caps caps) | ||
136 | { | ||
137 | string uri = "/CAPS/" + UUID.Random(); | ||
138 | m_capsDict[agentID] = uri; | ||
139 | |||
140 | caps.RegisterHandler("UntrustedSimulatorMessage", | ||
141 | new RestStreamHandler("POST", uri, | ||
142 | HandleUntrustedSimulatorMessage)); | ||
143 | } | ||
144 | |||
145 | private string HandleUntrustedSimulatorMessage(string request, | ||
146 | string path, string param, IOSHttpRequest httpRequest, | ||
147 | IOSHttpResponse httpResponse) | ||
148 | { | ||
149 | OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request); | ||
150 | |||
151 | string message = osd["message"].AsString(); | ||
152 | |||
153 | if (message == "GodKickUser") | ||
154 | { | ||
155 | OSDMap body = (OSDMap)osd["body"]; | ||
156 | OSDArray userInfo = (OSDArray)body["UserInfo"]; | ||
157 | OSDMap userData = (OSDMap)userInfo[0]; | ||
158 | |||
159 | UUID agentID = userData["AgentID"].AsUUID(); | ||
160 | UUID godID = userData["GodID"].AsUUID(); | ||
161 | UUID godSessionID = userData["GodSessionID"].AsUUID(); | ||
162 | uint kickFlags = userData["KickFlags"].AsUInteger(); | ||
163 | string reason = userData["Reason"].AsString(); | ||
164 | |||
165 | ScenePresence god = m_scene.GetScenePresence(godID); | ||
166 | if (god == null || god.ControllingClient.SessionId != godSessionID) | ||
167 | return String.Empty; | ||
168 | |||
169 | KickUser(godID, godSessionID, agentID, kickFlags, Util.StringToBytes1024(reason)); | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | m_log.ErrorFormat("[GOD]: Unhandled UntrustedSimulatorMessage: {0}", message); | ||
174 | } | ||
175 | return String.Empty; | ||
176 | } | ||
177 | |||
101 | public void RequestGodlikePowers( | 178 | public void RequestGodlikePowers( |
102 | UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) | 179 | UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) |
103 | { | 180 | { |
@@ -146,76 +223,86 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
146 | /// <param name="reason">The message to send to the user after it's been turned into a field</param> | 223 | /// <param name="reason">The message to send to the user after it's been turned into a field</param> |
147 | public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) | 224 | public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) |
148 | { | 225 | { |
149 | UUID kickUserID = ALL_AGENTS; | 226 | if (!m_scene.Permissions.IsGod(godID)) |
150 | 227 | return; | |
228 | |||
151 | ScenePresence sp = m_scene.GetScenePresence(agentID); | 229 | ScenePresence sp = m_scene.GetScenePresence(agentID); |
152 | 230 | ||
153 | if (sp != null || agentID == kickUserID) | 231 | if (sp == null && agentID != ALL_AGENTS) |
154 | { | 232 | { |
155 | if (m_scene.Permissions.IsGod(godID)) | 233 | IMessageTransferModule transferModule = |
234 | m_scene.RequestModuleInterface<IMessageTransferModule>(); | ||
235 | if (transferModule != null) | ||
156 | { | 236 | { |
157 | if (kickflags == 0) | 237 | m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID); |
158 | { | 238 | transferModule.SendInstantMessage(new GridInstantMessage( |
159 | if (agentID == kickUserID) | 239 | m_scene, godID, "God", agentID, (byte)250, false, |
160 | { | 240 | Utils.BytesToString(reason), UUID.Zero, true, |
161 | string reasonStr = Utils.BytesToString(reason); | 241 | new Vector3(), new byte[] {(byte)kickflags}, true), |
162 | 242 | delegate(bool success) {} ); | |
163 | m_scene.ForEachClient( | 243 | } |
164 | delegate(IClientAPI controller) | 244 | return; |
165 | { | 245 | } |
166 | if (controller.AgentId != godID) | ||
167 | controller.Kick(reasonStr); | ||
168 | } | ||
169 | ); | ||
170 | |||
171 | // This is a bit crude. It seems the client will be null before it actually stops the thread | ||
172 | // The thread will kill itself eventually :/ | ||
173 | // Is there another way to make sure *all* clients get this 'inter region' message? | ||
174 | m_scene.ForEachRootClient( | ||
175 | delegate(IClientAPI client) | ||
176 | { | ||
177 | if (client.AgentId != godID) | ||
178 | { | ||
179 | client.Close(); | ||
180 | } | ||
181 | } | ||
182 | ); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | m_scene.SceneGraph.removeUserCount(!sp.IsChildAgent); | ||
187 | 246 | ||
188 | sp.ControllingClient.Kick(Utils.BytesToString(reason)); | 247 | switch (kickflags) |
189 | sp.ControllingClient.Close(); | 248 | { |
190 | } | 249 | case 0: |
191 | } | 250 | if (sp != null) |
192 | 251 | { | |
193 | if (kickflags == 1) | 252 | KickPresence(sp, Utils.BytesToString(reason)); |
194 | { | ||
195 | sp.AllowMovement = false; | ||
196 | if (DialogModule != null) | ||
197 | { | ||
198 | DialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); | ||
199 | DialogModule.SendAlertToUser(godID, "User Frozen"); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | if (kickflags == 2) | ||
204 | { | ||
205 | sp.AllowMovement = true; | ||
206 | if (DialogModule != null) | ||
207 | { | ||
208 | DialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); | ||
209 | DialogModule.SendAlertToUser(godID, "User Unfrozen"); | ||
210 | } | ||
211 | } | ||
212 | } | 253 | } |
213 | else | 254 | else if (agentID == ALL_AGENTS) |
214 | { | 255 | { |
215 | if (DialogModule != null) | 256 | m_scene.ForEachRootScenePresence( |
216 | DialogModule.SendAlertToUser(godID, "Kick request denied"); | 257 | delegate(ScenePresence p) |
258 | { | ||
259 | if (p.UUID != godID && (!m_scene.Permissions.IsGod(p.UUID))) | ||
260 | KickPresence(p, Utils.BytesToString(reason)); | ||
261 | } | ||
262 | ); | ||
263 | } | ||
264 | break; | ||
265 | case 1: | ||
266 | if (sp != null) | ||
267 | { | ||
268 | sp.AllowMovement = false; | ||
269 | m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); | ||
270 | m_dialogModule.SendAlertToUser(godID, "User Frozen"); | ||
217 | } | 271 | } |
272 | break; | ||
273 | case 2: | ||
274 | if (sp != null) | ||
275 | { | ||
276 | sp.AllowMovement = true; | ||
277 | m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); | ||
278 | m_dialogModule.SendAlertToUser(godID, "User Unfrozen"); | ||
279 | } | ||
280 | break; | ||
281 | default: | ||
282 | break; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | private void KickPresence(ScenePresence sp, string reason) | ||
287 | { | ||
288 | if (sp.IsChildAgent) | ||
289 | return; | ||
290 | sp.ControllingClient.Kick(reason); | ||
291 | sp.MakeChildAgent(); | ||
292 | sp.ControllingClient.Close(); | ||
293 | } | ||
294 | |||
295 | private void OnIncomingInstantMessage(GridInstantMessage msg) | ||
296 | { | ||
297 | if (msg.dialog == (uint)250) // Nonlocal kick | ||
298 | { | ||
299 | UUID agentID = new UUID(msg.toAgentID); | ||
300 | string reason = msg.message; | ||
301 | UUID godID = new UUID(msg.fromAgentID); | ||
302 | uint kickMode = (uint)msg.binaryBucket[0]; | ||
303 | |||
304 | KickUser(godID, UUID.Zero, agentID, kickMode, Util.StringToBytes1024(reason)); | ||
218 | } | 305 | } |
219 | } | 306 | } |
220 | } | 307 | } |
221 | } \ No newline at end of file | 308 | } |