clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections.Generic;
30 using System.Reflection;
31  
32 using OpenSim.Framework;
33 using OpenSim.Framework.Client;
34 using OpenSim.Region.Framework.Interfaces;
35 using OpenSim.Region.Framework.Scenes;
36 using OpenSim.Services.Connectors.Hypergrid;
37 using OpenSim.Services.Interfaces;
38 using OpenSim.Server.Base;
39  
40 using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41  
42 using OpenMetaverse;
43 using log4net;
44 using Nini.Config;
45 using Mono.Addins;
46  
47 namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
48 {
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGInventoryAccessModule")]
50 public class HGInventoryAccessModule : BasicInventoryAccessModule, INonSharedRegionModule, IInventoryAccessModule
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53  
54 private static HGAssetMapper m_assMapper;
55 public static HGAssetMapper AssetMapper
56 {
57 get { return m_assMapper; }
58 }
59  
60 private string m_HomeURI;
61 private bool m_OutboundPermission;
62 private string m_ThisGatekeeper;
63 private bool m_RestrictInventoryAccessAbroad;
64  
65 private bool m_bypassPermissions = true;
66  
67 // This simple check makes it possible to support grids in which all the simulators
68 // share all central services of the Robust server EXCEPT assets. In other words,
69 // grids where the simulators' assets are kept in one DB and the users' inventory assets
70 // are kept on another. When users rez items from inventory or take objects from world,
71 // an HG-like asset copy takes place between the 2 servers, the world asset server and
72 // the user's asset server.
73 private bool m_CheckSeparateAssets = false;
74 private string m_LocalAssetsURL = string.Empty;
75  
76 // private bool m_Initialized = false;
77  
78 #region INonSharedRegionModule
79  
80 public override string Name
81 {
82 get { return "HGInventoryAccessModule"; }
83 }
84  
85 public override void Initialise(IConfigSource source)
86 {
87 IConfig moduleConfig = source.Configs["Modules"];
88 if (moduleConfig != null)
89 {
90 string name = moduleConfig.GetString("InventoryAccessModule", "");
91 if (name == Name)
92 {
93 m_Enabled = true;
94  
95 InitialiseCommon(source);
96  
97 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name);
98  
99 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"];
100 if (thisModuleConfig != null)
101 {
102 m_HomeURI = Util.GetConfigVarFromSections<string>(source, "HomeURI",
103 new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty);
104 m_ThisGatekeeper = Util.GetConfigVarFromSections<string>(source, "GatekeeperURI",
105 new string[] { "Startup", "Hypergrid", "HGInventoryAccessModule" }, String.Empty);
106 // Legacy. Renove soon!
107 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", m_ThisGatekeeper);
108  
109 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
110 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true);
111 m_CheckSeparateAssets = thisModuleConfig.GetBoolean("CheckSeparateAssets", false);
112 m_LocalAssetsURL = thisModuleConfig.GetString("RegionHGAssetServerURI", string.Empty);
113 m_LocalAssetsURL = m_LocalAssetsURL.Trim(new char[] { '/' });
114  
115 }
116 else
117 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
118  
119 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(source, "serverside_object_permissions",
120 new string[] { "Startup", "Permissions" }, true);
121  
122 }
123 }
124 }
125  
126 public override void AddRegion(Scene scene)
127 {
128 if (!m_Enabled)
129 return;
130  
131 base.AddRegion(scene);
132 m_assMapper = new HGAssetMapper(scene, m_HomeURI);
133 scene.EventManager.OnNewInventoryItemUploadComplete += PostInventoryAsset;
134 scene.EventManager.OnTeleportStart += TeleportStart;
135 scene.EventManager.OnTeleportFail += TeleportFail;
136  
137 // We're fgoing to enforce some stricter permissions if Outbound is false
138 scene.Permissions.OnTakeObject += CanTakeObject;
139 scene.Permissions.OnTakeCopyObject += CanTakeObject;
140 scene.Permissions.OnTransferUserInventory += OnTransferUserInventory;
141 }
142  
143 #endregion
144  
145 #region Event handlers
146  
147 protected override void OnNewClient(IClientAPI client)
148 {
149 base.OnNewClient(client);
150 client.OnCompleteMovementToRegion += new Action<IClientAPI, bool>(OnCompleteMovementToRegion);
151 }
152  
153 protected void OnCompleteMovementToRegion(IClientAPI client, bool arg2)
154 {
155 //m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: OnCompleteMovementToRegion of user {0}", client.Name);
156 object sp = null;
157 if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
158 {
159 if (sp is ScenePresence)
160 {
161 AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId);
162 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
163 {
164 if (m_RestrictInventoryAccessAbroad)
165 {
166 IUserManagement uMan = m_Scene.RequestModuleInterface<IUserManagement>();
167 if (uMan.IsLocalGridUser(client.AgentId))
168 ProcessInventoryForComingHome(client);
169 else
170 ProcessInventoryForArriving(client);
171 }
172 }
173 }
174 }
175 }
176  
177 protected void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout)
178 {
179 if (gridLogout && m_RestrictInventoryAccessAbroad)
180 {
181 IUserManagement uMan = m_Scene.RequestModuleInterface<IUserManagement>();
182 if (uMan != null && uMan.IsLocalGridUser(client.AgentId))
183 {
184 // local grid user
185 ProcessInventoryForHypergriding(client);
186 }
187 else
188 {
189 // Foreigner
190 ProcessInventoryForLeaving(client);
191 }
192 }
193  
194 }
195  
196 protected void TeleportFail(IClientAPI client, bool gridLogout)
197 {
198 if (gridLogout && m_RestrictInventoryAccessAbroad)
199 {
200 IUserManagement uMan = m_Scene.RequestModuleInterface<IUserManagement>();
201 if (uMan.IsLocalGridUser(client.AgentId))
202 {
203 ProcessInventoryForComingHome(client);
204 }
205 else
206 {
207 ProcessInventoryForArriving(client);
208 }
209 }
210 }
211  
212 public void PostInventoryAsset(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel)
213 {
214 if (type == AssetType.Link)
215 return;
216  
217 string userAssetServer = string.Empty;
218 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
219 {
220 m_assMapper.Post(assetID, avatarID, userAssetServer);
221 }
222 }
223  
224 #endregion
225  
226 #region Overrides of Basic Inventory Access methods
227  
228 protected override string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
229 {
230 if (UserManagementModule != null && !UserManagementModule.IsLocalGridUser(presence.UUID))
231 prefix = "HG ";
232 else
233 prefix = string.Empty;
234 suffix = " @ " + m_ThisGatekeeper;
235 Vector3 pos = presence.AbsolutePosition;
236 return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}\n",
237 presence.Scene.RegionInfo.RegionID,
238 pos.X, pos.Y, pos.Z,
239 presence.RegionHandle,
240 m_ThisGatekeeper);
241 }
242  
243  
244 ///
245 /// CapsUpdateInventoryItemAsset
246 ///
247 public override UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
248 {
249 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
250  
251 PostInventoryAsset(remoteClient.AgentId, AssetType.Unknown, newAssetID, "", 0);
252  
253 return newAssetID;
254 }
255  
256 ///
257 /// UpdateInventoryItemAsset
258 ///
259 public override bool UpdateInventoryItemAsset(UUID ownerID, InventoryItemBase item, AssetBase asset)
260 {
261 if (base.UpdateInventoryItemAsset(ownerID, item, asset))
262 {
263 PostInventoryAsset(ownerID, (AssetType)asset.Type, asset.FullID, asset.Name, 0);
264 return true;
265 }
266  
267 return false;
268 }
269  
270 ///
271 /// Used in DeleteToInventory
272 ///
273 protected override void ExportAsset(UUID agentID, UUID assetID)
274 {
275 if (!assetID.Equals(UUID.Zero))
276 PostInventoryAsset(agentID, AssetType.Unknown, assetID, "", 0);
277 else
278 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
279 }
280  
281 ///
282 /// RezObject
283 ///
284 public override SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
285 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
286 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
287 {
288 m_log.DebugFormat("[HGScene]: RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
289  
290 //if (fromTaskID.Equals(UUID.Zero))
291 //{
292 InventoryItemBase item = new InventoryItemBase(itemID);
293 item.Owner = remoteClient.AgentId;
294 item = m_Scene.InventoryService.GetItem(item);
295 //if (item == null)
296 //{ // Fetch the item
297 // item = new InventoryItemBase();
298 // item.Owner = remoteClient.AgentId;
299 // item.ID = itemID;
300 // item = m_assMapper.Get(item, userInfo.RootFolder.ID, userInfo);
301 //}
302 string userAssetServer = string.Empty;
303 if (item != null && IsForeignUser(remoteClient.AgentId, out userAssetServer))
304 {
305 m_assMapper.Get(item.AssetID, remoteClient.AgentId, userAssetServer);
306  
307 }
308 //}
309  
310 // OK, we're done fetching. Pass it up to the default RezObject
311 SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
312 RezSelected, RemoveItem, fromTaskID, attachment);
313  
314 return sog;
315  
316 }
317  
318 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
319 {
320 string senderAssetServer = string.Empty;
321 string receiverAssetServer = string.Empty;
322 bool isForeignSender, isForeignReceiver;
323 isForeignSender = IsForeignUser(sender, out senderAssetServer);
324 isForeignReceiver = IsForeignUser(receiver, out receiverAssetServer);
325  
326 // They're both local. Nothing to do.
327 if (!isForeignSender && !isForeignReceiver)
328 return;
329  
330 // At least one of them is foreign.
331 // If both users have the same asset server, no need to transfer the asset
332 if (senderAssetServer.Equals(receiverAssetServer))
333 {
334 m_log.DebugFormat("[HGScene]: Asset transfer between foreign users, but they have the same server. No transfer.");
335 return;
336 }
337  
338 if (isForeignSender && senderAssetServer != string.Empty)
339 m_assMapper.Get(item.AssetID, sender, senderAssetServer);
340  
341 if (isForeignReceiver && receiverAssetServer != string.Empty && m_OutboundPermission)
342 m_assMapper.Post(item.AssetID, receiver, receiverAssetServer);
343 }
344  
345 public override bool IsForeignUser(UUID userID, out string assetServerURL)
346 {
347 assetServerURL = string.Empty;
348  
349 if (UserManagementModule != null)
350 {
351 if (!m_CheckSeparateAssets)
352 {
353 if (!UserManagementModule.IsLocalGridUser(userID))
354 { // foreign
355 ScenePresence sp = null;
356 if (m_Scene.TryGetScenePresence(userID, out sp))
357 {
358 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
359 if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
360 {
361 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
362 assetServerURL = assetServerURL.Trim(new char[] { '/' });
363 }
364 }
365 else
366 {
367 assetServerURL = UserManagementModule.GetUserServerURL(userID, "AssetServerURI");
368 assetServerURL = assetServerURL.Trim(new char[] { '/' });
369 }
370 return true;
371 }
372 }
373 else
374 {
375 if (IsLocalInventoryAssetsUser(userID, out assetServerURL))
376 {
377 m_log.DebugFormat("[HGScene]: user {0} has local assets {1}", userID, assetServerURL);
378 return false;
379 }
380 else
381 {
382 m_log.DebugFormat("[HGScene]: user {0} has foreign assets {1}", userID, assetServerURL);
383 return true;
384 }
385 }
386 }
387 return false;
388 }
389  
390 private bool IsLocalInventoryAssetsUser(UUID uuid, out string assetsURL)
391 {
392 assetsURL = UserManagementModule.GetUserServerURL(uuid, "AssetServerURI");
393 if (assetsURL == string.Empty)
394 {
395 AgentCircuitData agent = m_Scene.AuthenticateHandler.GetAgentCircuitData(uuid);
396 if (agent != null)
397 {
398 assetsURL = agent.ServiceURLs["AssetServerURI"].ToString();
399 assetsURL = assetsURL.Trim(new char[] { '/' });
400 }
401 }
402 return m_LocalAssetsURL.Equals(assetsURL);
403 }
404  
405  
406 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID)
407 {
408 InventoryItemBase item = base.GetItem(agentID, itemID);
409 if (item == null)
410 return null;
411  
412 string userAssetServer = string.Empty;
413 if (IsForeignUser(agentID, out userAssetServer))
414 m_assMapper.Get(item.AssetID, agentID, userAssetServer);
415  
416 return item;
417 }
418  
419 #endregion
420  
421 #region Inventory manipulation upon arriving/leaving
422  
423 //
424 // These 2 are for local and foreign users coming back, respectively
425 //
426  
427 private void ProcessInventoryForComingHome(IClientAPI client)
428 {
429 m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Restoring root folder for local user {0}", client.Name);
430 if (client is IClientCore)
431 {
432 IClientCore core = (IClientCore)client;
433 IClientInventory inv;
434  
435 if (core.TryGet<IClientInventory>(out inv))
436 {
437 InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId);
438 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID);
439  
440 List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
441  
442 foreach (InventoryFolderBase f in content.Folders)
443 {
444 if (f.Name != "My Suitcase" && f.Name != "Current Outfit")
445 keep.Add(f);
446 }
447  
448 inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray());
449 }
450 }
451 }
452  
453 private void ProcessInventoryForArriving(IClientAPI client)
454 {
455 // No-op for now, but we may need to do something for freign users inventory
456 }
457  
458 //
459 // These 2 are for local and foreign users going away respectively
460 //
461  
462 private void ProcessInventoryForHypergriding(IClientAPI client)
463 {
464 if (client is IClientCore)
465 {
466 IClientCore core = (IClientCore)client;
467 IClientInventory inv;
468  
469 if (core.TryGet<IClientInventory>(out inv))
470 {
471 InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId);
472 if (root != null)
473 {
474 m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Changing root inventory for user {0}", client.Name);
475 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID);
476  
477 List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
478  
479 foreach (InventoryFolderBase f in content.Folders)
480 {
481 if (f.Name != "My Suitcase" && f.Name != "Current Outfit")
482 {
483 f.Name = f.Name + " (Unavailable)";
484 keep.Add(f);
485 }
486 }
487  
488 // items directly under the root folder
489 foreach (InventoryItemBase it in content.Items)
490 it.Name = it.Name + " (Unavailable)"; ;
491  
492 // Send the new names
493 inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray());
494  
495 }
496 }
497 }
498 }
499  
500 private void ProcessInventoryForLeaving(IClientAPI client)
501 {
502 // No-op for now
503 }
504  
505 #endregion
506  
507 #region Permissions
508  
509 private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene)
510 {
511 if (m_bypassPermissions) return true;
512  
513 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(stealer))
514 {
515 SceneObjectGroup sog = null;
516 if (m_Scene.TryGetSceneObjectGroup(objectID, out sog) && sog.OwnerID == stealer)
517 return true;
518  
519 return false;
520 }
521  
522 return true;
523 }
524  
525 private bool OnTransferUserInventory(UUID itemID, UUID userID, UUID recipientID)
526 {
527 if (m_bypassPermissions) return true;
528  
529 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(recipientID))
530 return false;
531  
532 return true;
533 }
534  
535  
536 #endregion
537 }
538 }