OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
HGInventoryAccessModule.cs
Go to the documentation of this file.
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 
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")]
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 
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 
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 
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 
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 }
override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
OpenSim.Services.Interfaces.GridRegion GridRegion
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
Dictionary< string, object > ServiceURLs
sbyte Type
(sbyte) AssetType enum
Definition: AssetBase.cs:198
Asset class. All Assets are reference by this class or a class derived from this class ...
Definition: AssetBase.cs:49
override UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
override void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
Circuit data for an agent. Connection information shared between regions that accept UDP connections ...
Inventory Item - contains all the properties associated with an individual inventory piece...
void PostInventoryAsset(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel)
override SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
override string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
override void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
override bool UpdateInventoryItemAsset(UUID ownerID, InventoryItemBase item, AssetBase asset)
void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout)
virtual string Name
The name of the node (64 characters or less)
UUID FullID
Asset UUID
Definition: AssetBase.cs:168
bool TryGetScenePresence(UUID agentID, out object scenePresence)
uint teleportFlags
How this agent got here
This maintains the relationship between a UUID and a user name.
Used to serialize a whole inventory for transfer over the network.