aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Inventory/Archiver')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs279
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs247
2 files changed, 526 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
new file mode 100644
index 0000000..49006a2
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -0,0 +1,279 @@
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.CoreModules.World.Archiver;
37using OpenSim.Region.CoreModules.World.Serialiser;
38using OpenSim.Framework;
39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Communications.Cache;
41using log4net;
42
43
44namespace OpenSim.Region.CoreModules.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/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
new file mode 100644
index 0000000..f548296
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -0,0 +1,247 @@
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.CoreModules.World.Archiver;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Communications.Cache;
40using log4net;
41
42
43namespace OpenSim.Region.CoreModules.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}