clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections.Generic;
30 using System.Linq;
31 using OpenMetaverse;
32 using log4net;
33 using Nini.Config;
34 using System.Reflection;
35 using OpenSim.Services.Base;
36 using OpenSim.Services.Interfaces;
37 using OpenSim.Services.InventoryService;
38 using OpenSim.Data;
39 using OpenSim.Framework;
40 using OpenSim.Server.Base;
41  
42 namespace OpenSim.Services.HypergridService
43 {
44 /// <summary>
45 /// Hypergrid inventory service. It serves the IInventoryService interface,
46 /// but implements it in ways that are appropriate for inter-grid
47 /// inventory exchanges. Specifically, it does not performs deletions
48 /// and it responds to GetRootFolder requests with the ID of the
49 /// Suitcase folder, not the actual "My Inventory" folder.
50 /// </summary>
51 public class HGSuitcaseInventoryService : XInventoryService, IInventoryService
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56  
57 // private string m_HomeURL;
58 private IUserAccountService m_UserAccountService;
59 private IAvatarService m_AvatarService;
60  
61 // private UserAccountCache m_Cache;
62  
63 private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>();
64 private ExpiringCache<UUID, AvatarAppearance> m_Appearances = new ExpiringCache<UUID, AvatarAppearance>();
65  
66 public HGSuitcaseInventoryService(IConfigSource config, string configName)
67 : base(config, configName)
68 {
69 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Starting with config name {0}", configName);
70 if (configName != string.Empty)
71 m_ConfigName = configName;
72  
73 if (m_Database == null)
74 m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: m_Database is null!");
75  
76 //
77 // Try reading the [InventoryService] section, if it exists
78 //
79 IConfig invConfig = config.Configs[m_ConfigName];
80 if (invConfig != null)
81 {
82 string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty);
83 if (userAccountsDll == string.Empty)
84 throw new Exception("Please specify UserAccountsService in HGInventoryService configuration");
85  
86 Object[] args = new Object[] { config };
87 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountsDll, args);
88 if (m_UserAccountService == null)
89 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll));
90  
91 string avatarDll = invConfig.GetString("AvatarService", string.Empty);
92 if (avatarDll == string.Empty)
93 throw new Exception("Please specify AvatarService in HGInventoryService configuration");
94  
95 m_AvatarService = ServerUtils.LoadPlugin<IAvatarService>(avatarDll, args);
96 if (m_AvatarService == null)
97 throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll));
98  
99 // m_HomeURL = Util.GetConfigVarFromSections<string>(config, "HomeURI",
100 // new string[] { "Startup", "Hypergrid", m_ConfigName }, String.Empty);
101  
102 // m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
103 }
104  
105 m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Starting...");
106 }
107  
108 public override bool CreateUserInventory(UUID principalID)
109 {
110 // NOGO
111 return false;
112 }
113  
114 public override List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
115 {
116 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
117  
118 if (suitcase == null)
119 {
120 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for inventory skeleton", principalID);
121 return null;
122 }
123  
124 List<XInventoryFolder> tree = GetFolderTree(principalID, suitcase.folderID);
125 if (tree.Count == 0)
126 return null;
127  
128 List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
129 foreach (XInventoryFolder x in tree)
130 {
131 folders.Add(ConvertToOpenSim(x));
132 }
133  
134 SetAsNormalFolder(suitcase);
135 folders.Add(ConvertToOpenSim(suitcase));
136  
137 return folders;
138 }
139  
140 public override InventoryFolderBase GetRootFolder(UUID principalID)
141 {
142 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID);
143  
144 // Let's find out the local root folder
145 XInventoryFolder root = GetRootXFolder(principalID);
146  
147 if (root == null)
148 {
149 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID);
150 return null;
151 }
152  
153 // Warp! Root folder for travelers is the suitcase folder
154 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
155  
156 if (suitcase == null)
157 {
158 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder. Creating it...", principalID);
159 // Create the My Suitcase folder under the user's root folder.
160 // In the DB we tag it as type 100, but we use type 8 (Folder) outside, as this affects the sort order.
161 suitcase = CreateFolder(principalID, root.folderID, InventoryItemBase.SUITCASE_FOLDER_TYPE, InventoryItemBase.SUITCASE_FOLDER_NAME);
162 if (suitcase == null)
163 {
164 m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder");
165 return null;
166 }
167  
168 CreateSystemFolders(principalID, suitcase.folderID);
169 }
170  
171 SetAsNormalFolder(suitcase);
172  
173 return ConvertToOpenSim(suitcase);
174 }
175  
176 protected void CreateSystemFolders(UUID principalID, UUID rootID)
177 {
178 m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Creating System folders under Suitcase...");
179 XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootID);
180  
181 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; }))
182 CreateFolder(principalID, rootID, (int)AssetType.Animation, "Animations");
183 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Bodypart) return true; return false; }))
184 CreateFolder(principalID, rootID, (int)AssetType.Bodypart, "Body Parts");
185 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CallingCard) return true; return false; }))
186 CreateFolder(principalID, rootID, (int)AssetType.CallingCard, "Calling Cards");
187 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Clothing) return true; return false; }))
188 CreateFolder(principalID, rootID, (int)AssetType.Clothing, "Clothing");
189 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CurrentOutfitFolder) return true; return false; }))
190 CreateFolder(principalID, rootID, (int)AssetType.CurrentOutfitFolder, "Current Outfit");
191 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.FavoriteFolder) return true; return false; }))
192 CreateFolder(principalID, rootID, (int)AssetType.FavoriteFolder, "Favorites");
193 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Gesture) return true; return false; }))
194 CreateFolder(principalID, rootID, (int)AssetType.Gesture, "Gestures");
195 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Landmark) return true; return false; }))
196 CreateFolder(principalID, rootID, (int)AssetType.Landmark, "Landmarks");
197 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LostAndFoundFolder) return true; return false; }))
198 CreateFolder(principalID, rootID, (int)AssetType.LostAndFoundFolder, "Lost And Found");
199 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Notecard) return true; return false; }))
200 CreateFolder(principalID, rootID, (int)AssetType.Notecard, "Notecards");
201 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Object) return true; return false; }))
202 CreateFolder(principalID, rootID, (int)AssetType.Object, "Objects");
203 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.SnapshotFolder) return true; return false; }))
204 CreateFolder(principalID, rootID, (int)AssetType.SnapshotFolder, "Photo Album");
205 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LSLText) return true; return false; }))
206 CreateFolder(principalID, rootID, (int)AssetType.LSLText, "Scripts");
207 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Sound) return true; return false; }))
208 CreateFolder(principalID, rootID, (int)AssetType.Sound, "Sounds");
209 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Texture) return true; return false; }))
210 CreateFolder(principalID, rootID, (int)AssetType.Texture, "Textures");
211 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.TrashFolder) return true; return false; }))
212 CreateFolder(principalID, rootID, (int)AssetType.TrashFolder, "Trash");
213 }
214  
215 public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
216 {
217 //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type);
218 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
219  
220 if (suitcase == null)
221 {
222 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for child type folder {1}", principalID, type);
223 return null;
224 }
225  
226 XInventoryFolder[] folders = m_Database.GetFolders(
227 new string[] { "agentID", "type", "parentFolderID" },
228 new string[] { principalID.ToString(), ((int)type).ToString(), suitcase.folderID.ToString() });
229  
230 if (folders.Length == 0)
231 {
232 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID);
233 return null;
234 }
235  
236 m_log.DebugFormat(
237 "[HG SUITCASE INVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}",
238 folders[0].folderName, folders[0].folderID, type, principalID);
239  
240 return ConvertToOpenSim(folders[0]);
241 }
242  
243 public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
244 {
245 InventoryCollection coll = null;
246  
247 if (!IsWithinSuitcaseTree(principalID, folderID))
248 {
249 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent: folder {0} (user {1}) is not within Suitcase tree", folderID, principalID);
250 return new InventoryCollection();
251 }
252  
253 coll = base.GetFolderContent(principalID, folderID);
254  
255 if (coll == null)
256 {
257 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID);
258 coll = new InventoryCollection();
259 }
260 return coll;
261 }
262  
263 public override List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
264 {
265 // Let's do a bit of sanity checking, more than the base service does
266 // make sure the given folder exists under the suitcase tree of this user
267 if (!IsWithinSuitcaseTree(principalID, folderID))
268 {
269 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderItems: folder {0} (user {1}) is not within Suitcase tree", folderID, principalID);
270 return new List<InventoryItemBase>();
271 }
272  
273 return base.GetFolderItems(principalID, folderID);
274 }
275  
276 public override bool AddFolder(InventoryFolderBase folder)
277 {
278 //m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID);
279 // Let's do a bit of sanity checking, more than the base service does
280 // make sure the given folder's parent folder exists under the suitcase tree of this user
281  
282 if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID))
283 {
284 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder: folder {0} (user {1}) is not within Suitcase tree", folder.ParentID, folder.Owner);
285 return false;
286 }
287  
288 // OK, it's legit
289 if (base.AddFolder(folder))
290 {
291 List<XInventoryFolder> tree;
292 if (m_SuitcaseTrees.TryGetValue(folder.Owner, out tree))
293 tree.Add(ConvertFromOpenSim(folder));
294  
295 return true;
296 }
297  
298 return false;
299 }
300  
301 public override bool UpdateFolder(InventoryFolderBase folder)
302 {
303 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version);
304 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID))
305 {
306 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: UpdateFolder: folder {0}/{1} (user {2}) is not within Suitcase tree", folder.Name, folder.ID, folder.Owner);
307 return false;
308 }
309  
310 // For all others
311 return base.UpdateFolder(folder);
312 }
313  
314 public override bool MoveFolder(InventoryFolderBase folder)
315 {
316 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID))
317 {
318 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder: folder {0} (user {1}) is not within Suitcase tree", folder.ID, folder.Owner);
319 return false;
320 }
321  
322 if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID))
323 {
324 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder: folder {0} (user {1}) is not within Suitcase tree", folder.ParentID, folder.Owner);
325 return false;
326 }
327  
328 return base.MoveFolder(folder);
329 }
330  
331 public override bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
332 {
333 // NOGO
334 return false;
335 }
336  
337 public override bool PurgeFolder(InventoryFolderBase folder)
338 {
339 // NOGO
340 return false;
341 }
342  
343 public override bool AddItem(InventoryItemBase item)
344 {
345 // Let's do a bit of sanity checking, more than the base service does
346 // make sure the given folder's parent folder exists under the suitcase tree of this user
347 if (!IsWithinSuitcaseTree(item.Owner, item.Folder))
348 {
349 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddItem: folder {0} (user {1}) is not within Suitcase tree", item.Folder, item.Owner);
350 return false;
351 }
352  
353 // OK, it's legit
354 return base.AddItem(item);
355  
356 }
357  
358 public override bool UpdateItem(InventoryItemBase item)
359 {
360 if (!IsWithinSuitcaseTree(item.Owner, item.Folder))
361 {
362 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: UpdateItem: folder {0} (user {1}) is not within Suitcase tree", item.Folder, item.Owner);
363 return false;
364 }
365  
366 return base.UpdateItem(item);
367 }
368  
369 public override bool MoveItems(UUID principalID, List<InventoryItemBase> items)
370 {
371 // Principal is b0rked. *sigh*
372  
373 // Check the items' destination folders
374 foreach (InventoryItemBase item in items)
375 {
376 if (!IsWithinSuitcaseTree(item.Owner, item.Folder))
377 {
378 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItems: folder {0} (user {1}) is not within Suitcase tree", item.Folder, item.Owner);
379 return false;
380 }
381 }
382  
383 // Check the items' current folders
384 foreach (InventoryItemBase item in items)
385 {
386 InventoryItemBase originalItem = base.GetItem(item);
387 if (!IsWithinSuitcaseTree(originalItem.Owner, originalItem.Folder))
388 {
389 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItems: folder {0} (user {1}) is not within Suitcase tree", item.Folder, item.Owner);
390 return false;
391 }
392 }
393  
394 return base.MoveItems(principalID, items);
395 }
396  
397 public override bool DeleteItems(UUID principalID, List<UUID> itemIDs)
398 {
399 return false;
400 }
401  
402 public new InventoryItemBase GetItem(InventoryItemBase item)
403 {
404 InventoryItemBase it = base.GetItem(item);
405 if (it == null)
406 {
407 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve item {0} ({1}) in folder {2}",
408 item.Name, item.ID, item.Folder);
409 return null;
410 }
411  
412 if (!IsWithinSuitcaseTree(it.Owner, it.Folder) && !IsPartOfAppearance(it.Owner, it.ID))
413 {
414 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetItem: item {0}/{1} (folder {2}) (user {3}) is not within Suitcase tree or Appearance",
415 it.Name, it.ID, it.Folder, it.Owner);
416 return null;
417 }
418  
419 // UserAccount user = m_Cache.GetUser(it.CreatorId);
420  
421 // // Adjust the creator data
422 // if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty))
423 // it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName;
424 //}
425  
426 return it;
427 }
428  
429 public new InventoryFolderBase GetFolder(InventoryFolderBase folder)
430 {
431 InventoryFolderBase f = base.GetFolder(folder);
432  
433 if (f != null)
434 {
435 if (!IsWithinSuitcaseTree(f.Owner, f.ID))
436 {
437 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolder: folder {0}/{1} (user {2}) is not within Suitcase tree",
438 f.Name, f.ID, f.Owner);
439 return null;
440 }
441 }
442  
443 return f;
444 }
445  
446 //public List<InventoryItemBase> GetActiveGestures(UUID principalID)
447 //{
448 //}
449  
450 //public int GetAssetPermissions(UUID principalID, UUID assetID)
451 //{
452 //}
453  
454 #region Auxiliary functions
455 private XInventoryFolder GetXFolder(UUID userID, UUID folderID)
456 {
457 XInventoryFolder[] folders = m_Database.GetFolders(
458 new string[] { "agentID", "folderID" },
459 new string[] { userID.ToString(), folderID.ToString() });
460  
461 if (folders.Length == 0)
462 return null;
463  
464 return folders[0];
465 }
466  
467 private XInventoryFolder GetRootXFolder(UUID principalID)
468 {
469 XInventoryFolder[] folders = m_Database.GetFolders(
470 new string[] { "agentID", "folderName", "type" },
471 new string[] { principalID.ToString(), "My Inventory", ((int)AssetType.RootFolder).ToString() });
472  
473 if (folders != null && folders.Length > 0)
474 return folders[0];
475  
476 // OK, so the RootFolder type didn't work. Let's look for any type with parent UUID.Zero.
477 folders = m_Database.GetFolders(
478 new string[] { "agentID", "folderName", "parentFolderID" },
479 new string[] { principalID.ToString(), "My Inventory", UUID.Zero.ToString() });
480  
481 if (folders != null && folders.Length > 0)
482 return folders[0];
483  
484 return null;
485 }
486  
487 private XInventoryFolder GetCurrentOutfitXFolder(UUID userID)
488 {
489 XInventoryFolder root = GetRootXFolder(userID);
490 if (root == null)
491 return null;
492  
493 XInventoryFolder[] folders = m_Database.GetFolders(
494 new string[] { "agentID", "type", "parentFolderID" },
495 new string[] { userID.ToString(), ((int)AssetType.CurrentOutfitFolder).ToString(), root.folderID.ToString() });
496  
497 if (folders.Length == 0)
498 return null;
499  
500 return folders[0];
501 }
502  
503 private XInventoryFolder GetSuitcaseXFolder(UUID principalID)
504 {
505 // Warp! Root folder for travelers
506 XInventoryFolder[] folders = m_Database.GetFolders(
507 new string[] { "agentID", "type" },
508 new string[] { principalID.ToString(), InventoryItemBase.SUITCASE_FOLDER_TYPE.ToString() }); // This is a special folder type...
509  
510 if (folders != null && folders.Length > 0)
511 return folders[0];
512  
513 // check to see if we have the old Suitcase folder
514 folders = m_Database.GetFolders(
515 new string[] { "agentID", "folderName", "parentFolderID" },
516 new string[] { principalID.ToString(), InventoryItemBase.SUITCASE_FOLDER_NAME, UUID.Zero.ToString() });
517 if (folders != null && folders.Length > 0)
518 {
519 // Move it to under the root folder
520 XInventoryFolder root = GetRootXFolder(principalID);
521 folders[0].parentFolderID = root.folderID;
522 folders[0].type = InventoryItemBase.SUITCASE_FOLDER_TYPE;
523 m_Database.StoreFolder(folders[0]);
524 return folders[0];
525 }
526  
527 return null;
528 }
529  
530 private void SetAsNormalFolder(XInventoryFolder suitcase)
531 {
532 suitcase.type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE;
533 }
534  
535 private List<XInventoryFolder> GetFolderTree(UUID principalID, UUID folder)
536 {
537 List<XInventoryFolder> t;
538 if (m_SuitcaseTrees.TryGetValue(principalID, out t))
539 return t;
540  
541 // Get the tree of the suitcase folder
542 t = GetFolderTreeRecursive(folder);
543 m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5 minutes
544 return t;
545 }
546  
547 private List<XInventoryFolder> GetFolderTreeRecursive(UUID root)
548 {
549 List<XInventoryFolder> tree = new List<XInventoryFolder>();
550 XInventoryFolder[] folders = m_Database.GetFolders(
551 new string[] { "parentFolderID" },
552 new string[] { root.ToString() });
553  
554 if (folders == null || folders.Length == 0)
555 {
556 return tree; // empty tree
557 }
558 else
559 {
560 foreach (XInventoryFolder f in folders)
561 {
562 tree.Add(f);
563 tree.AddRange(GetFolderTreeRecursive(f.folderID));
564 }
565 return tree;
566 }
567  
568 }
569  
570 /// <summary>
571 /// Return true if the folderID is a subfolder of the Suitcase or the suitcase folder itself
572 /// </summary>
573 /// <param name="folderID"></param>
574 /// <param name="root"></param>
575 /// <param name="suitcase"></param>
576 /// <returns></returns>
577 private bool IsWithinSuitcaseTree(UUID principalID, UUID folderID)
578 {
579 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
580  
581 if (suitcase == null)
582 {
583 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder", principalID);
584 return false;
585 }
586  
587 List<XInventoryFolder> tree = new List<XInventoryFolder>();
588 tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder
589 tree.AddRange(GetFolderTree(principalID, suitcase.folderID));
590  
591 // Also add the Current Outfit folder to the list of available folders
592 XInventoryFolder folder = GetCurrentOutfitXFolder(principalID);
593 if (folder != null)
594 tree.Add(folder);
595  
596 XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl)
597 {
598 return (fl.folderID == folderID);
599 });
600  
601 return (f != null);
602 }
603 #endregion
604  
605 #region Avatar Appearance
606  
607 private AvatarAppearance GetAppearance(UUID principalID)
608 {
609 AvatarAppearance a = null;
610 if (m_Appearances.TryGetValue(principalID, out a))
611 return a;
612  
613 a = m_AvatarService.GetAppearance(principalID);
614 m_Appearances.AddOrUpdate(principalID, a, 5 * 60); // 5minutes
615 return a;
616 }
617  
618 private bool IsPartOfAppearance(UUID principalID, UUID itemID)
619 {
620 AvatarAppearance a = GetAppearance(principalID);
621  
622 if (a == null)
623 return false;
624  
625 // Check wearables (body parts and clothes)
626 for (int i = 0; i < a.Wearables.Length; i++)
627 {
628 for (int j = 0; j < a.Wearables[i].Count; j++)
629 {
630 if (a.Wearables[i][j].ItemID == itemID)
631 {
632 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is a wearable", itemID);
633 return true;
634 }
635 }
636 }
637  
638 // Check attachments
639 if (a.GetAttachmentForItem(itemID) != null)
640 {
641 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is an attachment", itemID);
642 return true;
643 }
644  
645 return false;
646 }
647  
648 #endregion
649  
650 }
651  
652 }