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