opensim-development – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 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 == null || (tree != null && 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 InventoryCollection GetUserInventory(UUID userID)
141 {
142 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Get Suitcase inventory for user {0}", userID);
143  
144 InventoryCollection userInventory = new InventoryCollection();
145 userInventory.UserID = userID;
146 userInventory.Folders = new List<InventoryFolderBase>();
147 userInventory.Items = new List<InventoryItemBase>();
148  
149 XInventoryFolder suitcase = GetSuitcaseXFolder(userID);
150  
151 if (suitcase == null)
152 {
153 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for user inventory", userID);
154 return null;
155 }
156  
157 List<XInventoryFolder> tree = GetFolderTree(userID, suitcase.folderID);
158 if (tree == null || (tree != null && tree.Count == 0))
159 {
160 SetAsNormalFolder(suitcase);
161 userInventory.Folders.Add(ConvertToOpenSim(suitcase));
162 return userInventory;
163 }
164  
165 List<InventoryItemBase> items;
166 foreach (XInventoryFolder f in tree)
167 {
168 // Add the items of this subfolder
169 items = GetFolderItems(userID, f.folderID);
170 if (items != null && items.Count > 0)
171 {
172 userInventory.Items.AddRange(items);
173 }
174  
175 // Add the folder itself
176 userInventory.Folders.Add(ConvertToOpenSim(f));
177 }
178  
179 items = GetFolderItems(userID, suitcase.folderID);
180 if (items != null && items.Count > 0)
181 {
182 userInventory.Items.AddRange(items);
183 }
184  
185 SetAsNormalFolder(suitcase);
186 userInventory.Folders.Add(ConvertToOpenSim(suitcase));
187  
188 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items",
189 userID, userInventory.Folders.Count, userInventory.Items.Count);
190 return userInventory;
191 }
192  
193 public override InventoryFolderBase GetRootFolder(UUID principalID)
194 {
195 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID);
196  
197 // Let's find out the local root folder
198 XInventoryFolder root = GetRootXFolder(principalID);
199  
200 if (root == null)
201 {
202 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID);
203 return null;
204 }
205  
206 // Warp! Root folder for travelers is the suitcase folder
207 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
208  
209 if (suitcase == null)
210 {
211 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder. Creating it...", principalID);
212 // make one, and let's add it to the user's inventory as a direct child of the root folder
213 // In the DB we tag it as type 100, but we use -1 (Unknown) outside
214 suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase");
215 if (suitcase == null)
216 {
217 m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder");
218 }
219 else
220 {
221 m_Database.StoreFolder(suitcase);
222  
223 // Create System folders
224 CreateSystemFolders(principalID, suitcase.folderID);
225  
226 SetAsNormalFolder(suitcase);
227  
228 return ConvertToOpenSim(suitcase);
229 }
230 }
231  
232 return null;
233 }
234  
235 protected void CreateSystemFolders(UUID principalID, UUID rootID)
236 {
237 m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Creating System folders under Suitcase...");
238 XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootID);
239  
240 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; }))
241 CreateFolder(principalID, rootID, (int)AssetType.Animation, "Animations");
242 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Bodypart) return true; return false; }))
243 CreateFolder(principalID, rootID, (int)AssetType.Bodypart, "Body Parts");
244 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CallingCard) return true; return false; }))
245 CreateFolder(principalID, rootID, (int)AssetType.CallingCard, "Calling Cards");
246 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Clothing) return true; return false; }))
247 CreateFolder(principalID, rootID, (int)AssetType.Clothing, "Clothing");
248 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Gesture) return true; return false; }))
249 CreateFolder(principalID, rootID, (int)AssetType.Gesture, "Gestures");
250 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Landmark) return true; return false; }))
251 CreateFolder(principalID, rootID, (int)AssetType.Landmark, "Landmarks");
252 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LostAndFoundFolder) return true; return false; }))
253 CreateFolder(principalID, rootID, (int)AssetType.LostAndFoundFolder, "Lost And Found");
254 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Notecard) return true; return false; }))
255 CreateFolder(principalID, rootID, (int)AssetType.Notecard, "Notecards");
256 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Object) return true; return false; }))
257 CreateFolder(principalID, rootID, (int)AssetType.Object, "Objects");
258 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.SnapshotFolder) return true; return false; }))
259 CreateFolder(principalID, rootID, (int)AssetType.SnapshotFolder, "Photo Album");
260 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LSLText) return true; return false; }))
261 CreateFolder(principalID, rootID, (int)AssetType.LSLText, "Scripts");
262 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Sound) return true; return false; }))
263 CreateFolder(principalID, rootID, (int)AssetType.Sound, "Sounds");
264 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Texture) return true; return false; }))
265 CreateFolder(principalID, rootID, (int)AssetType.Texture, "Textures");
266 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.TrashFolder) return true; return false; }))
267 CreateFolder(principalID, rootID, (int)AssetType.TrashFolder, "Trash");
268 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.FavoriteFolder) return true; return false; }))
269 CreateFolder(principalID, rootID, (int)AssetType.FavoriteFolder, "Favorites");
270 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CurrentOutfitFolder) return true; return false; }))
271 CreateFolder(principalID, rootID, (int)AssetType.CurrentOutfitFolder, "Current Outfit");
272  
273 }
274  
275 public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
276 {
277 //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type);
278 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
279  
280 if (suitcase == null)
281 {
282 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for child type folder {1}", principalID, type);
283 return null;
284 }
285  
286 XInventoryFolder[] folders = m_Database.GetFolders(
287 new string[] { "agentID", "type", "parentFolderID" },
288 new string[] { principalID.ToString(), ((int)type).ToString(), suitcase.folderID.ToString() });
289  
290 if (folders.Length == 0)
291 {
292 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID);
293 return null;
294 }
295  
296 m_log.DebugFormat(
297 "[HG SUITCASE INVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}",
298 folders[0].folderName, folders[0].folderID, type, principalID);
299  
300 return ConvertToOpenSim(folders[0]);
301 }
302  
303 public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
304 {
305 InventoryCollection coll = null;
306  
307 if (!IsWithinSuitcaseTree(principalID, folderID))
308 return new InventoryCollection();
309  
310 coll = base.GetFolderContent(principalID, folderID);
311  
312 if (coll == null)
313 {
314 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID);
315 coll = new InventoryCollection();
316 }
317 return coll;
318 }
319  
320 public override List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
321 {
322 // Let's do a bit of sanity checking, more than the base service does
323 // make sure the given folder exists under the suitcase tree of this user
324 if (!IsWithinSuitcaseTree(principalID, folderID))
325 return new List<InventoryItemBase>();
326  
327 return base.GetFolderItems(principalID, folderID);
328 }
329  
330 public override bool AddFolder(InventoryFolderBase folder)
331 {
332 //m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID);
333 // Let's do a bit of sanity checking, more than the base service does
334 // make sure the given folder's parent folder exists under the suitcase tree of this user
335  
336 if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID))
337 return false;
338  
339 // OK, it's legit
340 if (base.AddFolder(folder))
341 {
342 List<XInventoryFolder> tree;
343 if (m_SuitcaseTrees.TryGetValue(folder.Owner, out tree))
344 tree.Add(ConvertFromOpenSim(folder));
345  
346 return true;
347 }
348  
349 return false;
350 }
351  
352 public override bool UpdateFolder(InventoryFolderBase folder)
353 {
354 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version);
355 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID))
356 {
357 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name);
358 return false;
359 }
360  
361 // For all others
362 return base.UpdateFolder(folder);
363 }
364  
365 public override bool MoveFolder(InventoryFolderBase folder)
366 {
367 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID) ||
368 !IsWithinSuitcaseTree(folder.Owner, folder.ParentID))
369 return false;
370  
371 return base.MoveFolder(folder);
372 }
373  
374 public override bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
375 {
376 // NOGO
377 return false;
378 }
379  
380 public override bool PurgeFolder(InventoryFolderBase folder)
381 {
382 // NOGO
383 return false;
384 }
385  
386 public override bool AddItem(InventoryItemBase item)
387 {
388 // Let's do a bit of sanity checking, more than the base service does
389 // make sure the given folder's parent folder exists under the suitcase tree of this user
390 if (!IsWithinSuitcaseTree(item.Owner, item.Folder))
391 return false;
392  
393 // OK, it's legit
394 return base.AddItem(item);
395  
396 }
397  
398 public override bool UpdateItem(InventoryItemBase item)
399 {
400 if (!IsWithinSuitcaseTree(item.Owner, item.Folder))
401 return false;
402  
403 return base.UpdateItem(item);
404 }
405  
406 public override bool MoveItems(UUID principalID, List<InventoryItemBase> items)
407 {
408 // Principal is b0rked. *sigh*
409  
410 if (!IsWithinSuitcaseTree(items[0].Owner, items[0].Folder))
411 return false;
412  
413 return base.MoveItems(principalID, items);
414  
415 }
416  
417 public override bool DeleteItems(UUID principalID, List<UUID> itemIDs)
418 {
419 return false;
420 }
421  
422 public new InventoryItemBase GetItem(InventoryItemBase item)
423 {
424 InventoryItemBase it = base.GetItem(item);
425 if (it == null)
426 {
427 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve item {0} ({1}) in folder {2}",
428 item.Name, item.ID, item.Folder);
429 return null;
430 }
431  
432 if (!IsWithinSuitcaseTree(it.Owner, it.Folder) && !IsPartOfAppearance(it.Owner, it.ID))
433 {
434 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase",
435 it.Name, it.Folder);
436 return null;
437 }
438  
439 // UserAccount user = m_Cache.GetUser(it.CreatorId);
440  
441 // // Adjust the creator data
442 // if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty))
443 // it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName;
444 //}
445  
446 return it;
447 }
448  
449 public new InventoryFolderBase GetFolder(InventoryFolderBase folder)
450 {
451 InventoryFolderBase f = base.GetFolder(folder);
452  
453 if (f != null)
454 {
455 if (!IsWithinSuitcaseTree(f.Owner, f.ID))
456 return null;
457 }
458  
459 return f;
460 }
461  
462 //public List<InventoryItemBase> GetActiveGestures(UUID principalID)
463 //{
464 //}
465  
466 //public int GetAssetPermissions(UUID principalID, UUID assetID)
467 //{
468 //}
469  
470 #region Auxiliary functions
471 private XInventoryFolder GetXFolder(UUID userID, UUID folderID)
472 {
473 XInventoryFolder[] folders = m_Database.GetFolders(
474 new string[] { "agentID", "folderID" },
475 new string[] { userID.ToString(), folderID.ToString() });
476  
477 if (folders.Length == 0)
478 return null;
479  
480 return folders[0];
481 }
482  
483 private XInventoryFolder GetRootXFolder(UUID principalID)
484 {
485 XInventoryFolder[] folders = m_Database.GetFolders(
486 new string[] { "agentID", "folderName", "type" },
487 new string[] { principalID.ToString(), "My Inventory", ((int)AssetType.RootFolder).ToString() });
488  
489 if (folders != null && folders.Length > 0)
490 return folders[0];
491  
492 // OK, so the RootFolder type didn't work. Let's look for any type with parent UUID.Zero.
493 folders = m_Database.GetFolders(
494 new string[] { "agentID", "folderName", "parentFolderID" },
495 new string[] { principalID.ToString(), "My Inventory", UUID.Zero.ToString() });
496  
497 if (folders != null && folders.Length > 0)
498 return folders[0];
499  
500 return null;
501 }
502  
503 private XInventoryFolder GetCurrentOutfitXFolder(UUID userID)
504 {
505 XInventoryFolder root = GetRootXFolder(userID);
506 if (root == null)
507 return null;
508  
509 XInventoryFolder[] folders = m_Database.GetFolders(
510 new string[] { "agentID", "type", "parentFolderID" },
511 new string[] { userID.ToString(), ((int)AssetType.CurrentOutfitFolder).ToString(), root.folderID.ToString() });
512  
513 if (folders.Length == 0)
514 return null;
515  
516 return folders[0];
517 }
518  
519 private XInventoryFolder GetSuitcaseXFolder(UUID principalID)
520 {
521 // Warp! Root folder for travelers
522 XInventoryFolder[] folders = m_Database.GetFolders(
523 new string[] { "agentID", "type" },
524 new string[] { principalID.ToString(), "100" }); // This is a special folder type...
525  
526 if (folders != null && folders.Length > 0)
527 return folders[0];
528  
529 // check to see if we have the old Suitcase folder
530 folders = m_Database.GetFolders(
531 new string[] { "agentID", "folderName", "parentFolderID" },
532 new string[] { principalID.ToString(), "My Suitcase", UUID.Zero.ToString() });
533 if (folders != null && folders.Length > 0)
534 {
535 // Move it to under the root folder
536 XInventoryFolder root = GetRootXFolder(principalID);
537 folders[0].parentFolderID = root.folderID;
538 folders[0].type = 100;
539 m_Database.StoreFolder(folders[0]);
540 return folders[0];
541 }
542  
543 return null;
544 }
545  
546 private void SetAsNormalFolder(XInventoryFolder suitcase)
547 {
548 suitcase.type = (short)AssetType.Folder;
549 }
550  
551 private List<XInventoryFolder> GetFolderTree(UUID principalID, UUID folder)
552 {
553 List<XInventoryFolder> t = null;
554 if (m_SuitcaseTrees.TryGetValue(principalID, out t))
555 return t;
556  
557 // Get the tree of the suitcase folder
558 t = GetFolderTreeRecursive(folder);
559 m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5minutes
560 return t;
561 }
562  
563 private List<XInventoryFolder> GetFolderTreeRecursive(UUID root)
564 {
565 List<XInventoryFolder> tree = new List<XInventoryFolder>();
566 XInventoryFolder[] folders = m_Database.GetFolders(
567 new string[] { "parentFolderID" },
568 new string[] { root.ToString() });
569  
570 if (folders == null || (folders != null && folders.Length == 0))
571 return tree; // empty tree
572 else
573 {
574 foreach (XInventoryFolder f in folders)
575 {
576 tree.Add(f);
577 tree.AddRange(GetFolderTreeRecursive(f.folderID));
578 }
579 return tree;
580 }
581  
582 }
583  
584 /// <summary>
585 /// Return true if the folderID is a subfolder of the Suitcase or the suitcase folder itself
586 /// </summary>
587 /// <param name="folderID"></param>
588 /// <param name="root"></param>
589 /// <param name="suitcase"></param>
590 /// <returns></returns>
591 private bool IsWithinSuitcaseTree(UUID principalID, UUID folderID)
592 {
593 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
594  
595 if (suitcase == null)
596 {
597 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder", principalID);
598 return false;
599 }
600  
601 List<XInventoryFolder> tree = new List<XInventoryFolder>();
602 tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder
603 tree.AddRange(GetFolderTree(principalID, suitcase.folderID));
604 // Also add the Current Outfit folder to the list of available folders
605 tree.Add(GetCurrentOutfitXFolder(principalID));
606  
607 XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl)
608 {
609 if (fl.folderID == folderID) return true;
610 else return false;
611 });
612  
613 if (f == null) return false;
614 else return true;
615 }
616 #endregion
617  
618 #region Avatar Appearance
619  
620 private AvatarAppearance GetAppearance(UUID principalID)
621 {
622 AvatarAppearance a = null;
623 if (m_Appearances.TryGetValue(principalID, out a))
624 return a;
625  
626 a = m_AvatarService.GetAppearance(principalID);
627 m_Appearances.AddOrUpdate(principalID, a, 5 * 60); // 5minutes
628 return a;
629 }
630  
631 private bool IsPartOfAppearance(UUID principalID, UUID itemID)
632 {
633 AvatarAppearance a = GetAppearance(principalID);
634  
635 if (a == null)
636 return false;
637  
638 // Check wearables (body parts and clothes)
639 for (int i = 0; i < a.Wearables.Length; i++)
640 {
641 for (int j = 0; j < a.Wearables[i].Count; j++)
642 {
643 if (a.Wearables[i][j].ItemID == itemID)
644 {
645 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is a wearable", itemID);
646 return true;
647 }
648 }
649 }
650  
651 // Check attachments
652 if (a.GetAttachmentForItem(itemID) != null)
653 {
654 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is an attachment", itemID);
655 return true;
656 }
657  
658 return false;
659 }
660  
661 #endregion
662  
663 }
664  
665 }