diff options
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs | 199 |
1 files changed, 137 insertions, 62 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index 5a7446f..d9badcd 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs | |||
@@ -32,14 +32,35 @@ 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; | ||
35 | 44 | ||
36 | using Mono.Addins; | 45 | using Mono.Addins; |
37 | 46 | ||
47 | using OpenMetaverse.Messages.Linden; | ||
48 | using OpenMetaverse.StructuredData; | ||
49 | using OpenSim.Framework.Capabilities; | ||
50 | using OpenSim.Framework.Servers; | ||
51 | using OpenSim.Framework.Servers.HttpServer; | ||
52 | using Caps = OpenSim.Framework.Capabilities.Caps; | ||
53 | using OSDArray = OpenMetaverse.StructuredData.OSDArray; | ||
54 | using OSDMap = OpenMetaverse.StructuredData.OSDMap; | ||
55 | |||
38 | namespace OpenSim.Region.CoreModules.Avatar.Gods | 56 | namespace OpenSim.Region.CoreModules.Avatar.Gods |
39 | { | 57 | { |
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 | ||
@@ -65,6 +86,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
65 | m_scene = scene; | 86 | m_scene = scene; |
66 | m_scene.RegisterModuleInterface<IGodsModule>(this); | 87 | m_scene.RegisterModuleInterface<IGodsModule>(this); |
67 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; | 88 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; |
89 | m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; | ||
90 | scene.EventManager.OnIncomingInstantMessage += | ||
91 | OnIncomingInstantMessage; | ||
68 | } | 92 | } |
69 | 93 | ||
70 | public void RemoveRegion(Scene scene) | 94 | public void RemoveRegion(Scene scene) |
@@ -98,6 +122,47 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods | |||
98 | client.OnRequestGodlikePowers -= RequestGodlikePowers; | 122 | client.OnRequestGodlikePowers -= RequestGodlikePowers; |
99 | } | 123 | } |
100 | 124 | ||
125 | private void OnRegisterCaps(UUID agentID, Caps caps) | ||
126 | { | ||
127 | string uri = "/CAPS/" + UUID.Random(); | ||
128 | |||
129 | caps.RegisterHandler("UntrustedSimulatorMessage", | ||
130 | new RestStreamHandler("POST", uri, | ||
131 | HandleUntrustedSimulatorMessage)); | ||
132 | } | ||
133 | |||
134 | private string HandleUntrustedSimulatorMessage(string request, | ||
135 | string path, string param, IOSHttpRequest httpRequest, | ||
136 | IOSHttpResponse httpResponse) | ||
137 | { | ||
138 | OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request); | ||
139 | |||
140 | string message = osd["message"].AsString(); | ||
141 | |||
142 | if (message == "GodKickUser") | ||
143 | { | ||
144 | OSDMap body = (OSDMap)osd["body"]; | ||
145 | OSDArray userInfo = (OSDArray)body["UserInfo"]; | ||
146 | OSDMap userData = (OSDMap)userInfo[0]; | ||
147 | |||
148 | UUID agentID = userData["AgentID"].AsUUID(); | ||
149 | UUID godID = userData["GodID"].AsUUID(); | ||
150 | UUID godSessionID = userData["GodSessionID"].AsUUID(); | ||
151 | uint kickFlags = userData["KickFlags"].AsUInteger(); | ||
152 | string reason = userData["Reason"].AsString(); | ||
153 | ScenePresence god = m_scene.GetScenePresence(godID); | ||
154 | if (god == null || god.ControllingClient.SessionId != godSessionID) | ||
155 | return String.Empty; | ||
156 | |||
157 | KickUser(godID, godSessionID, agentID, kickFlags, Util.StringToBytes1024(reason)); | ||
158 | } | ||
159 | else | ||
160 | { | ||
161 | m_log.ErrorFormat("[GOD]: Unhandled UntrustedSimulatorMessage: {0}", message); | ||
162 | } | ||
163 | return String.Empty; | ||
164 | } | ||
165 | |||
101 | public void RequestGodlikePowers( | 166 | public void RequestGodlikePowers( |
102 | UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) | 167 | UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) |
103 | { | 168 | { |
@@ -146,76 +211,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> | 211 | /// <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) | 212 | public void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason) |
148 | { | 213 | { |
149 | UUID kickUserID = ALL_AGENTS; | 214 | if (!m_scene.Permissions.IsGod(godID)) |
150 | 215 | return; | |
216 | |||
151 | ScenePresence sp = m_scene.GetScenePresence(agentID); | 217 | ScenePresence sp = m_scene.GetScenePresence(agentID); |
152 | 218 | ||
153 | if (sp != null || agentID == kickUserID) | 219 | if (sp == null && agentID != ALL_AGENTS) |
154 | { | 220 | { |
155 | if (m_scene.Permissions.IsGod(godID)) | 221 | IMessageTransferModule transferModule = |
222 | m_scene.RequestModuleInterface<IMessageTransferModule>(); | ||
223 | if (transferModule != null) | ||
156 | { | 224 | { |
157 | if (kickflags == 0) | 225 | m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID); |
158 | { | 226 | transferModule.SendInstantMessage(new GridInstantMessage( |
159 | if (agentID == kickUserID) | 227 | m_scene, godID, "God", agentID, (byte)250, false, |
160 | { | 228 | Utils.BytesToString(reason), UUID.Zero, true, |
161 | string reasonStr = Utils.BytesToString(reason); | 229 | new Vector3(), new byte[] {(byte)kickflags}, true), |
162 | 230 | delegate(bool success) {} ); | |
163 | m_scene.ForEachClient( | 231 | } |
164 | delegate(IClientAPI controller) | 232 | return; |
165 | { | 233 | } |
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 | 234 | ||
188 | sp.ControllingClient.Kick(Utils.BytesToString(reason)); | 235 | switch (kickflags) |
189 | sp.ControllingClient.Close(); | 236 | { |
190 | } | 237 | case 0: |
191 | } | 238 | if (sp != null) |
192 | 239 | { | |
193 | if (kickflags == 1) | 240 | 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 | } | 241 | } |
213 | else | 242 | else if (agentID == ALL_AGENTS) |
214 | { | 243 | { |
215 | if (DialogModule != null) | 244 | m_scene.ForEachRootScenePresence( |
216 | DialogModule.SendAlertToUser(godID, "Kick request denied"); | 245 | delegate(ScenePresence p) |
246 | { | ||
247 | if (p.UUID != godID && (!m_scene.Permissions.IsGod(p.UUID))) | ||
248 | KickPresence(p, Utils.BytesToString(reason)); | ||
249 | } | ||
250 | ); | ||
217 | } | 251 | } |
252 | break; | ||
253 | case 1: | ||
254 | if (sp != null) | ||
255 | { | ||
256 | sp.AllowMovement = false; | ||
257 | m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); | ||
258 | m_dialogModule.SendAlertToUser(godID, "User Frozen"); | ||
259 | } | ||
260 | break; | ||
261 | case 2: | ||
262 | if (sp != null) | ||
263 | { | ||
264 | sp.AllowMovement = true; | ||
265 | m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); | ||
266 | m_dialogModule.SendAlertToUser(godID, "User Unfrozen"); | ||
267 | } | ||
268 | break; | ||
269 | default: | ||
270 | break; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | private void KickPresence(ScenePresence sp, string reason) | ||
275 | { | ||
276 | if (sp.IsChildAgent) | ||
277 | return; | ||
278 | sp.ControllingClient.Kick(reason); | ||
279 | sp.MakeChildAgent(); | ||
280 | sp.ControllingClient.Close(); | ||
281 | } | ||
282 | |||
283 | private void OnIncomingInstantMessage(GridInstantMessage msg) | ||
284 | { | ||
285 | if (msg.dialog == (uint)250) // Nonlocal kick | ||
286 | { | ||
287 | UUID agentID = new UUID(msg.toAgentID); | ||
288 | string reason = msg.message; | ||
289 | UUID godID = new UUID(msg.fromAgentID); | ||
290 | uint kickMode = (uint)msg.binaryBucket[0]; | ||
291 | |||
292 | KickUser(godID, UUID.Zero, agentID, kickMode, Util.StringToBytes1024(reason)); | ||
218 | } | 293 | } |
219 | } | 294 | } |
220 | } | 295 | } |
221 | } \ No newline at end of file | 296 | } |