aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs223
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs29
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs2
-rw-r--r--OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs2
-rw-r--r--OpenSim/Services/Interfaces/IGridUserService.cs2
9 files changed, 226 insertions, 116 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index b255415..2979e29 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -268,7 +268,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
268 268
269 if (m_Friends.ContainsKey(agentID)) 269 if (m_Friends.ContainsKey(agentID))
270 { 270 {
271 if (m_Friends[agentID].RegionID == UUID.Zero && m_Friends[agentID].Friends == null) 271 if (m_Friends[agentID].RegionID == UUID.Zero)
272 { 272 {
273 m_Friends[agentID].Friends = 273 m_Friends[agentID].Friends =
274 m_FriendsService.GetFriends(agentID); 274 m_FriendsService.GetFriends(agentID);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 806aa4f..60d1720 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -97,9 +97,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
97 int successfulAssetRestores = 0; 97 int successfulAssetRestores = 0;
98 int failedAssetRestores = 0; 98 int failedAssetRestores = 0;
99 int successfulItemRestores = 0; 99 int successfulItemRestores = 0;
100 List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>(); 100
101 List<InventoryNodeBase> loadedNodes = new List<InventoryNodeBase>();
101 102
102 //InventoryFolderImpl rootDestinationFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath);
103 InventoryFolderBase rootDestinationFolder 103 InventoryFolderBase rootDestinationFolder
104 = InventoryArchiveUtils.FindFolderByPath( 104 = InventoryArchiveUtils.FindFolderByPath(
105 m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); 105 m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath);
@@ -109,14 +109,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
109 // Possibly provide an option later on to automatically create this folder if it does not exist 109 // Possibly provide an option later on to automatically create this folder if it does not exist
110 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); 110 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
111 111
112 return nodesLoaded; 112 return loadedNodes;
113 } 113 }
114 114
115 archive = new TarArchiveReader(m_loadStream); 115 archive = new TarArchiveReader(m_loadStream);
116 116
117 // In order to load identically named folders, we need to keep track of the folders that we have already 117 // In order to load identically named folders, we need to keep track of the folders that we have already
118 // created 118 // resolved
119 Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>(); 119 Dictionary <string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase>();
120 120
121 byte[] data; 121 byte[] data;
122 TarArchiveReader.TarEntryType entryType; 122 TarArchiveReader.TarEntryType entryType;
@@ -139,10 +139,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
139 } 139 }
140 else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) 140 else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
141 { 141 {
142 filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length);
143
144 // Trim off the file portion if we aren't already dealing with a directory path
145 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
146 filePath = filePath.Remove(filePath.LastIndexOf("/") + 1);
147
142 InventoryFolderBase foundFolder 148 InventoryFolderBase foundFolder
143 = ReplicateArchivePathToUserInventory( 149 = ReplicateArchivePathToUserInventory(
144 filePath, TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType, 150 filePath, rootDestinationFolder, resolvedFolders, loadedNodes);
145 rootDestinationFolder, foldersCreated, nodesLoaded);
146 151
147 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) 152 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
148 { 153 {
@@ -155,7 +160,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
155 // If we're loading an item directly into the given destination folder then we need to record 160 // If we're loading an item directly into the given destination folder then we need to record
156 // it separately from any loaded root folders 161 // it separately from any loaded root folders
157 if (rootDestinationFolder == foundFolder) 162 if (rootDestinationFolder == foundFolder)
158 nodesLoaded.Add(item); 163 loadedNodes.Add(item);
159 } 164 }
160 } 165 }
161 } 166 }
@@ -171,7 +176,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
171 successfulAssetRestores, failedAssetRestores); 176 successfulAssetRestores, failedAssetRestores);
172 m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); 177 m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores);
173 178
174 return nodesLoaded; 179 return loadedNodes;
175 } 180 }
176 181
177 public void Close() 182 public void Close()
@@ -184,54 +189,119 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
184 /// Replicate the inventory paths in the archive to the user's inventory as necessary. 189 /// Replicate the inventory paths in the archive to the user's inventory as necessary.
185 /// </summary> 190 /// </summary>
186 /// <param name="archivePath">The item archive path to replicate</param> 191 /// <param name="archivePath">The item archive path to replicate</param>
187 /// <param name="isDir">Is the path we're dealing with a directory?</param>
188 /// <param name="rootDestinationFolder">The root folder for the inventory load</param> 192 /// <param name="rootDestinationFolder">The root folder for the inventory load</param>
189 /// <param name="foldersCreated"> 193 /// <param name="resolvedFolders">
190 /// The folders created so far. This method will add more folders if necessary 194 /// The folders that we have resolved so far for a given archive path.
195 /// This method will add more folders if necessary
191 /// </param> 196 /// </param>
192 /// <param name="nodesLoaded"> 197 /// <param name="loadedNodes">
193 /// Track the inventory nodes created. This is distinct from the folders created since for a particular folder 198 /// Track the inventory nodes created.
194 /// chain, only the root node needs to be recorded
195 /// </param> 199 /// </param>
196 /// <returns>The last user inventory folder created or found for the archive path</returns> 200 /// <returns>The last user inventory folder created or found for the archive path</returns>
197 public InventoryFolderBase ReplicateArchivePathToUserInventory( 201 public InventoryFolderBase ReplicateArchivePathToUserInventory(
198 string archivePath, 202 string archivePath,
199 bool isDir,
200 InventoryFolderBase rootDestFolder, 203 InventoryFolderBase rootDestFolder,
201 Dictionary <string, InventoryFolderBase> foldersCreated, 204 Dictionary <string, InventoryFolderBase> resolvedFolders,
202 List<InventoryNodeBase> nodesLoaded) 205 List<InventoryNodeBase> loadedNodes)
203 { 206 {
204 archivePath = archivePath.Substring(ArchiveConstants.INVENTORY_PATH.Length);
205
206 // Remove the file portion if we aren't already dealing with a directory path
207 if (!isDir)
208 archivePath = archivePath.Remove(archivePath.LastIndexOf("/") + 1);
209
210 string originalArchivePath = archivePath; 207 string originalArchivePath = archivePath;
211 208
212// m_log.DebugFormat( 209// m_log.DebugFormat(
213// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); 210// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
211
212 InventoryFolderBase destFolder = ResolveDestinationFolder(rootDestFolder, ref archivePath, resolvedFolders);
213
214// m_log.DebugFormat(
215// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]",
216// originalArchivePath, archivePath);
217
218 string archivePathSectionToCreate = originalArchivePath.Substring(archivePath.Length);
219 CreateFoldersForPath(destFolder, archivePathSectionToCreate, resolvedFolders, loadedNodes);
220
221 return destFolder;
222
223 /*
224 string[] rawFolders = filePath.Split(new char[] { '/' });
225
226 // Find the folders that do exist along the path given
227 int i = 0;
228 bool noFolder = false;
229 InventoryFolderImpl foundFolder = rootDestinationFolder;
230 while (!noFolder && i < rawFolders.Length)
231 {
232 InventoryFolderImpl folder = foundFolder.FindFolderByPath(rawFolders[i]);
233 if (null != folder)
234 {
235 m_log.DebugFormat("[INVENTORY ARCHIVER]: Found folder {0}", folder.Name);
236 foundFolder = folder;
237 i++;
238 }
239 else
240 {
241 noFolder = true;
242 }
243 }
244
245 // Create any folders that did not previously exist
246 while (i < rawFolders.Length)
247 {
248 m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0}", rawFolders[i]);
249
250 UUID newFolderId = UUID.Random();
251 m_userInfo.CreateFolder(
252 rawFolders[i++], newFolderId, (ushort)AssetType.Folder, foundFolder.ID);
253 foundFolder = foundFolder.GetChildFolder(newFolderId);
254 }
255 */
256 }
257
258 /// <summary>
259 /// Resolve a destination folder
260 /// </summary>
261 ///
262 /// We require here a root destination folder (usually the root of the user's inventory) and the archive
263 /// path. We also pass in a list of previously resolved folders in case we've found this one previously.
264 ///
265 /// <param name="archivePath">
266 /// The item archive path to resolve. The portion of the path passed back is that
267 /// which corresponds to the resolved desintation folder.
268 /// <param name="rootDestinationFolder">
269 /// The root folder for the inventory load
270 /// </param>
271 /// <param name="resolvedFolders">
272 /// The folders that we have resolved so far for a given archive path.
273 /// </param>
274 /// <returns>
275 /// The folder in the user's inventory that matches best the archive path given. If no such folder was found
276 /// then the passed in root destination folder is returned.
277 /// </returns>
278 protected InventoryFolderBase ResolveDestinationFolder(
279 InventoryFolderBase rootDestFolder,
280 ref string archivePath,
281 Dictionary <string, InventoryFolderBase> resolvedFolders)
282 {
283 string originalArchivePath = archivePath;
214 284
215 InventoryFolderBase destFolder = null; 285 InventoryFolderBase destFolder = null;
216 286
217 // XXX: Nasty way of dealing with a path that has no directory component
218 if (archivePath.Length > 0) 287 if (archivePath.Length > 0)
219 { 288 {
220 while (null == destFolder && archivePath.Length > 0) 289 while (null == destFolder && archivePath.Length > 0)
221 { 290 {
222 if (foldersCreated.ContainsKey(archivePath)) 291 if (resolvedFolders.ContainsKey(archivePath))
223 { 292 {
224// m_log.DebugFormat( 293// m_log.DebugFormat(
225// "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); 294// "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
226 destFolder = foldersCreated[archivePath]; 295 destFolder = resolvedFolders[archivePath];
227 } 296 }
228 else 297 else
229 { 298 {
230 // Don't include the last slash 299 // Don't include the last slash so find the penultimate one
231 int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2); 300 int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);
232 301
233 if (penultimateSlashIndex >= 0) 302 if (penultimateSlashIndex >= 0)
234 { 303 {
304 // Remove the last section of path so that we can see if we've already resolved the parent
235 archivePath = archivePath.Remove(penultimateSlashIndex + 1); 305 archivePath = archivePath.Remove(penultimateSlashIndex + 1);
236 } 306 }
237 else 307 else
@@ -245,19 +315,39 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
245 } 315 }
246 } 316 }
247 } 317 }
248 else 318
249 { 319 if (null == destFolder)
250 destFolder = rootDestFolder; 320 destFolder = rootDestFolder;
251 } 321
252 322 return destFolder;
253 string archivePathSectionToCreate = originalArchivePath.Substring(archivePath.Length); 323 }
254 string[] rawDirsToCreate 324
255 = archivePathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 325 /// <summary>
326 /// Create a set of folders for the given path.
327 /// </summary>
328 /// <param name="destFolder">
329 /// The root folder from which the creation will take place.
330 /// </param>
331 /// <param name="path">
332 /// The path to create
333 /// </param>
334 /// <param name="resolvedFolders">
335 /// The folders that we have resolved so far for a given archive path.
336 /// </param>
337 /// <param name="loadedNodes">
338 /// Track the inventory nodes created.
339 /// </param>
340 protected void CreateFoldersForPath(
341 InventoryFolderBase destFolder, string path, Dictionary <string, InventoryFolderBase> resolvedFolders,
342 List<InventoryNodeBase> loadedNodes)
343 {
344 string pathCreated = "";
345 string[] rawDirsToCreate = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
256 int i = 0; 346 int i = 0;
257 347
258 while (i < rawDirsToCreate.Length) 348 while (i < rawDirsToCreate.Length)
259 { 349 {
260 m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading archived folder {0}", rawDirsToCreate[i]); 350// m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);
261 351
262 int identicalNameIdentifierIndex 352 int identicalNameIdentifierIndex
263 = rawDirsToCreate[i].LastIndexOf( 353 = rawDirsToCreate[i].LastIndexOf(
@@ -282,66 +372,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
282 newFolderId, newFolderName, m_userInfo.PrincipalID, 372 newFolderId, newFolderName, m_userInfo.PrincipalID,
283 (short)AssetType.Unknown, destFolder.ID, 1); 373 (short)AssetType.Unknown, destFolder.ID, 1);
284 m_scene.InventoryService.AddFolder(destFolder); 374 m_scene.InventoryService.AddFolder(destFolder);
285
286// UUID newFolderId = UUID.Random();
287// m_scene.InventoryService.AddFolder(
288// m_userInfo.CreateFolder(
289// folderName, newFolderId, (ushort)AssetType.Folder, foundFolder.ID);
290
291// m_log.DebugFormat("[INVENTORY ARCHIVER]: Retrieving newly created folder {0}", folderName);
292// foundFolder = foundFolder.GetChildFolder(newFolderId);
293// m_log.DebugFormat(
294// "[INVENTORY ARCHIVER]: Retrieved newly created folder {0} with ID {1}",
295// foundFolder.Name, foundFolder.ID);
296 375
297 // Record that we have now created this folder 376 // Record that we have now created this folder
298 archivePath += rawDirsToCreate[i] + "/"; 377 pathCreated += rawDirsToCreate[i] + "/";
299 m_log.DebugFormat("[INVENTORY ARCHIVER]: Loaded archive path {0}", archivePath); 378 m_log.DebugFormat("[INVENTORY ARCHIVER]: Created folder {0} from IAR", pathCreated);
300 foldersCreated[archivePath] = destFolder; 379 resolvedFolders[pathCreated] = destFolder;
301 380
302 if (0 == i) 381 if (0 == i)
303 nodesLoaded.Add(destFolder); 382 loadedNodes.Add(destFolder);
304 383
305 i++; 384 i++;
306 } 385 }
307
308 return destFolder;
309
310 /*
311 string[] rawFolders = filePath.Split(new char[] { '/' });
312
313 // Find the folders that do exist along the path given
314 int i = 0;
315 bool noFolder = false;
316 InventoryFolderImpl foundFolder = rootDestinationFolder;
317 while (!noFolder && i < rawFolders.Length)
318 {
319 InventoryFolderImpl folder = foundFolder.FindFolderByPath(rawFolders[i]);
320 if (null != folder)
321 {
322 m_log.DebugFormat("[INVENTORY ARCHIVER]: Found folder {0}", folder.Name);
323 foundFolder = folder;
324 i++;
325 }
326 else
327 {
328 noFolder = true;
329 }
330 }
331
332 // Create any folders that did not previously exist
333 while (i < rawFolders.Length)
334 {
335 m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0}", rawFolders[i]);
336
337 UUID newFolderId = UUID.Random();
338 m_userInfo.CreateFolder(
339 rawFolders[i++], newFolderId, (ushort)AssetType.Folder, foundFolder.ID);
340 foundFolder = foundFolder.GetChildFolder(newFolderId);
341 }
342 */
343 } 386 }
344 387
345 /// <summary> 388 /// <summary>
346 /// Load an item from the archive 389 /// Load an item from the archive
347 /// </summary> 390 /// </summary>
@@ -432,4 +475,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
432 } 475 }
433 } 476 }
434 } 477 }
435} 478} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index ab5f485..cfefbe9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -30,11 +30,11 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using NDesk.Options;
33using Nini.Config; 34using Nini.Config;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Framework.Communications; 37using OpenSim.Framework.Communications;
37
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
@@ -91,9 +91,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
91 91
92 scene.AddCommand( 92 scene.AddCommand(
93 this, "load iar", 93 this, "load iar",
94 "load iar <first> <last> <inventory path> <password> [<IAR path>]", 94 "load iar <first> <last> <inventory path> <password> [<IAR path>]",
95 //"load iar [--merge] <first> <last> <inventory path> <password> [<IAR path>]",
95 "Load user inventory archive (IAR).", 96 "Load user inventory archive (IAR).",
96 "<first> is user's first name." + Environment.NewLine 97 //"--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones"
98 //+ "<first> is user's first name." + Environment.NewLine
99 "<first> is user's first name." + Environment.NewLine
97 + "<last> is user's last name." + Environment.NewLine 100 + "<last> is user's last name." + Environment.NewLine
98 + "<inventory path> is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine 101 + "<inventory path> is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine
99 + "<password> is the user's password." + Environment.NewLine 102 + "<password> is the user's password." + Environment.NewLine
@@ -133,8 +136,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
133 if (handlerInventoryArchiveSaved != null) 136 if (handlerInventoryArchiveSaved != null)
134 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException); 137 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException);
135 } 138 }
136 139
137 public bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) 140 public bool ArchiveInventory(
141 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream)
142 {
143 return ArchiveInventory(id, firstName, lastName, invPath, pass, saveStream, new Dictionary<string, object>());
144 }
145
146 public bool ArchiveInventory(
147 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream,
148 Dictionary<string, object> options)
138 { 149 {
139 if (m_scenes.Count > 0) 150 if (m_scenes.Count > 0)
140 { 151 {
@@ -172,7 +183,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
172 return false; 183 return false;
173 } 184 }
174 185
175 public bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, string savePath) 186 public bool ArchiveInventory(
187 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
188 Dictionary<string, object> options)
176 { 189 {
177 if (m_scenes.Count > 0) 190 if (m_scenes.Count > 0)
178 { 191 {
@@ -209,8 +222,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
209 222
210 return false; 223 return false;
211 } 224 }
212 225
213 public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream) 226 public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream)
227 {
228 return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>());
229 }
230
231 public bool DearchiveInventory(
232 string firstName, string lastName, string invPath, string pass, Stream loadStream,
233 Dictionary<string, object> options)
214 { 234 {
215 if (m_scenes.Count > 0) 235 if (m_scenes.Count > 0)
216 { 236 {
@@ -252,7 +272,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
252 return false; 272 return false;
253 } 273 }
254 274
255 public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, string loadPath) 275 public bool DearchiveInventory(
276 string firstName, string lastName, string invPath, string pass, string loadPath,
277 Dictionary<string, object> options)
256 { 278 {
257 if (m_scenes.Count > 0) 279 if (m_scenes.Count > 0)
258 { 280 {
@@ -300,29 +322,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
300 /// <param name="cmdparams"></param> 322 /// <param name="cmdparams"></param>
301 protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams) 323 protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams)
302 { 324 {
303 if (cmdparams.Length < 6) 325 m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME.");
326
327 Dictionary<string, object> options = new Dictionary<string, object>();
328 OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; });
329
330 List<string> mainParams = optionSet.Parse(cmdparams);
331
332 if (mainParams.Count < 6)
304 { 333 {
305 m_log.Error( 334 m_log.Error(
306 "[INVENTORY ARCHIVER]: usage is load iar <first name> <last name> <inventory path> <user password> [<load file path>]"); 335 "[INVENTORY ARCHIVER]: usage is load iar <first name> <last name> <inventory path> <user password> [<load file path>]");
307 return; 336 return;
308 } 337 }
309 338
310 m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); 339 string firstName = mainParams[2];
311 340 string lastName = mainParams[3];
312 string firstName = cmdparams[2]; 341 string invPath = mainParams[4];
313 string lastName = cmdparams[3]; 342 string pass = mainParams[5];
314 string invPath = cmdparams[4]; 343 string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
315 string pass = cmdparams[5];
316 string loadPath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME);
317 344
318 m_log.InfoFormat( 345 m_log.InfoFormat(
319 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", 346 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}",
320 loadPath, invPath, firstName, lastName); 347 loadPath, invPath, firstName, lastName);
321 348
322 if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath)) 349 if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options))
323 m_log.InfoFormat( 350 m_log.InfoFormat(
324 "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", 351 "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}",
325 loadPath, firstName, lastName); 352 loadPath, firstName, lastName);
326 } 353 }
327 354
328 /// <summary> 355 /// <summary>
@@ -351,7 +378,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
351 savePath, invPath, firstName, lastName); 378 savePath, invPath, firstName, lastName);
352 379
353 Guid id = Guid.NewGuid(); 380 Guid id = Guid.NewGuid();
354 ArchiveInventory(id, firstName, lastName, invPath, pass, savePath); 381 ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, new Dictionary<string, object>());
355 382
356 lock (m_pendingConsoleSaves) 383 lock (m_pendingConsoleSaves)
357 m_pendingConsoleSaves.Add(id); 384 m_pendingConsoleSaves.Add(id);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index 507662f..59cd386 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -279,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
279 public void TestIarV0_1WithEscapedChars() 279 public void TestIarV0_1WithEscapedChars()
280 { 280 {
281 TestHelper.InMethod(); 281 TestHelper.InMethod();
282// log4net.Config.XmlConfigurator.Configure(); 282 log4net.Config.XmlConfigurator.Configure();
283 283
284 string itemName = "You & you are a mean/man/"; 284 string itemName = "You & you are a mean/man/";
285 string humanEscapedItemName = @"You & you are a mean\/man\/"; 285 string humanEscapedItemName = @"You & you are a mean\/man\/";
@@ -531,7 +531,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
531 531
532 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) 532 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null)
533 .ReplicateArchivePathToUserInventory( 533 .ReplicateArchivePathToUserInventory(
534 itemArchivePath, false, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 534 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
535 foldersCreated, nodesLoaded); 535 foldersCreated, nodesLoaded);
536 536
537 InventoryFolderBase folder1 537 InventoryFolderBase folder1
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index dc1025d..66c5a72 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -410,6 +410,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
410 teleportFlags, capsPath); 410 teleportFlags, capsPath);
411 } 411 }
412 412
413 // Let's set this to true tentatively. This does not trigger OnChildAgent
414 sp.IsChildAgent = true;
415
413 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which 416 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
414 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation 417 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
415 // that the client contacted the destination before we send the attachments and close things here. 418 // that the client contacted the destination before we send the attachments and close things here.
@@ -418,6 +421,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
418 // Client never contacted destination. Let's restore everything back 421 // Client never contacted destination. Let's restore everything back
419 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); 422 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
420 423
424 // Fail. Reset it back
425 sp.IsChildAgent = false;
426
421 ResetFromTransit(sp.UUID); 427 ResetFromTransit(sp.UUID);
422 428
423 // Yikes! We should just have a ref to scene here. 429 // Yikes! We should just have a ref to scene here.
@@ -436,7 +442,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
436 442
437 KillEntity(sp.Scene, sp.LocalId); 443 KillEntity(sp.Scene, sp.LocalId);
438 444
445 // Now let's make it officially a child agent
439 sp.MakeChildAgent(); 446 sp.MakeChildAgent();
447
440 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 448 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
441 449
442 if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 450 if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
@@ -538,6 +546,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
538 client.SendTeleportFailed("Your home region could not be found."); 546 client.SendTeleportFailed("Your home region could not be found.");
539 return; 547 return;
540 } 548 }
549 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})",
550 regionInfo.RegionName, regionInfo.RegionID, regionInfo.RegionLocX / Constants.RegionSize, regionInfo.RegionLocY / Constants.RegionSize);
551
541 // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point... 552 // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point...
542 ((Scene)(client.Scene)).RequestTeleportLocation( 553 ((Scene)(client.Scene)).RequestTeleportLocation(
543 client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt, 554 client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt,
diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs
index fbadd91..01066e6 100644
--- a/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.IO; 30using System.IO;
30using OpenSim.Services.Interfaces; 31using OpenSim.Services.Interfaces;
31 32
@@ -59,6 +60,20 @@ namespace OpenSim.Region.Framework.Interfaces
59 /// <param name="loadStream">The stream from which the inventory archive will be loaded</param> 60 /// <param name="loadStream">The stream from which the inventory archive will be loaded</param>
60 /// <returns>true if the first stage of the operation succeeded, false otherwise</returns> 61 /// <returns>true if the first stage of the operation succeeded, false otherwise</returns>
61 bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream); 62 bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream);
63
64 /// <summary>
65 /// Dearchive a user's inventory folder from the given stream
66 /// </summary>
67 /// <param name="firstName"></param>
68 /// <param name="lastName"></param>
69 /// <param name="invPath">The inventory path in which to place the loaded folders and items</param>
70 /// <param name="loadStream">The stream from which the inventory archive will be loaded</param>
71 /// <param name="options">Dearchiving options. At the moment, the only option is ("merge", true). This merges
72 /// the loaded IAR with existing folders where possible.</param>
73 /// <returns>true if the first stage of the operation succeeded, false otherwise</returns>
74 bool DearchiveInventory(
75 string firstName, string lastName, string invPath, string pass, Stream loadStream,
76 Dictionary<string, object> options);
62 77
63 /// <summary> 78 /// <summary>
64 /// Archive a user's inventory folder to the given stream 79 /// Archive a user's inventory folder to the given stream
@@ -70,5 +85,19 @@ namespace OpenSim.Region.Framework.Interfaces
70 /// <param name="saveStream">The stream to which the inventory archive will be saved</param> 85 /// <param name="saveStream">The stream to which the inventory archive will be saved</param>
71 /// <returns>true if the first stage of the operation succeeded, false otherwise</returns> 86 /// <returns>true if the first stage of the operation succeeded, false otherwise</returns>
72 bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream); 87 bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream);
88
89 /// <summary>
90 /// Archive a user's inventory folder to the given stream
91 /// </summary>
92 /// <param name="id">ID representing this request. This will later be returned in the save event</param>
93 /// <param name="firstName"></param>
94 /// <param name="lastName"></param>
95 /// <param name="invPath">The inventory path from which the inventory should be saved.</param>
96 /// <param name="saveStream">The stream to which the inventory archive will be saved</param>
97 /// <param name="options">Archiving options. Currently, there are none.</param>
98 /// <returns>true if the first stage of the operation succeeded, false otherwise</returns>
99 bool ArchiveInventory(
100 Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream,
101 Dictionary<string, object> options);
73 } 102 }
74} 103}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 19329a8..756b81e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -4039,7 +4039,9 @@ namespace OpenSim.Region.Framework.Scenes
4039 // bordercross if position is outside of region 4039 // bordercross if position is outside of region
4040 4040
4041 if (!result) 4041 if (!result)
4042 {
4042 regionHandle = m_regInfo.RegionHandle; 4043 regionHandle = m_regInfo.RegionHandle;
4044 }
4043 else 4045 else
4044 { 4046 {
4045 // not in this region, undo the shift! 4047 // not in this region, undo the shift!
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
index 600ddfd..935ebb1 100644
--- a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
+++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
@@ -206,9 +206,7 @@ namespace OpenSim.Services.Connectors
206 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null)) 206 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
207 { 207 {
208 if (replyData["result"] is Dictionary<string, object>) 208 if (replyData["result"] is Dictionary<string, object>)
209 {
210 guinfo = new GridUserInfo((Dictionary<string, object>)replyData["result"]); 209 guinfo = new GridUserInfo((Dictionary<string, object>)replyData["result"]);
211 }
212 } 210 }
213 211
214 return guinfo; 212 return guinfo;
diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs
index e629dff..95ce5e8 100644
--- a/OpenSim/Services/Interfaces/IGridUserService.cs
+++ b/OpenSim/Services/Interfaces/IGridUserService.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Services.Interfaces
65 Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt); 65 Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt);
66 66
67 if (kvp.ContainsKey("LastRegionID")) 67 if (kvp.ContainsKey("LastRegionID"))
68 UUID.TryParse(kvp["LastRegionID"].ToString(), out HomeRegionID); 68 UUID.TryParse(kvp["LastRegionID"].ToString(), out LastRegionID);
69 if (kvp.ContainsKey("LastPosition")) 69 if (kvp.ContainsKey("LastPosition"))
70 Vector3.TryParse(kvp["LastPosition"].ToString(), out LastPosition); 70 Vector3.TryParse(kvp["LastPosition"].ToString(), out LastPosition);
71 if (kvp.ContainsKey("LastLookAt")) 71 if (kvp.ContainsKey("LastLookAt"))