aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework
diff options
context:
space:
mode:
authorDiva Canto2010-01-30 09:23:07 -0800
committerDiva Canto2010-01-30 09:23:07 -0800
commit42f978a478093da579907e15dc29680a3711b27e (patch)
tree89cf2e484d8b9e3c0c0607cb5625acda4afd858e /OpenSim/Region/CoreModules/Framework
parentOn the way to making HG inventory work. Inventory can now be accessed again. ... (diff)
downloadopensim-SC_OLD-42f978a478093da579907e15dc29680a3711b27e.zip
opensim-SC_OLD-42f978a478093da579907e15dc29680a3711b27e.tar.gz
opensim-SC_OLD-42f978a478093da579907e15dc29680a3711b27e.tar.bz2
opensim-SC_OLD-42f978a478093da579907e15dc29680a3711b27e.tar.xz
* HGScene is no more.
* Moved a few key inventory access methods from Scene.Inventory to an IInventoryAccessModule module
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework')
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs200
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs204
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs57
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs654
4 files changed, 1115 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
new file mode 100644
index 0000000..e303a1f
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -0,0 +1,200 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.Framework.Scenes.Serialization;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Services.Interfaces;
40
41//using HyperGrid.Framework;
42//using OpenSim.Region.Communications.Hypergrid;
43
44namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
45{
46 public class HGAssetMapper
47 {
48 #region Fields
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 // This maps between inventory server urls and inventory server clients
52// private Dictionary<string, InventoryClient> m_inventoryServers = new Dictionary<string, InventoryClient>();
53
54 private Scene m_scene;
55
56 #endregion
57
58 #region Constructor
59
60 public HGAssetMapper(Scene scene)
61 {
62 m_scene = scene;
63 }
64
65 #endregion
66
67 #region Internal functions
68
69 public AssetBase FetchAsset(string url, UUID assetID)
70 {
71 AssetBase asset = m_scene.AssetService.Get(url + "/" + assetID.ToString());
72
73 if (asset != null)
74 {
75 m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url);
76 return asset;
77 }
78 return null;
79 }
80
81 public bool PostAsset(string url, AssetBase asset)
82 {
83 if (asset != null)
84 {
85 // See long comment in AssetCache.AddAsset
86 if (!asset.Temporary || asset.Local)
87 {
88 // We need to copy the asset into a new asset, because
89 // we need to set its ID to be URL+UUID, so that the
90 // HGAssetService dispatches it to the remote grid.
91 // It's not pretty, but the best that can be done while
92 // not having a global naming infrastructure
93 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type);
94 Copy(asset, asset1);
95 try
96 {
97 asset1.ID = url + "/" + asset.ID;
98 }
99 catch
100 {
101 m_log.Warn("[HG ASSET MAPPER]: Oops.");
102 }
103
104 m_scene.AssetService.Store(asset1);
105 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
106 }
107 return true;
108 }
109 else
110 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache.");
111
112 return false;
113 }
114
115 private void Copy(AssetBase from, AssetBase to)
116 {
117 to.Data = from.Data;
118 to.Description = from.Description;
119 to.FullID = from.FullID;
120 to.ID = from.ID;
121 to.Local = from.Local;
122 to.Name = from.Name;
123 to.Temporary = from.Temporary;
124 to.Type = from.Type;
125
126 }
127
128 // TODO: unused
129 // private void Dump(Dictionary<UUID, bool> lst)
130 // {
131 // m_log.Debug("XXX -------- UUID DUMP ------- XXX");
132 // foreach (KeyValuePair<UUID, bool> kvp in lst)
133 // m_log.Debug(" >> " + kvp.Key + " (texture? " + kvp.Value + ")");
134 // m_log.Debug("XXX -------- UUID DUMP ------- XXX");
135 // }
136
137 #endregion
138
139
140 #region Public interface
141
142 public void Get(UUID assetID, UUID ownerID, string userAssetURL)
143 {
144 // Get the item from the remote asset server onto the local AssetCache
145 // and place an entry in m_assetMap
146
147 m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL);
148 AssetBase asset = FetchAsset(userAssetURL, assetID);
149
150 if (asset != null)
151 {
152 // OK, now fetch the inside.
153 Dictionary<UUID, int> ids = new Dictionary<UUID, int>();
154 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL);
155 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
156 foreach (UUID uuid in ids.Keys)
157 FetchAsset(userAssetURL, uuid);
158
159 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL);
160
161 }
162 else
163 m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL);
164 }
165
166
167 public void Post(UUID assetID, UUID ownerID, string userAssetURL)
168 {
169 // Post the item from the local AssetCache onto the remote asset server
170 // and place an entry in m_assetMap
171
172 m_log.Debug("[HG ASSET MAPPER]: Posting object " + assetID + " to asset server " + userAssetURL);
173 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
174 if (asset != null)
175 {
176 Dictionary<UUID, int> ids = new Dictionary<UUID, int>();
177 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty);
178 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
179 foreach (UUID uuid in ids.Keys)
180 {
181 asset = m_scene.AssetService.Get(uuid.ToString());
182 if (asset == null)
183 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid);
184 else
185 PostAsset(userAssetURL, asset);
186 }
187
188 // maybe all pieces got there...
189 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
190
191 }
192 else
193 m_log.DebugFormat("[HG ASSET MAPPER]: Something wrong with asset {0}, it could not be found", assetID);
194
195 }
196
197 #endregion
198
199 }
200}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
new file mode 100644
index 0000000..ecd7002
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -0,0 +1,204 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Connectors.Hypergrid;
36using OpenSim.Services.Interfaces;
37using OpenSim.Server.Base;
38
39using GridRegion = OpenSim.Services.Interfaces.GridRegion;
40
41using OpenMetaverse;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
46{
47 public class HGInventoryAccessModule : InventoryAccessModule, INonSharedRegionModule, IInventoryAccessModule
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private static HGAssetMapper m_assMapper;
52 public static HGAssetMapper AssetMapper
53 {
54 get { return m_assMapper; }
55 }
56
57 private bool m_Initialized = false;
58
59 #region INonSharedRegionModule
60
61 public override string Name
62 {
63 get { return "HGInventoryAccessModule"; }
64 }
65
66 public override void Initialise(IConfigSource source)
67 {
68 IConfig moduleConfig = source.Configs["Modules"];
69 if (moduleConfig != null)
70 {
71 string name = moduleConfig.GetString("InventoryAccessModule", "");
72 if (name == Name)
73 {
74 m_Enabled = true;
75 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name);
76 }
77 }
78 }
79
80 public override void AddRegion(Scene scene)
81 {
82 if (!m_Enabled)
83 return;
84
85 base.AddRegion(scene);
86 m_assMapper = new HGAssetMapper(scene);
87 scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem;
88
89 }
90
91 #endregion
92
93 #region Event handlers
94
95 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel)
96 {
97 string userAssetServer = string.Empty;
98 if (IsForeignUser(avatarID, out userAssetServer))
99 {
100 m_assMapper.Post(assetID, avatarID, userAssetServer);
101 }
102 }
103
104 #endregion
105
106 #region Overrides of Basic Inventory Access methods
107 ///
108 /// CapsUpdateInventoryItemAsset
109 ///
110 public override UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
111 {
112 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
113
114 UploadInventoryItem(remoteClient.AgentId, newAssetID, "", 0);
115
116 return newAssetID;
117 }
118
119 ///
120 /// DeleteToInventory
121 ///
122 public override UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient)
123 {
124 UUID assetID = base.DeleteToInventory(action, folderID, objectGroup, remoteClient);
125
126 if (!assetID.Equals(UUID.Zero))
127 {
128 UploadInventoryItem(remoteClient.AgentId, assetID, "", 0);
129 }
130 else
131 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
132
133 return assetID;
134 }
135
136 ///
137 /// RezObject
138 ///
139 public override SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
140 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
141 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
142 {
143 m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
144
145 //if (fromTaskID.Equals(UUID.Zero))
146 //{
147 InventoryItemBase item = new InventoryItemBase(itemID);
148 item.Owner = remoteClient.AgentId;
149 item = m_Scene.InventoryService.GetItem(item);
150 //if (item == null)
151 //{ // Fetch the item
152 // item = new InventoryItemBase();
153 // item.Owner = remoteClient.AgentId;
154 // item.ID = itemID;
155 // item = m_assMapper.Get(item, userInfo.RootFolder.ID, userInfo);
156 //}
157 string userAssetServer = string.Empty;
158 if (item != null && IsForeignUser(remoteClient.AgentId, out userAssetServer))
159 {
160 m_assMapper.Get(item.AssetID, remoteClient.AgentId, userAssetServer);
161
162 }
163 //}
164
165 // OK, we're done fetching. Pass it up to the default RezObject
166 return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
167 RezSelected, RemoveItem, fromTaskID, attachment);
168
169 }
170
171 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
172 {
173 string userAssetServer = string.Empty;
174 if (IsForeignUser(sender, out userAssetServer))
175 m_assMapper.Get(item.AssetID, sender, userAssetServer);
176
177 if (IsForeignUser(receiver, out userAssetServer))
178 m_assMapper.Post(item.AssetID, receiver, userAssetServer);
179 }
180
181 #endregion
182
183 public bool IsForeignUser(UUID userID, out string assetServerURL)
184 {
185 assetServerURL = string.Empty;
186 UserAccount account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.ScopeID, userID);
187 if (account == null) // foreign
188 {
189 ScenePresence sp = null;
190 if (m_Scene.TryGetAvatar(userID, out sp))
191 {
192 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
193 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
194 {
195 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
196 return true;
197 }
198 }
199 }
200
201 return false;
202 }
203 }
204}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
new file mode 100644
index 0000000..fcb544f
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
@@ -0,0 +1,57 @@
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
28using System;
29using System.Collections.Generic;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Services.Interfaces;
34using OpenMetaverse;
35
36namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
37{
38 public class HGUuidGatherer : UuidGatherer
39 {
40 protected string m_assetServerURL;
41 protected HGAssetMapper m_assetMapper;
42
43 public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache)
44 {
45 m_assetMapper = assMap;
46 m_assetServerURL = assetServerURL;
47 }
48
49 protected override AssetBase GetAsset(UUID uuid)
50 {
51 if (string.Empty == m_assetServerURL)
52 return m_assetCache.Get(uuid.ToString());
53 else
54 return m_assetMapper.FetchAsset(m_assetServerURL, uuid);
55 }
56 }
57}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
new file mode 100644
index 0000000..d242a34
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -0,0 +1,654 @@
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
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using System.Threading;
33
34using OpenSim.Framework;
35using OpenSim.Framework.Capabilities;
36using OpenSim.Framework.Client;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Framework.Scenes.Serialization;
40using OpenSim.Services.Interfaces;
41
42using GridRegion = OpenSim.Services.Interfaces.GridRegion;
43
44using OpenMetaverse;
45using log4net;
46using Nini.Config;
47
48namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
49{
50 public class InventoryAccessModule : INonSharedRegionModule, IInventoryAccessModule
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 protected bool m_Enabled = false;
55 protected Scene m_Scene;
56
57 #region INonSharedRegionModule
58
59 public Type ReplaceableInterface
60 {
61 get { return null; }
62 }
63
64 public virtual string Name
65 {
66 get { return "BasicInventoryAcessModule"; }
67 }
68
69 public virtual void Initialise(IConfigSource source)
70 {
71 IConfig moduleConfig = source.Configs["Modules"];
72 if (moduleConfig != null)
73 {
74 string name = moduleConfig.GetString("InventoryAccessModule", "");
75 if (name == Name)
76 {
77 m_Enabled = true;
78 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name);
79 }
80 }
81 }
82
83 public virtual void PostInitialise()
84 {
85 }
86
87 public virtual void AddRegion(Scene scene)
88 {
89 if (!m_Enabled)
90 return;
91
92 m_Scene = scene;
93
94 scene.RegisterModuleInterface<IInventoryAccessModule>(this);
95 scene.EventManager.OnNewClient += OnNewClient;
96 }
97
98 protected virtual void OnNewClient(IClientAPI client)
99 {
100
101 }
102
103 public virtual void Close()
104 {
105 if (!m_Enabled)
106 return;
107 }
108
109
110 public virtual void RemoveRegion(Scene scene)
111 {
112 if (!m_Enabled)
113 return;
114 m_Scene = null;
115 }
116
117 public virtual void RegionLoaded(Scene scene)
118 {
119 if (!m_Enabled)
120 return;
121
122 }
123
124 #endregion
125
126 #region Inventory Access
127
128 /// <summary>
129 /// Capability originating call to update the asset of an item in an agent's inventory
130 /// </summary>
131 /// <param name="remoteClient"></param>
132 /// <param name="itemID"></param>
133 /// <param name="data"></param>
134 /// <returns></returns>
135 public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
136 {
137 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
138 item = m_Scene.InventoryService.GetItem(item);
139
140 if (item != null)
141 {
142 if ((InventoryType)item.InvType == InventoryType.Notecard)
143 {
144 if (!m_Scene.Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId))
145 {
146 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
147 return UUID.Zero;
148 }
149
150 remoteClient.SendAgentAlertMessage("Notecard saved", false);
151 }
152 else if ((InventoryType)item.InvType == InventoryType.LSL)
153 {
154 if (!m_Scene.Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId))
155 {
156 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
157 return UUID.Zero;
158 }
159
160 remoteClient.SendAgentAlertMessage("Script saved", false);
161 }
162
163 AssetBase asset =
164 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data);
165 item.AssetID = asset.FullID;
166 m_Scene.AssetService.Store(asset);
167
168 m_Scene.InventoryService.UpdateItem(item);
169
170 // remoteClient.SendInventoryItemCreateUpdate(item);
171 return (asset.FullID);
172 }
173 else
174 {
175 m_log.ErrorFormat(
176 "[AGENT INVENTORY]: Could not find item {0} for caps inventory update",
177 itemID);
178 }
179
180 return UUID.Zero;
181 }
182
183 /// <summary>
184 /// Delete a scene object from a scene and place in the given avatar's inventory.
185 /// Returns the UUID of the newly created asset.
186 /// </summary>
187 /// <param name="action"></param>
188 /// <param name="folderID"></param>
189 /// <param name="objectGroup"></param>
190 /// <param name="remoteClient"> </param>
191 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
192 SceneObjectGroup objectGroup, IClientAPI remoteClient)
193 {
194 UUID assetID = UUID.Zero;
195
196 Vector3 inventoryStoredPosition = new Vector3
197 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
198 ? 250
199 : objectGroup.AbsolutePosition.X)
200 ,
201 (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
202 ? 250
203 : objectGroup.AbsolutePosition.X,
204 objectGroup.AbsolutePosition.Z);
205
206 Vector3 originalPosition = objectGroup.AbsolutePosition;
207
208 objectGroup.AbsolutePosition = inventoryStoredPosition;
209
210 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
211
212 objectGroup.AbsolutePosition = originalPosition;
213
214 // Get the user info of the item destination
215 //
216 UUID userID = UUID.Zero;
217
218 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
219 action == DeRezAction.SaveToExistingUserInventoryItem)
220 {
221 // Take or take copy require a taker
222 // Saving changes requires a local user
223 //
224 if (remoteClient == null)
225 return UUID.Zero;
226
227 userID = remoteClient.AgentId;
228 }
229 else
230 {
231 // All returns / deletes go to the object owner
232 //
233
234 userID = objectGroup.RootPart.OwnerID;
235 }
236
237 if (userID == UUID.Zero) // Can't proceed
238 {
239 return UUID.Zero;
240 }
241
242 // If we're returning someone's item, it goes back to the
243 // owner's Lost And Found folder.
244 // Delete is treated like return in this case
245 // Deleting your own items makes them go to trash
246 //
247
248 InventoryFolderBase folder = null;
249 InventoryItemBase item = null;
250
251 if (DeRezAction.SaveToExistingUserInventoryItem == action)
252 {
253 item = new InventoryItemBase(objectGroup.RootPart.FromUserInventoryItemID, userID);
254 item = m_Scene.InventoryService.GetItem(item);
255
256 //item = userInfo.RootFolder.FindItem(
257 // objectGroup.RootPart.FromUserInventoryItemID);
258
259 if (null == item)
260 {
261 m_log.DebugFormat(
262 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
263 objectGroup.Name, objectGroup.UUID);
264 return UUID.Zero;
265 }
266 }
267 else
268 {
269 // Folder magic
270 //
271 if (action == DeRezAction.Delete)
272 {
273 // Deleting someone else's item
274 //
275
276
277 if (remoteClient == null ||
278 objectGroup.OwnerID != remoteClient.AgentId)
279 {
280 // Folder skeleton may not be loaded and we
281 // have to wait for the inventory to find
282 // the destination folder
283 //
284 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
285 }
286 else
287 {
288 // Assume inventory skeleton was loaded during login
289 // and all folders can be found
290 //
291 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
292 }
293 }
294 else if (action == DeRezAction.Return)
295 {
296
297 // Dump to lost + found unconditionally
298 //
299 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
300 }
301
302 if (folderID == UUID.Zero && folder == null)
303 {
304 if (action == DeRezAction.Delete)
305 {
306 // Deletes go to trash by default
307 //
308 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
309 }
310 else
311 {
312 // Catch all. Use lost & found
313 //
314
315 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
316 }
317 }
318
319 if (folder == null) // None of the above
320 {
321 //folder = userInfo.RootFolder.FindFolder(folderID);
322 folder = new InventoryFolderBase(folderID);
323
324 if (folder == null) // Nowhere to put it
325 {
326 return UUID.Zero;
327 }
328 }
329
330 item = new InventoryItemBase();
331 item.CreatorId = objectGroup.RootPart.CreatorID.ToString();
332 item.ID = UUID.Random();
333 item.InvType = (int)InventoryType.Object;
334 item.Folder = folder.ID;
335 item.Owner = userID;
336 }
337
338 AssetBase asset = CreateAsset(
339 objectGroup.GetPartName(objectGroup.RootPart.LocalId),
340 objectGroup.GetPartDescription(objectGroup.RootPart.LocalId),
341 (sbyte)AssetType.Object,
342 Utils.StringToBytes(sceneObjectXml));
343 m_Scene.AssetService.Store(asset);
344 assetID = asset.FullID;
345
346 if (DeRezAction.SaveToExistingUserInventoryItem == action)
347 {
348 item.AssetID = asset.FullID;
349 m_Scene.InventoryService.UpdateItem(item);
350 }
351 else
352 {
353 item.AssetID = asset.FullID;
354
355 if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
356 {
357 uint perms = objectGroup.GetEffectivePermissions();
358 uint nextPerms = (perms & 7) << 13;
359 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
360 perms &= ~(uint)PermissionMask.Copy;
361 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
362 perms &= ~(uint)PermissionMask.Transfer;
363 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
364 perms &= ~(uint)PermissionMask.Modify;
365
366 item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask;
367 item.CurrentPermissions = item.BasePermissions;
368 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
369 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask;
370 item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask;
371 item.CurrentPermissions |= 8; // Slam!
372 }
373 else
374 {
375 item.BasePermissions = objectGroup.GetEffectivePermissions();
376 item.CurrentPermissions = objectGroup.GetEffectivePermissions();
377 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
378 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask;
379 item.GroupPermissions = objectGroup.RootPart.GroupMask;
380
381 item.CurrentPermissions |= 8; // Slam!
382 }
383
384 // TODO: add the new fields (Flags, Sale info, etc)
385 item.CreationDate = Util.UnixTimeSinceEpoch();
386 item.Description = asset.Description;
387 item.Name = asset.Name;
388 item.AssetType = asset.Type;
389
390 m_Scene.InventoryService.AddItem(item);
391
392 if (remoteClient != null && item.Owner == remoteClient.AgentId)
393 {
394 remoteClient.SendInventoryItemCreateUpdate(item, 0);
395 }
396 else
397 {
398 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
399 if (notifyUser != null)
400 {
401 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
402 }
403 }
404 }
405
406 return assetID;
407 }
408
409
410 /// <summary>
411 /// Rez an object into the scene from the user's inventory
412 /// </summary>
413 /// <param name="remoteClient"></param>
414 /// <param name="itemID"></param>
415 /// <param name="RayEnd"></param>
416 /// <param name="RayStart"></param>
417 /// <param name="RayTargetID"></param>
418 /// <param name="BypassRayCast"></param>
419 /// <param name="RayEndIsIntersection"></param>
420 /// <param name="RezSelected"></param>
421 /// <param name="RemoveItem"></param>
422 /// <param name="fromTaskID"></param>
423 /// <param name="attachment"></param>
424 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns>
425 public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
426 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
427 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
428 {
429 // Work out position details
430 byte bRayEndIsIntersection = (byte)0;
431
432 if (RayEndIsIntersection)
433 {
434 bRayEndIsIntersection = (byte)1;
435 }
436 else
437 {
438 bRayEndIsIntersection = (byte)0;
439 }
440
441 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
442
443
444 Vector3 pos = m_Scene.GetNewRezLocation(
445 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
446 BypassRayCast, bRayEndIsIntersection, true, scale, false);
447
448 // Rez object
449 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
450 item = m_Scene.InventoryService.GetItem(item);
451
452 if (item != null)
453 {
454 AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
455
456 if (rezAsset != null)
457 {
458 UUID itemId = UUID.Zero;
459
460 // If we have permission to copy then link the rezzed object back to the user inventory
461 // item that it came from. This allows us to enable 'save object to inventory'
462 if (!m_Scene.Permissions.BypassPermissions())
463 {
464 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy)
465 {
466 itemId = item.ID;
467 }
468 }
469 else
470 {
471 // Brave new fullperm world
472 //
473 itemId = item.ID;
474 }
475
476 string xmlData = Utils.BytesToString(rezAsset.Data);
477 SceneObjectGroup group
478 = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData);
479
480 if (!m_Scene.Permissions.CanRezObject(
481 group.Children.Count, remoteClient.AgentId, pos)
482 && !attachment)
483 {
484 // The client operates in no fail mode. It will
485 // have already removed the item from the folder
486 // if it's no copy.
487 // Put it back if it's not an attachment
488 //
489 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
490 remoteClient.SendBulkUpdateInventory(item);
491 return null;
492 }
493
494 group.ResetIDs();
495
496 if (attachment)
497 {
498 group.RootPart.ObjectFlags |= (uint)PrimFlags.Phantom;
499 group.RootPart.IsAttachment = true;
500 }
501
502 m_Scene.AddNewSceneObject(group, true);
503
504 // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z);
505 // if attachment we set it's asset id so object updates can reflect that
506 // if not, we set it's position in world.
507 if (!attachment)
508 {
509 float offsetHeight = 0;
510 pos = m_Scene.GetNewRezLocation(
511 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
512 BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false);
513 pos.Z += offsetHeight;
514 group.AbsolutePosition = pos;
515 // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight);
516
517 }
518 else
519 {
520 group.SetFromItemID(itemID);
521 }
522
523 SceneObjectPart rootPart = null;
524 try
525 {
526 rootPart = group.GetChildPart(group.UUID);
527 }
528 catch (NullReferenceException)
529 {
530 string isAttachment = "";
531
532 if (attachment)
533 isAttachment = " Object was an attachment";
534
535 m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment);
536 }
537
538 // Since renaming the item in the inventory does not affect the name stored
539 // in the serialization, transfer the correct name from the inventory to the
540 // object itself before we rez.
541 rootPart.Name = item.Name;
542 rootPart.Description = item.Description;
543
544 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values);
545
546 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
547 if (rootPart.OwnerID != item.Owner)
548 {
549 //Need to kill the for sale here
550 rootPart.ObjectSaleType = 0;
551 rootPart.SalePrice = 10;
552
553 if (m_Scene.Permissions.PropagatePermissions())
554 {
555 if ((item.CurrentPermissions & 8) != 0)
556 {
557 foreach (SceneObjectPart part in partList)
558 {
559 part.EveryoneMask = item.EveryOnePermissions;
560 part.NextOwnerMask = item.NextPermissions;
561 part.GroupMask = 0; // DO NOT propagate here
562 }
563 }
564 group.ApplyNextOwnerPermissions();
565 }
566 }
567
568 foreach (SceneObjectPart part in partList)
569 {
570 if (part.OwnerID != item.Owner)
571 {
572 part.LastOwnerID = part.OwnerID;
573 part.OwnerID = item.Owner;
574 part.Inventory.ChangeInventoryOwner(item.Owner);
575 }
576 else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam!
577 {
578 part.EveryoneMask = item.EveryOnePermissions;
579 part.NextOwnerMask = item.NextPermissions;
580
581 part.GroupMask = 0; // DO NOT propagate here
582 }
583 }
584
585 rootPart.TrimPermissions();
586
587 if (!attachment)
588 {
589 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
590 {
591 group.ClearPartAttachmentData();
592 }
593 }
594
595 if (!attachment)
596 {
597 // Fire on_rez
598 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0);
599
600 rootPart.ScheduleFullUpdate();
601 }
602
603 if (!m_Scene.Permissions.BypassPermissions())
604 {
605 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
606 {
607 // If this is done on attachments, no
608 // copy ones will be lost, so avoid it
609 //
610 if (!attachment)
611 {
612 List<UUID> uuids = new List<UUID>();
613 uuids.Add(item.ID);
614 m_Scene.InventoryService.DeleteItems(item.Owner, uuids);
615 }
616 }
617 }
618
619 return rootPart.ParentGroup;
620 }
621 }
622
623 return null;
624 }
625
626 public virtual void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
627 {
628 }
629
630 #endregion
631
632 #region Misc
633
634 /// <summary>
635 /// Create a new asset data structure.
636 /// </summary>
637 /// <param name="name"></param>
638 /// <param name="description"></param>
639 /// <param name="invType"></param>
640 /// <param name="assetType"></param>
641 /// <param name="data"></param>
642 /// <returns></returns>
643 private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data)
644 {
645 AssetBase asset = new AssetBase(UUID.Random(), name, assetType);
646 asset.Description = description;
647 asset.Data = (data == null) ? new byte[1] : data;
648
649 return asset;
650 }
651
652 #endregion
653 }
654}