aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Avatar/Inventory
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/Inventory')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs279
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs247
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs389
3 files changed, 0 insertions, 915 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
deleted file mode 100644
index 3a58202..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ /dev/null
@@ -1,279 +0,0 @@
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 OpenSim 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.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Xml;
34using OpenMetaverse;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Environment.Modules.World.Archiver;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Communications.Cache;
40using log4net;
41using OpenSim.Region.Environment.Modules.World.Serialiser;
42
43
44namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Archiver
45{
46 public class InventoryArchiveReadRequest
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 protected Scene scene;
51 protected TarArchiveReader archive;
52 private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding();
53
54 CommunicationsManager commsManager;
55
56 public InventoryArchiveReadRequest(Scene currentScene, CommunicationsManager commsManager)
57 {
58 //List<string> serialisedObjects = new List<string>();
59 scene = currentScene;
60 this.commsManager = commsManager;
61 }
62
63 protected InventoryItemBase loadInvItem(string path, string contents)
64 {
65 InventoryItemBase item = new InventoryItemBase();
66 StringReader sr = new StringReader(contents);
67 XmlTextReader reader = new XmlTextReader(sr);
68
69 if (contents.Equals("")) return null;
70
71 reader.ReadStartElement("InventoryObject");
72 reader.ReadStartElement("Name");
73 item.Name = reader.ReadString();
74 reader.ReadEndElement();
75 reader.ReadStartElement("ID");
76 item.ID = UUID.Parse(reader.ReadString());
77 reader.ReadEndElement();
78 reader.ReadStartElement("InvType");
79 item.InvType = System.Convert.ToInt32(reader.ReadString());
80 reader.ReadEndElement();
81 reader.ReadStartElement("CreatorUUID");
82 item.Creator = UUID.Parse(reader.ReadString());
83 reader.ReadEndElement();
84 reader.ReadStartElement("CreationDate");
85 item.CreationDate = System.Convert.ToInt32(reader.ReadString());
86 reader.ReadEndElement();
87 reader.ReadStartElement("Owner");
88 item.Owner = UUID.Parse(reader.ReadString());
89 reader.ReadEndElement();
90 //No description would kill it
91 if (reader.IsEmptyElement)
92 {
93 reader.ReadStartElement("Description");
94 }
95 else
96 {
97 reader.ReadStartElement("Description");
98 item.Description = reader.ReadString();
99 reader.ReadEndElement();
100 }
101 reader.ReadStartElement("AssetType");
102 item.AssetType = System.Convert.ToInt32(reader.ReadString());
103 reader.ReadEndElement();
104 reader.ReadStartElement("AssetID");
105 item.AssetID = UUID.Parse(reader.ReadString());
106 reader.ReadEndElement();
107 reader.ReadStartElement("SaleType");
108 item.SaleType = System.Convert.ToByte(reader.ReadString());
109 reader.ReadEndElement();
110 reader.ReadStartElement("SalePrice");
111 item.SalePrice = System.Convert.ToInt32(reader.ReadString());
112 reader.ReadEndElement();
113 reader.ReadStartElement("BasePermissions");
114 item.BasePermissions = System.Convert.ToUInt32(reader.ReadString());
115 reader.ReadEndElement();
116 reader.ReadStartElement("CurrentPermissions");
117 item.CurrentPermissions = System.Convert.ToUInt32(reader.ReadString());
118 reader.ReadEndElement();
119 reader.ReadStartElement("EveryOnePermssions");
120 item.EveryOnePermissions = System.Convert.ToUInt32(reader.ReadString());
121 reader.ReadEndElement();
122 reader.ReadStartElement("NextPermissions");
123 item.NextPermissions = System.Convert.ToUInt32(reader.ReadString());
124 reader.ReadEndElement();
125 reader.ReadStartElement("Flags");
126 item.Flags = System.Convert.ToUInt32(reader.ReadString());
127 reader.ReadEndElement();
128 reader.ReadStartElement("GroupID");
129 item.GroupID = UUID.Parse(reader.ReadString());
130 reader.ReadEndElement();
131 reader.ReadStartElement("GroupOwned");
132 item.GroupOwned = System.Convert.ToBoolean(reader.ReadString());
133 reader.ReadEndElement();
134 //reader.ReadStartElement("ParentFolderID");
135 //item.Folder = UUID.Parse(reader.ReadString());
136 //reader.ReadEndElement();
137 //reader.ReadEndElement();
138
139 return item;
140 }
141
142 public void execute(string firstName, string lastName, string invPath, string loadPath)
143 {
144 string filePath = "ERROR";
145 int successfulAssetRestores = 0;
146 int failedAssetRestores = 0;
147 int successfulItemRestores = 0;
148
149 UserProfileData userProfile = commsManager.UserService.GetUserProfile(firstName, lastName);
150 if (null == userProfile)
151 {
152 m_log.ErrorFormat("[CONSOLE]: Failed to find user {0} {1}", firstName, lastName);
153 return;
154 }
155
156 CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userProfile.ID);
157 if (null == userInfo)
158 {
159 m_log.ErrorFormat(
160 "[CONSOLE]: Failed to find user info for {0} {1} {2}",
161 firstName, lastName, userProfile.ID);
162
163 return;
164 }
165
166 if (!userInfo.HasReceivedInventory)
167 {
168 m_log.ErrorFormat(
169 "[CONSOLE]: Have not yet received inventory info for user {0} {1} {2}",
170 firstName, lastName, userProfile.ID);
171
172 return;
173 }
174
175 InventoryFolderImpl inventoryFolder = userInfo.RootFolder.FindFolderByPath(invPath);
176
177 if (null == inventoryFolder)
178 {
179 // TODO: Later on, automatically create this folder if it does not exist
180 m_log.ErrorFormat("[ARCHIVER]: Inventory path {0} does not exist", invPath);
181
182 return;
183 }
184
185 archive
186 = new TarArchiveReader(new GZipStream(
187 new FileStream(loadPath, FileMode.Open), CompressionMode.Decompress));
188
189 byte[] data;
190 TarArchiveReader.TarEntryType entryType;
191 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
192 {
193 if (entryType == TarArchiveReader.TarEntryType.TYPE_DIRECTORY) {
194 m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", filePath);
195 } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
196 {
197 if (LoadAsset(filePath, data))
198 successfulAssetRestores++;
199 else
200 failedAssetRestores++;
201 }
202 else
203 {
204 InventoryItemBase item = loadInvItem(filePath, m_asciiEncoding.GetString(data));
205
206 if (item != null)
207 {
208 item.Creator = userProfile.ID;
209 item.Owner = userProfile.ID;
210
211 // Reset folder ID to the one in which we want to load it
212 // TODO: Properly restore entire folder structure. At the moment all items are dumped in this
213 // single folder no matter where in the saved folder structure they are.
214 item.Folder = inventoryFolder.ID;
215
216 userInfo.AddItem(item);
217 successfulItemRestores++;
218 }
219 }
220 }
221
222 archive.Close();
223
224 m_log.DebugFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores);
225 m_log.InfoFormat("[ARCHIVER]: Restored {0} items", successfulItemRestores);
226 }
227
228 /// <summary>
229 /// Load an asset
230 /// </summary>
231 /// <param name="assetFilename"></param>
232 /// <param name="data"></param>
233 /// <returns>true if asset was successfully loaded, false otherwise</returns>
234 private bool LoadAsset(string assetPath, byte[] data)
235 {
236 //IRegionSerialiser serialiser = scene.RequestModuleInterface<IRegionSerialiser>();
237 // Right now we're nastily obtaining the UUID from the filename
238 string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
239 int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
240
241 if (i == -1)
242 {
243 m_log.ErrorFormat(
244 "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping",
245 assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
246
247 return false;
248 }
249
250 string extension = filename.Substring(i);
251 string uuid = filename.Remove(filename.Length - extension.Length);
252
253 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
254 {
255 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
256
257 m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
258
259 AssetBase asset = new AssetBase(new UUID(uuid), "RandomName");
260
261 asset.Metadata.Type = assetType;
262 asset.Data = data;
263
264 scene.AssetCache.AddAsset(asset);
265
266
267 return true;
268 }
269 else
270 {
271 m_log.ErrorFormat(
272 "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
273 assetPath, extension);
274
275 return false;
276 }
277 }
278 }
279}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
deleted file mode 100644
index e23f2a8..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ /dev/null
@@ -1,247 +0,0 @@
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 OpenSim 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.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Xml;
34using OpenMetaverse;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Environment.Modules.World.Archiver;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Communications.Cache;
40using log4net;
41
42
43namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Archiver
44{
45 public class InventoryArchiveWriteRequest
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 protected Scene scene;
50 protected TarArchiveWriter archive;
51 protected CommunicationsManager commsManager;
52 Dictionary<UUID, int> assetUuids;
53
54 /// <value>
55 /// The path to which the inventory archive will be saved.
56 /// </value>
57 private string m_savePath;
58
59 public InventoryArchiveWriteRequest(Scene currentScene, CommunicationsManager commsManager)
60 {
61 scene = currentScene;
62 archive = new TarArchiveWriter();
63 this.commsManager = commsManager;
64 assetUuids = new Dictionary<UUID, int>();
65 }
66
67 protected void ReceivedAllAssets(IDictionary<UUID, AssetBase> assetsFound, ICollection<UUID> assetsNotFoundUuids)
68 {
69 AssetsArchiver assetsArchiver = new AssetsArchiver(assetsFound);
70 assetsArchiver.Archive(archive);
71 archive.WriteTar(new GZipStream(new FileStream(m_savePath, FileMode.Create), CompressionMode.Compress));
72 }
73
74 protected void saveInvItem(InventoryItemBase inventoryItem, string path)
75 {
76 string filename
77 = string.Format("{0}{1}_{2}.xml",
78 path, inventoryItem.Name, inventoryItem.ID);
79 StringWriter sw = new StringWriter();
80 XmlTextWriter writer = new XmlTextWriter(sw);
81 writer.WriteStartElement("InventoryObject");
82 writer.WriteStartElement("Name");
83 writer.WriteString(inventoryItem.Name);
84 writer.WriteEndElement();
85 writer.WriteStartElement("ID");
86 writer.WriteString(inventoryItem.ID.ToString());
87 writer.WriteEndElement();
88 writer.WriteStartElement("InvType");
89 writer.WriteString(inventoryItem.InvType.ToString());
90 writer.WriteEndElement();
91 writer.WriteStartElement("CreatorUUID");
92 writer.WriteString(inventoryItem.Creator.ToString());
93 writer.WriteEndElement();
94 writer.WriteStartElement("CreationDate");
95 writer.WriteString(inventoryItem.CreationDate.ToString());
96 writer.WriteEndElement();
97 writer.WriteStartElement("Owner");
98 writer.WriteString(inventoryItem.Owner.ToString());
99 writer.WriteEndElement();
100 writer.WriteStartElement("Description");
101 if (inventoryItem.Description.Length > 0)
102 writer.WriteString(inventoryItem.Description);
103 else writer.WriteString("No Description");
104 writer.WriteEndElement();
105 writer.WriteStartElement("AssetType");
106 writer.WriteString(inventoryItem.AssetType.ToString());
107 writer.WriteEndElement();
108 writer.WriteStartElement("AssetID");
109 writer.WriteString(inventoryItem.AssetID.ToString());
110 writer.WriteEndElement();
111 writer.WriteStartElement("SaleType");
112 writer.WriteString(inventoryItem.SaleType.ToString());
113 writer.WriteEndElement();
114 writer.WriteStartElement("SalePrice");
115 writer.WriteString(inventoryItem.SalePrice.ToString());
116 writer.WriteEndElement();
117 writer.WriteStartElement("BasePermissions");
118 writer.WriteString(inventoryItem.BasePermissions.ToString());
119 writer.WriteEndElement();
120 writer.WriteStartElement("CurrentPermissions");
121 writer.WriteString(inventoryItem.CurrentPermissions.ToString());
122 writer.WriteEndElement();
123 writer.WriteStartElement("EveryOnePermssions");
124 writer.WriteString(inventoryItem.EveryOnePermissions.ToString());
125 writer.WriteEndElement();
126 writer.WriteStartElement("NextPermissions");
127 writer.WriteString(inventoryItem.NextPermissions.ToString());
128 writer.WriteEndElement();
129 writer.WriteStartElement("Flags");
130 writer.WriteString(inventoryItem.Flags.ToString());
131 writer.WriteEndElement();
132 writer.WriteStartElement("GroupID");
133 writer.WriteString(inventoryItem.GroupID.ToString());
134 writer.WriteEndElement();
135 writer.WriteStartElement("GroupOwned");
136 writer.WriteString(inventoryItem.GroupOwned.ToString());
137 writer.WriteEndElement();
138 writer.WriteStartElement("ParentFolderID");
139 writer.WriteString(inventoryItem.Folder.ToString());
140 writer.WriteEndElement();
141 writer.WriteEndElement();
142
143 archive.AddFile(filename, sw.ToString());
144
145 assetUuids[inventoryItem.AssetID] = 1;
146 }
147
148 protected void saveInvDir(InventoryFolderImpl inventoryFolder, string path)
149 {
150 List<InventoryFolderImpl> inventories = inventoryFolder.RequestListOfFolderImpls();
151 List<InventoryItemBase> items = inventoryFolder.RequestListOfItems();
152 string newPath = path + inventoryFolder.Name + InventoryFolderImpl.PATH_DELIMITER;
153 archive.AddDir(newPath);
154 foreach (InventoryFolderImpl folder in inventories)
155 {
156 saveInvDir(folder, newPath);
157 }
158 foreach (InventoryItemBase item in items)
159 {
160 saveInvItem(item, newPath);
161 }
162 }
163
164 public void execute(string firstName, string lastName, string invPath, string savePath)
165 {
166 m_savePath = savePath;
167
168 UserProfileData userProfile = commsManager.UserService.GetUserProfile(firstName, lastName);
169 if (null == userProfile)
170 {
171 m_log.ErrorFormat("[CONSOLE]: Failed to find user {0} {1}", firstName, lastName);
172 return;
173 }
174
175 CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(userProfile.ID);
176 if (null == userInfo)
177 {
178 m_log.ErrorFormat("[CONSOLE]: Failed to find user info for {0} {1} {2}", firstName, lastName, userProfile.ID);
179 return;
180 }
181
182 InventoryFolderImpl inventoryFolder = null;
183 InventoryItemBase inventoryItem = null;
184
185 if (userInfo.HasReceivedInventory)
186 {
187 // Eliminate double slashes and any leading / on the path. This might be better done within InventoryFolderImpl
188 // itself (possibly at a small loss in efficiency).
189 string[] components
190 = invPath.Split(new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);
191 invPath = String.Empty;
192 foreach (string c in components)
193 {
194 invPath += c + InventoryFolderImpl.PATH_DELIMITER;
195 }
196
197 // Annoyingly Split actually returns the original string if the input string consists only of delimiters
198 // Therefore if we still start with a / after the split, then we need the root folder
199 if (invPath.Length == 0)
200 {
201 inventoryFolder = userInfo.RootFolder;
202 }
203 else
204 {
205 invPath = invPath.Remove(invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
206 inventoryFolder = userInfo.RootFolder.FindFolderByPath(invPath);
207 }
208
209 // The path may point to an item instead
210 if (inventoryFolder == null)
211 {
212 inventoryItem = userInfo.RootFolder.FindItemByPath(invPath);
213 }
214 }
215 else
216 {
217 m_log.ErrorFormat("[CONSOLE]: Have not yet received inventory info for user {0} {1} {2}", firstName, lastName, userProfile.ID);
218 return;
219 }
220
221 if (null == inventoryFolder)
222 {
223 if (null == inventoryItem)
224 {
225 m_log.ErrorFormat("[CONSOLE]: Could not find inventory entry at path {0}", invPath);
226 return;
227 }
228 else
229 {
230 m_log.InfoFormat("[CONSOLE]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID,
231 invPath);
232 //get and export item info
233 saveInvItem(inventoryItem, invPath);
234 }
235 }
236 else
237 {
238 m_log.InfoFormat("[CONSOLE]: Found folder {0} {1} at {2}", inventoryFolder.Name, inventoryFolder.ID,
239 invPath);
240 //recurse through all dirs getting dirs and files
241 saveInvDir(inventoryFolder, "");
242 }
243
244 new AssetsRequest(assetUuids.Keys, scene.AssetCache, ReceivedAllAssets).Execute();
245 }
246 }
247}
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
deleted file mode 100644
index 62fb3a2..0000000
--- a/OpenSim/Region/Environment/Modules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ /dev/null
@@ -1,389 +0,0 @@
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 OpenSim 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;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Framework.Communications.Cache;
39
40namespace OpenSim.Region.Environment.Modules.Avatar.Inventory.Transfer
41{
42 public class InventoryTransferModule : IInventoryTransferModule, IRegionModule
43 {
44 private static readonly ILog m_log
45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 /// <summary>
48 private List<Scene> m_Scenelist = new List<Scene>();
49 private Dictionary<UUID, Scene> m_AgentRegions =
50 new Dictionary<UUID, Scene>();
51
52 private IMessageTransferModule m_TransferModule = null;
53
54 #region IRegionModule Members
55
56 public void Initialise(Scene scene, IConfigSource config)
57 {
58 if (config.Configs["Messaging"] != null)
59 {
60 // Allow disabling this module in config
61 //
62 if (config.Configs["Messaging"].GetString(
63 "InventoryTransferModule", "InventoryTransferModule") !=
64 "InventoryTransferModule")
65 return;
66 }
67
68 if (!m_Scenelist.Contains(scene))
69 {
70 if (m_Scenelist.Count == 0)
71 {
72 m_TransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
73 if (m_TransferModule == null)
74 m_log.Error("[INVENTORY TRANSFER] No Message transfer module found, transfers will be local only");
75 }
76
77 m_Scenelist.Add(scene);
78
79 scene.RegisterModuleInterface<IInventoryTransferModule>(this);
80
81 scene.EventManager.OnNewClient += OnNewClient;
82 scene.EventManager.OnClientClosed += ClientLoggedOut;
83 }
84 }
85
86 public void PostInitialise()
87 {
88 }
89
90 public void Close()
91 {
92 }
93
94 public string Name
95 {
96 get { return "InventoryModule"; }
97 }
98
99 public bool IsSharedModule
100 {
101 get { return true; }
102 }
103
104 #endregion
105
106 private void OnNewClient(IClientAPI client)
107 {
108 // Inventory giving is conducted via instant message
109 client.OnInstantMessage += OnInstantMessage;
110 }
111
112 private Scene FindClientScene(UUID agentId)
113 {
114 lock (m_Scenelist)
115 {
116 foreach (Scene scene in m_Scenelist)
117 {
118 ScenePresence presence = scene.GetScenePresence(agentId);
119 if (presence != null)
120 {
121 if (!presence.IsChildAgent)
122 return scene;
123 }
124 }
125 }
126 return null;
127 }
128
129 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
130 {
131 Scene scene = FindClientScene(client.AgentId);
132
133 if (scene == null) // Something seriously wrong here.
134 return;
135
136 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
137 {
138 //m_log.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0]));
139
140 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
141 UUID copyID;
142
143 // First byte is the asset type
144 AssetType assetType = (AssetType)im.binaryBucket[0];
145
146 if (AssetType.Folder == assetType)
147 {
148 UUID folderID = new UUID(im.binaryBucket, 1);
149
150 m_log.DebugFormat("[AGENT INVENTORY]: Inserting original folder {0} "+
151 "into agent {1}'s inventory",
152 folderID, new UUID(im.toAgentID));
153
154 InventoryFolderImpl folderCopy
155 = scene.GiveInventoryFolder(new UUID(im.toAgentID), client.AgentId, folderID, UUID.Zero);
156
157 if (folderCopy == null)
158 {
159 client.SendAgentAlertMessage("Can't find folder to give. Nothing given.", false);
160 return;
161 }
162
163 // The outgoing binary bucket should contain only the byte which signals an asset folder is
164 // being copied and the following bytes for the copied folder's UUID
165 copyID = folderCopy.ID;
166 byte[] copyIDBytes = copyID.GetBytes();
167 im.binaryBucket = new byte[1 + copyIDBytes.Length];
168 im.binaryBucket[0] = (byte)AssetType.Folder;
169 Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length);
170
171 if (user != null && !user.IsChildAgent)
172 {
173 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
174 }
175 }
176 else
177 {
178 // First byte of the array is probably the item type
179 // Next 16 bytes are the UUID
180
181 UUID itemID = new UUID(im.binaryBucket, 1);
182
183 m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+
184 "into agent {1}'s inventory",
185 itemID, new UUID(im.toAgentID));
186
187 InventoryItemBase itemCopy = scene.GiveInventoryItem(
188 new UUID(im.toAgentID),
189 client.AgentId, itemID);
190
191 if (itemCopy == null)
192 {
193 client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
194 return;
195 }
196
197 copyID = itemCopy.ID;
198 Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16);
199
200 if (user != null && !user.IsChildAgent)
201 {
202 user.ControllingClient.SendBulkUpdateInventory(itemCopy);
203 }
204 }
205
206 // Send the IM to the recipient. The item is already
207 // in their inventory, so it will not be lost if
208 // they are offline.
209 //
210 if (user != null && !user.IsChildAgent)
211 {
212 // And notify. Transaction ID is the item ID. We get that
213 // same ID back on the reply so we know what to act on
214 //
215 user.ControllingClient.SendInstantMessage(
216 new UUID(im.fromAgentID), im.message,
217 new UUID(im.toAgentID),
218 im.fromAgentName, im.dialog, im.timestamp,
219 copyID, false, im.binaryBucket);
220
221 return;
222 }
223 else
224 {
225 if (m_TransferModule != null)
226 m_TransferModule.SendInstantMessage(im, delegate(bool success) {} );
227 }
228 }
229 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
230 {
231 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
232
233 if (user != null) // Local
234 {
235 user.ControllingClient.SendInstantMessage(
236 new UUID(im.fromAgentID), im.message,
237 new UUID(im.toAgentID),
238 im.fromAgentName, im.dialog, im.timestamp,
239 UUID.Zero, false, im.binaryBucket);
240 }
241 else
242 {
243 if (m_TransferModule != null)
244 m_TransferModule.SendInstantMessage(im, delegate(bool success) {} );
245 }
246 }
247 else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
248 {
249 // Here, the recipient is local and we can assume that the
250 // inventory is loaded. Courtesy of the above bulk update,
251 // It will have been pushed to the client, too
252 //
253
254 CachedUserInfo userInfo =
255 scene.CommsManager.UserProfileCacheService.
256 GetUserDetails(client.AgentId);
257
258 if (userInfo != null)
259 {
260 InventoryFolderImpl trashFolder =
261 userInfo.FindFolderForType((int)AssetType.TrashFolder);
262
263 UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
264
265 InventoryItemBase item = userInfo.RootFolder.FindItem(inventoryEntityID);
266 InventoryFolderBase folder = null;
267
268 if (item != null && trashFolder != null)
269 {
270 item.Folder = trashFolder.ID;
271
272 userInfo.DeleteItem(inventoryEntityID);
273
274 scene.AddInventoryItem(client, item);
275 }
276 else
277 {
278 folder = userInfo.RootFolder.FindFolder(inventoryEntityID);
279
280 if (folder != null & trashFolder != null)
281 {
282 userInfo.MoveFolder(inventoryEntityID, trashFolder.ID);
283 }
284 }
285
286 if ((null == item && null == folder) | null == trashFolder)
287 {
288 string reason = String.Empty;
289
290 if (trashFolder == null)
291 reason += " Trash folder not found.";
292 if (item == null)
293 reason += " Item not found.";
294 if (folder == null)
295 reason += " Folder not found.";
296
297 client.SendAgentAlertMessage("Unable to delete "+
298 "received inventory" + reason, false);
299 }
300 }
301
302 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
303
304 if (user != null) // Local
305 {
306 user.ControllingClient.SendInstantMessage(
307 new UUID(im.fromAgentID), im.message,
308 new UUID(im.toAgentID),
309 im.fromAgentName, im.dialog, im.timestamp,
310 UUID.Zero, false, im.binaryBucket);
311 }
312 else
313 {
314 if (m_TransferModule != null)
315 m_TransferModule.SendInstantMessage(im, delegate(bool success) {} );
316 }
317 }
318 }
319
320 public void SetRootAgentScene(UUID agentID, Scene scene)
321 {
322 m_AgentRegions[agentID] = scene;
323 }
324
325 public bool NeedSceneCacheClear(UUID agentID, Scene scene)
326 {
327 if (!m_AgentRegions.ContainsKey(agentID))
328 {
329 // Since we can get here two ways, we need to scan
330 // the scenes here. This is somewhat more expensive
331 // but helps avoid a nasty bug
332 //
333
334 foreach (Scene s in m_Scenelist)
335 {
336 ScenePresence presence;
337
338 if (s.TryGetAvatar(agentID, out presence))
339 {
340 // If the agent is in this scene, then we
341 // are being called twice in a single
342 // teleport. This is wasteful of cycles
343 // but harmless due to this 2nd level check
344 //
345 // If the agent is found in another scene
346 // then the list wasn't current
347 //
348 // If the agent is totally unknown, then what
349 // are we even doing here??
350 //
351 if (s == scene)
352 {
353 //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
354 return true;
355 }
356 else
357 {
358 //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
359 return false;
360 }
361 }
362 }
363 //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
364 return true;
365 }
366
367 // The agent is left in current Scene, so we must be
368 // going to another instance
369 //
370 if (m_AgentRegions[agentID] == scene)
371 {
372 //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
373 m_AgentRegions.Remove(agentID);
374 return true;
375 }
376
377 // Another region has claimed the agent
378 //
379 //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
380 return false;
381 }
382
383 public void ClientLoggedOut(UUID agentID)
384 {
385 if (m_AgentRegions.ContainsKey(agentID))
386 m_AgentRegions.Remove(agentID);
387 }
388 }
389}