OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
HGSuitcaseInventoryService.cs
Go to the documentation of this file.
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 {
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, (int)FolderType.Suitcase, InventoryFolderBase.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)FolderType.Animation) return true; return false; }))
182  CreateFolder(principalID, rootID, (int)FolderType.Animation, "Animations");
183  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.BodyPart) return true; return false; }))
184  CreateFolder(principalID, rootID, (int)FolderType.BodyPart, "Body Parts");
185  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.CallingCard) return true; return false; }))
186  CreateFolder(principalID, rootID, (int)FolderType.CallingCard, "Calling Cards");
187  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Clothing) return true; return false; }))
188  CreateFolder(principalID, rootID, (int)FolderType.Clothing, "Clothing");
189  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.CurrentOutfit) return true; return false; }))
190  CreateFolder(principalID, rootID, (int)FolderType.CurrentOutfit, "Current Outfit");
191  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Favorites) return true; return false; }))
192  CreateFolder(principalID, rootID, (int)FolderType.Favorites, "Favorites");
193  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Gesture) return true; return false; }))
194  CreateFolder(principalID, rootID, (int)FolderType.Gesture, "Gestures");
195  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Landmark) return true; return false; }))
196  CreateFolder(principalID, rootID, (int)FolderType.Landmark, "Landmarks");
197  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.LostAndFound) return true; return false; }))
198  CreateFolder(principalID, rootID, (int)FolderType.LostAndFound, "Lost And Found");
199  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Notecard) return true; return false; }))
200  CreateFolder(principalID, rootID, (int)FolderType.Notecard, "Notecards");
201  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Object) return true; return false; }))
202  CreateFolder(principalID, rootID, (int)FolderType.Object, "Objects");
203  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Snapshot) return true; return false; }))
204  CreateFolder(principalID, rootID, (int)FolderType.Snapshot, "Photo Album");
205  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.LSLText) return true; return false; }))
206  CreateFolder(principalID, rootID, (int)FolderType.LSLText, "Scripts");
207  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Sound) return true; return false; }))
208  CreateFolder(principalID, rootID, (int)FolderType.Sound, "Sounds");
209  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Texture) return true; return false; }))
210  CreateFolder(principalID, rootID, (int)FolderType.Texture, "Textures");
211  if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Trash) return true; return false; }))
212  CreateFolder(principalID, rootID, (int)FolderType.Trash, "Trash");
213  }
214 
215  public override InventoryFolderBase GetFolderForType(UUID principalID, FolderType 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 
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 
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(), InventoryFolderBase.ROOT_FOLDER_NAME, ((int)FolderType.Root).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(), InventoryFolderBase.ROOT_FOLDER_NAME, 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)FolderType.CurrentOutfit).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(), ((int)FolderType.Suitcase).ToString() });
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(), InventoryFolderBase.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 = (int)FolderType.Suitcase;
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 
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 }
override List< InventoryItemBase > GetFolderItems(UUID principalID, UUID folderID)
Gets the items inside a folder
override bool MoveFolder(InventoryFolderBase folder)
Move an inventory folder to a new location
override List< InventoryFolderBase > GetInventorySkeleton(UUID principalID)
Gets the skeleton of the inventory – folders only
override bool MoveItems(UUID principalID, List< InventoryItemBase > items)
override bool AddFolder(InventoryFolderBase folder)
Add a new folder to the user's inventory
Contains the Avatar's Appearance and methods to manipulate the appearance.
override bool UpdateFolder(InventoryFolderBase folder)
Update a folder in the user's inventory
override bool AddItem(InventoryItemBase item)
Add a new item to the user's inventory
AvatarAttachment GetAttachmentForItem(UUID itemID)
If the item is already attached, return it.
virtual UUID Owner
The agent who's inventory this is contained by
override bool PurgeFolder(InventoryFolderBase folder)
Purge an inventory folder of all its items and subfolders.
override InventoryFolderBase GetFolderForType(UUID principalID, FolderType type)
Gets the user folder for the given folder-type
override bool CreateUserInventory(UUID principalID)
Create the entire inventory for a given user
Inventory Item - contains all the properties associated with an individual inventory piece...
new InventoryFolderBase GetFolder(InventoryFolderBase folder)
Get a folder, given by its UUID
virtual AvatarWearable[] Wearables
Hypergrid inventory service. It serves the IInventoryService interface, but implements it in ways tha...
UUID ID
A UUID containing the ID for the inventory node itself
override bool DeleteFolders(UUID principalID, List< UUID > folderIDs)
Delete an item from the user's inventory
override InventoryFolderBase GetRootFolder(UUID principalID)
Retrieve the root inventory folder for the given user.
override InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
Gets everything (folders and items) inside a folder
new InventoryItemBase GetItem(InventoryItemBase item)
Get an item, given by its UUID
override bool UpdateItem(InventoryItemBase item)
Update an item in the user's inventory
Used to serialize a whole inventory for transfer over the network.
override bool DeleteItems(UUID principalID, List< UUID > itemIDs)
Delete an item from the user's inventory