PageRenderTime 49ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/Aurora/Services/SQLServices/InventoryService/InventoryService.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 1616 lines | 1237 code | 196 blank | 183 comment | 314 complexity | 16e6342b9084f5dfaa2a8cfde07a47b0 MD5 | raw file
  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/, 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 Aurora-Sim 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. using Aurora.Framework;
  28. using Aurora.Framework.ClientInterfaces;
  29. using Aurora.Framework.ConsoleFramework;
  30. using Aurora.Framework.Modules;
  31. using Aurora.Framework.SceneInfo;
  32. using Aurora.Framework.Services;
  33. using Aurora.Framework.Services.ClassHelpers.Assets;
  34. using Aurora.Framework.Services.ClassHelpers.Inventory;
  35. using Aurora.Framework.Utilities;
  36. using Nini.Config;
  37. using OpenMetaverse;
  38. using OpenMetaverse.StructuredData;
  39. using System;
  40. using System.Collections.Generic;
  41. using System.Linq;
  42. namespace Aurora.Services.SQLServices.InventoryService
  43. {
  44. public class InventoryService : ConnectorBase, IInventoryService, IService
  45. {
  46. #region Declares
  47. protected bool m_AllowDelete = true;
  48. protected IAssetService m_AssetService;
  49. protected IInventoryData m_Database;
  50. protected ILibraryService m_LibraryService;
  51. protected IUserAccountService m_UserAccountService;
  52. protected Dictionary<UUID, InventoryItemBase> _tempItemCache = new Dictionary<UUID, InventoryItemBase>();
  53. #endregion
  54. #region IService Members
  55. public virtual string Name
  56. {
  57. get { return GetType().Name; }
  58. }
  59. public virtual void Initialize(IConfigSource config, IRegistryCore registry)
  60. {
  61. IConfig handlerConfig = config.Configs["Handlers"];
  62. if (handlerConfig.GetString("InventoryHandler", "") != Name)
  63. return;
  64. IConfig invConfig = config.Configs["InventoryService"];
  65. if (invConfig != null)
  66. m_AllowDelete = invConfig.GetBoolean("AllowDelete", true);
  67. if (MainConsole.Instance != null)
  68. MainConsole.Instance.Commands.AddCommand("fix inventory", "fix inventory",
  69. "If the user's inventory has been corrupted, this function will attempt to fix it",
  70. FixInventory);
  71. registry.RegisterModuleInterface<IInventoryService>(this);
  72. Init(registry, Name, serverPath: "/inventory/");
  73. }
  74. public virtual void Start(IConfigSource config, IRegistryCore registry)
  75. {
  76. m_Database = Framework.Utilities.DataManager.RequestPlugin<IInventoryData>();
  77. m_UserAccountService = registry.RequestModuleInterface<IUserAccountService>();
  78. m_LibraryService = registry.RequestModuleInterface<ILibraryService>();
  79. m_AssetService = registry.RequestModuleInterface<IAssetService>();
  80. registry.RequestModuleInterface<ISimulationBase>()
  81. .EventManager.RegisterEventHandler("DeleteUserInformation", DeleteUserInformation);
  82. }
  83. public virtual void FinishedStartup()
  84. {
  85. _addInventoryItemQueue.Start(0.5, (agentID, itemsToAdd) =>
  86. {
  87. if (itemsToAdd == null)
  88. return;
  89. foreach (AddInventoryItemStore item in itemsToAdd)
  90. {
  91. if (UUID.Zero == item.Item.Folder)
  92. {
  93. InventoryFolderBase f = GetFolderForType(item.Item.Owner,
  94. (InventoryType)
  95. item.Item.InvType,
  96. (AssetType)
  97. item.Item
  98. .AssetType);
  99. if (f != null)
  100. item.Item.Folder = f.ID;
  101. else
  102. {
  103. f = GetRootFolder(item.Item.Owner);
  104. if (f != null)
  105. item.Item.Folder = f.ID;
  106. else
  107. {
  108. MainConsole.Instance.WarnFormat(
  109. "[InventorySerivce]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
  110. item.Item.Owner, item.Item.Name);
  111. return;
  112. }
  113. }
  114. }
  115. AddItem(item.Item);
  116. lock (_tempItemCache)
  117. _tempItemCache.Remove(item.Item.ID);
  118. if (item.Complete != null)
  119. item.Complete(item.Item);
  120. }
  121. });
  122. _moveInventoryItemQueue.Start(0.5, (agentID, itemsToMove) =>
  123. {
  124. foreach (var item in itemsToMove)
  125. {
  126. MoveItems(agentID, item.Items);
  127. if (item.Complete != null)
  128. item.Complete();
  129. }
  130. });
  131. }
  132. #endregion
  133. #region IInventoryService Members
  134. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  135. public virtual bool CreateUserInventory(UUID principalID, bool createDefaultItems)
  136. {
  137. /*object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, createDefaultItems);
  138. if (remoteValue != null || m_doRemoteOnly)
  139. return remoteValue == null ? false : (bool)remoteValue;*/
  140. List<InventoryItemBase> items;
  141. return CreateUserInventory(principalID, createDefaultItems, out items);
  142. }
  143. public virtual bool CreateUserInventory(UUID principalID, bool createDefaultItems,
  144. out List<InventoryItemBase> defaultItems)
  145. {
  146. // This is braindeaad. We can't ever communicate that we fixed
  147. // an existing inventory. Well, just return root folder status,
  148. // but check sanity anyway.
  149. //
  150. bool result = false;
  151. InventoryFolderBase rootFolder = GetRootFolder(principalID);
  152. if (rootFolder == null)
  153. {
  154. rootFolder = CreateFolder(principalID, UUID.Zero, (int) AssetType.RootFolder, "My Inventory");
  155. result = true;
  156. }
  157. InventoryFolderBase[] sysFolders = GetSystemFolders(principalID);
  158. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  159. {
  160. if (f.Type == (short) AssetType.Animation) return true;
  161. return false;
  162. }))
  163. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Animation, "Animations");
  164. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  165. {
  166. if (f.Type == (short) AssetType.Bodypart) return true;
  167. return false;
  168. }))
  169. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Bodypart, "Body Parts");
  170. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  171. {
  172. if (f.Type == (short) AssetType.CallingCard) return true;
  173. return false;
  174. }))
  175. CreateFolder(principalID, rootFolder.ID, (int) AssetType.CallingCard, "Calling Cards");
  176. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  177. {
  178. if (f.Type == (short) AssetType.Clothing) return true;
  179. return false;
  180. }))
  181. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Clothing, "Clothing");
  182. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  183. {
  184. if (f.Type == (short) AssetType.Gesture) return true;
  185. return false;
  186. }))
  187. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Gesture, "Gestures");
  188. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  189. {
  190. if (f.Type == (short) AssetType.Landmark) return true;
  191. return false;
  192. }))
  193. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Landmark, "Landmarks");
  194. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  195. {
  196. if (f.Type == (short) AssetType.LostAndFoundFolder) return true;
  197. return false;
  198. }))
  199. CreateFolder(principalID, rootFolder.ID, (int) AssetType.LostAndFoundFolder, "Lost And Found");
  200. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  201. {
  202. if (f.Type == (short) AssetType.Notecard) return true;
  203. return false;
  204. }))
  205. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Notecard, "Notecards");
  206. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  207. {
  208. if (f.Type == (short) AssetType.Object) return true;
  209. return false;
  210. }))
  211. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Object, "Objects");
  212. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  213. {
  214. if (f.Type == (short) AssetType.SnapshotFolder) return true;
  215. return false;
  216. }))
  217. CreateFolder(principalID, rootFolder.ID, (int) AssetType.SnapshotFolder, "Photo Album");
  218. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  219. {
  220. if (f.Type == (short) AssetType.LSLText) return true;
  221. return false;
  222. }))
  223. CreateFolder(principalID, rootFolder.ID, (int) AssetType.LSLText, "Scripts");
  224. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  225. {
  226. if (f.Type == (short) AssetType.Sound) return true;
  227. return false;
  228. }))
  229. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Sound, "Sounds");
  230. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  231. {
  232. if (f.Type == (short) AssetType.Texture) return true;
  233. return false;
  234. }))
  235. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Texture, "Textures");
  236. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  237. {
  238. if (f.Type == (short) AssetType.TrashFolder) return true;
  239. return false;
  240. }))
  241. CreateFolder(principalID, rootFolder.ID, (int) AssetType.TrashFolder, "Trash");
  242. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  243. {
  244. if (f.Type == (short) AssetType.Mesh) return true;
  245. return false;
  246. }))
  247. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Mesh, "Mesh");
  248. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  249. {
  250. if (f.Type == (short) AssetType.Inbox) return true;
  251. return false;
  252. }))
  253. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Inbox, "Received Items");
  254. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  255. {
  256. if (f.Type == (short) AssetType.Outbox) return true;
  257. return false;
  258. }))
  259. CreateFolder(principalID, rootFolder.ID, (int) AssetType.Outbox, "Merchant Outbox");
  260. if (!Array.Exists(sysFolders, delegate(InventoryFolderBase f)
  261. {
  262. if (f.Type == (short) AssetType.CurrentOutfitFolder) return true;
  263. return false;
  264. }))
  265. CreateFolder(principalID, rootFolder.ID, (int) AssetType.CurrentOutfitFolder, "Current Outfit");
  266. if (createDefaultItems && m_LibraryService != null)
  267. {
  268. defaultItems = new List<InventoryItemBase>();
  269. InventoryFolderBase bodypartFolder = GetFolderForType(principalID, InventoryType.Unknown,
  270. AssetType.Bodypart);
  271. InventoryFolderBase clothingFolder = GetFolderForType(principalID, InventoryType.Unknown,
  272. AssetType.Clothing);
  273. // Default items
  274. InventoryItemBase defaultShape = new InventoryItemBase
  275. {
  276. Name = "Default shape",
  277. Description = "Default shape description",
  278. AssetType = (int) AssetType.Bodypart,
  279. InvType = (int) InventoryType.Wearable,
  280. Flags = (uint) WearableType.Shape,
  281. ID = UUID.Random()
  282. };
  283. //Give a new copy to every person
  284. AssetBase asset = m_AssetService.Get(AvatarWearable.DEFAULT_BODY_ASSET.ToString());
  285. if (asset != null)
  286. {
  287. asset.ID = UUID.Random();
  288. asset.ID = m_AssetService.Store(asset);
  289. defaultShape.AssetID = asset.ID;
  290. defaultShape.Folder = bodypartFolder.ID;
  291. defaultShape.CreatorId = m_LibraryService.LibraryOwner.ToString();
  292. defaultShape.Owner = principalID;
  293. defaultShape.BasePermissions = (uint) PermissionMask.All;
  294. defaultShape.CurrentPermissions = (uint) PermissionMask.All;
  295. defaultShape.EveryOnePermissions = (uint) PermissionMask.None;
  296. defaultShape.NextPermissions = (uint) PermissionMask.All;
  297. AddItem(defaultShape, false);
  298. defaultItems.Add(defaultShape);
  299. }
  300. InventoryItemBase defaultSkin = new InventoryItemBase
  301. {
  302. Name = "Default skin",
  303. Description = "Default skin description",
  304. AssetType = (int) AssetType.Bodypart,
  305. InvType = (int) InventoryType.Wearable,
  306. Flags = (uint) WearableType.Skin,
  307. ID = UUID.Random()
  308. };
  309. //Give a new copy to every person
  310. asset = m_AssetService.Get(AvatarWearable.DEFAULT_SKIN_ASSET.ToString());
  311. if (asset != null)
  312. {
  313. asset.ID = UUID.Random();
  314. asset.ID = m_AssetService.Store(asset);
  315. defaultSkin.AssetID = asset.ID;
  316. defaultSkin.Folder = bodypartFolder.ID;
  317. defaultSkin.CreatorId = m_LibraryService.LibraryOwner.ToString();
  318. defaultSkin.Owner = principalID;
  319. defaultSkin.BasePermissions = (uint) PermissionMask.All;
  320. defaultSkin.CurrentPermissions = (uint) PermissionMask.All;
  321. defaultSkin.EveryOnePermissions = (uint) PermissionMask.None;
  322. defaultSkin.NextPermissions = (uint) PermissionMask.All;
  323. AddItem(defaultSkin, false);
  324. defaultItems.Add(defaultSkin);
  325. }
  326. InventoryItemBase defaultHair = new InventoryItemBase
  327. {
  328. Name = "Default hair",
  329. Description = "Default hair description",
  330. AssetType = (int) AssetType.Bodypart,
  331. InvType = (int) InventoryType.Wearable,
  332. Flags = (uint) WearableType.Hair,
  333. ID = UUID.Random()
  334. };
  335. //Give a new copy to every person
  336. asset = m_AssetService.Get(AvatarWearable.DEFAULT_HAIR_ASSET.ToString());
  337. if (asset != null)
  338. {
  339. asset.ID = UUID.Random();
  340. asset.ID = m_AssetService.Store(asset);
  341. defaultHair.AssetID = asset.ID;
  342. defaultHair.Folder = bodypartFolder.ID;
  343. defaultHair.CreatorId = m_LibraryService.LibraryOwner.ToString();
  344. defaultHair.Owner = principalID;
  345. defaultHair.BasePermissions = (uint) PermissionMask.All;
  346. defaultHair.CurrentPermissions = (uint) PermissionMask.All;
  347. defaultHair.EveryOnePermissions = (uint) PermissionMask.None;
  348. defaultHair.NextPermissions = (uint) PermissionMask.All;
  349. AddItem(defaultHair, false);
  350. defaultItems.Add(defaultHair);
  351. }
  352. InventoryItemBase defaultEyes = new InventoryItemBase
  353. {
  354. Name = "Default eyes",
  355. Description = "Default eyes description",
  356. AssetType = (int) AssetType.Bodypart,
  357. InvType = (int) InventoryType.Wearable,
  358. Flags = (uint) WearableType.Eyes,
  359. ID = UUID.Random()
  360. };
  361. //Give a new copy to every person
  362. asset = m_AssetService.Get(AvatarWearable.DEFAULT_EYES_ASSET.ToString());
  363. if (asset != null)
  364. {
  365. asset.ID = UUID.Random();
  366. asset.ID = m_AssetService.Store(asset);
  367. defaultEyes.AssetID = asset.ID;
  368. defaultEyes.Folder = bodypartFolder.ID;
  369. defaultEyes.CreatorId = m_LibraryService.LibraryOwner.ToString();
  370. defaultEyes.Owner = principalID;
  371. defaultEyes.BasePermissions = (uint) PermissionMask.All;
  372. defaultEyes.CurrentPermissions = (uint) PermissionMask.All;
  373. defaultEyes.EveryOnePermissions = (uint) PermissionMask.None;
  374. defaultEyes.NextPermissions = (uint) PermissionMask.All;
  375. AddItem(defaultEyes, false);
  376. defaultItems.Add(defaultEyes);
  377. }
  378. InventoryItemBase defaultShirt = new InventoryItemBase
  379. {
  380. Name = "Default shirt",
  381. Description = "Default shirt description",
  382. AssetType = (int) AssetType.Clothing,
  383. InvType = (int) InventoryType.Wearable,
  384. Flags = (uint) WearableType.Shirt,
  385. ID = UUID.Random()
  386. };
  387. //Give a new copy to every person
  388. asset = m_AssetService.Get(AvatarWearable.DEFAULT_SHIRT_ASSET.ToString());
  389. if (asset != null)
  390. {
  391. OpenMetaverse.Assets.AssetClothing clothing = new OpenMetaverse.Assets.AssetClothing()
  392. {
  393. Creator = m_LibraryService.LibraryOwner,
  394. Name = "Default shirt",
  395. Owner = principalID,
  396. Permissions =
  397. new Permissions(
  398. (uint) PermissionMask.All,
  399. (uint) PermissionMask.All,
  400. (uint) PermissionMask.All,
  401. (uint) PermissionMask.All,
  402. (uint) PermissionMask.All),
  403. WearableType = WearableType.Shirt,
  404. Textures =
  405. new Dictionary<AvatarTextureIndex, UUID>()
  406. {
  407. {
  408. AvatarTextureIndex
  409. .UpperShirt
  410. ,
  411. UUID
  412. .Parse
  413. ("5748decc-f629-461c-9a36-a35a221fe21f")
  414. }
  415. }
  416. };
  417. clothing.Encode();
  418. asset.Data = clothing.AssetData;
  419. asset.ID = UUID.Random();
  420. asset.ID = m_AssetService.Store(asset);
  421. defaultShirt.AssetID = asset.ID;
  422. defaultShirt.Folder = clothingFolder.ID;
  423. defaultShirt.CreatorId = m_LibraryService.LibraryOwner.ToString();
  424. defaultShirt.Owner = principalID;
  425. defaultShirt.BasePermissions = (uint) PermissionMask.All;
  426. defaultShirt.CurrentPermissions = (uint) PermissionMask.All;
  427. defaultShirt.EveryOnePermissions = (uint) PermissionMask.None;
  428. defaultShirt.NextPermissions = (uint) PermissionMask.All;
  429. AddItem(defaultShirt, false);
  430. defaultItems.Add(defaultShirt);
  431. }
  432. InventoryItemBase defaultPants = new InventoryItemBase
  433. {
  434. Name = "Default pants",
  435. Description = "Default pants description",
  436. AssetType = (int) AssetType.Clothing,
  437. InvType = (int) InventoryType.Wearable,
  438. Flags = (uint) WearableType.Pants,
  439. ID = UUID.Random()
  440. };
  441. //Give a new copy to every person
  442. asset = m_AssetService.Get(AvatarWearable.DEFAULT_PANTS_ASSET.ToString());
  443. if (asset != null)
  444. {
  445. OpenMetaverse.Assets.AssetClothing clothing = new OpenMetaverse.Assets.AssetClothing()
  446. {
  447. Creator = m_LibraryService.LibraryOwner,
  448. Name = "Default pants",
  449. Owner = principalID,
  450. Permissions =
  451. new Permissions(
  452. (uint) PermissionMask.All,
  453. (uint) PermissionMask.All,
  454. (uint) PermissionMask.All,
  455. (uint) PermissionMask.All,
  456. (uint) PermissionMask.All),
  457. WearableType = WearableType.Pants,
  458. Textures =
  459. new Dictionary<AvatarTextureIndex, UUID>()
  460. {
  461. {
  462. AvatarTextureIndex
  463. .LowerPants
  464. ,
  465. UUID
  466. .Parse
  467. ("5748decc-f629-461c-9a36-a35a221fe21f")
  468. }
  469. }
  470. };
  471. clothing.Encode();
  472. asset.Data = clothing.AssetData;
  473. asset.ID = UUID.Random();
  474. asset.ID = m_AssetService.Store(asset);
  475. defaultPants.AssetID = asset.ID;
  476. defaultPants.Folder = clothingFolder.ID;
  477. defaultPants.CreatorId = m_LibraryService.LibraryOwner.ToString();
  478. defaultPants.Owner = principalID;
  479. defaultPants.BasePermissions = (uint) PermissionMask.All;
  480. defaultPants.CurrentPermissions = (uint) PermissionMask.All;
  481. defaultPants.EveryOnePermissions = (uint) PermissionMask.None;
  482. defaultPants.NextPermissions = (uint) PermissionMask.All;
  483. AddItem(defaultPants, false);
  484. defaultItems.Add(defaultPants);
  485. }
  486. }
  487. else
  488. defaultItems = new List<InventoryItemBase>();
  489. return result;
  490. }
  491. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  492. public virtual List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
  493. {
  494. /*object remoteValue = DoRemoteByURL("InventoryServerURI", principalID);
  495. if (remoteValue != null || m_doRemoteOnly)
  496. return (List<InventoryFolderBase>)remoteValue;*/
  497. List<InventoryFolderBase> allFolders = m_Database.GetFolders(
  498. new[] {"agentID"},
  499. new[] {principalID.ToString()});
  500. if (allFolders.Count == 0)
  501. return null;
  502. return allFolders;
  503. }
  504. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  505. public virtual List<InventoryFolderBase> GetRootFolders(UUID principalID)
  506. {
  507. /*object remoteValue = DoRemoteByURL("InventoryServerURI", principalID);
  508. if (remoteValue != null || m_doRemoteOnly)
  509. return (List<InventoryFolderBase>)remoteValue;*/
  510. return m_Database.GetFolders(
  511. new[] {"agentID", "parentFolderID"},
  512. new[] {principalID.ToString(), UUID.Zero.ToString()});
  513. }
  514. [CanBeReflected(ThreatLevel = ThreatLevel.Medium)]
  515. public virtual InventoryFolderBase GetRootFolder(UUID principalID)
  516. {
  517. object remoteValue = DoRemoteByURL("InventoryServerURI", principalID);
  518. if (remoteValue != null || m_doRemoteOnly)
  519. return (InventoryFolderBase) remoteValue;
  520. List<InventoryFolderBase> folders = m_Database.GetFolders(
  521. new[] {"agentID", "parentFolderID"},
  522. new[] {principalID.ToString(), UUID.Zero.ToString()});
  523. if (folders.Count == 0)
  524. return null;
  525. InventoryFolderBase root = null;
  526. #if (!ISWIN)
  527. foreach (InventoryFolderBase folder in folders)
  528. {
  529. if (folder.Name == "My Inventory") root = folder;
  530. }
  531. #else
  532. foreach (InventoryFolderBase folder in folders.Where(folder => folder.Name == "My Inventory"))
  533. root = folder;
  534. #endif
  535. if (folders == null) // oops
  536. root = folders[0];
  537. return root;
  538. }
  539. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  540. public virtual InventoryFolderBase GetFolderForType(UUID principalID, InventoryType invType, AssetType type)
  541. {
  542. object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, invType, type);
  543. if (remoteValue != null || m_doRemoteOnly)
  544. return (InventoryFolderBase) remoteValue;
  545. if (invType == InventoryType.Snapshot)
  546. type = AssetType.SnapshotFolder;
  547. //Fix for snapshots, as they get the texture asset type, but need to get checked as snapshotfolder types
  548. List<InventoryFolderBase> folders = m_Database.GetFolders(
  549. new[] {"agentID", "type"},
  550. new[] {principalID.ToString(), ((int) type).ToString()});
  551. if (folders.Count == 0)
  552. {
  553. // MainConsole.Instance.WarnFormat("[XINVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID);
  554. return null;
  555. }
  556. // MainConsole.Instance.DebugFormat(
  557. // "[XINVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}",
  558. // folders[0].folderName, folders[0].folderID, type, principalID);
  559. return folders[0];
  560. }
  561. [CanBeReflected(ThreatLevel = ThreatLevel.High)]
  562. public virtual InventoryCollection GetFolderContent(UUID UserID, UUID folderID)
  563. {
  564. object remoteValue = DoRemoteByURL("InventoryServerURI", UserID, folderID);
  565. if (remoteValue != null || m_doRemoteOnly)
  566. return (InventoryCollection) remoteValue;
  567. // This method doesn't receive a valud principal id from the
  568. // connector. So we disregard the principal and look
  569. // by ID.
  570. //
  571. MainConsole.Instance.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString());
  572. InventoryCollection inventory = new InventoryCollection
  573. {
  574. UserID = UserID,
  575. FolderID = folderID,
  576. Folders = m_Database.GetFolders(
  577. new[] {"parentFolderID"},
  578. new[] {folderID.ToString()}),
  579. Items = m_Database.GetItems(UserID,
  580. new[] {"parentFolderID"},
  581. new[] {folderID.ToString()})
  582. };
  583. return inventory;
  584. }
  585. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  586. public virtual List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
  587. {
  588. /*object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, folderID);
  589. if (remoteValue != null || m_doRemoteOnly)
  590. return (List<InventoryItemBase>)remoteValue;*/
  591. if (principalID != UUID.Zero)
  592. return m_Database.GetItems(principalID,
  593. new[] {"parentFolderID", "avatarID"},
  594. new[] {folderID.ToString(), principalID.ToString()});
  595. return m_Database.GetItems(principalID,
  596. new[] {"parentFolderID"},
  597. new[] {folderID.ToString()});
  598. }
  599. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  600. public virtual List<InventoryFolderBase> GetFolderFolders(UUID principalID, UUID folderID)
  601. {
  602. object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, folderID);
  603. if (remoteValue != null || m_doRemoteOnly)
  604. return (List<InventoryFolderBase>) remoteValue;
  605. // Since we probably don't get a valid principal here, either ...
  606. //
  607. List<InventoryFolderBase> invItems = m_Database.GetFolders(
  608. new[] {"parentFolderID"},
  609. new[] {folderID.ToString()});
  610. return invItems;
  611. }
  612. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  613. public virtual bool AddFolder(InventoryFolderBase folder)
  614. {
  615. object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
  616. if (remoteValue != null || m_doRemoteOnly)
  617. return remoteValue == null ? false : (bool) remoteValue;
  618. InventoryFolderBase check = GetFolder(folder);
  619. if (check != null)
  620. return false;
  621. return m_Database.StoreFolder(folder);
  622. }
  623. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  624. public virtual bool UpdateFolder(InventoryFolderBase folder)
  625. {
  626. object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
  627. if (remoteValue != null || m_doRemoteOnly)
  628. return remoteValue == null ? false : (bool) remoteValue;
  629. if (!m_AllowDelete) //Initial item MUST be created as a link folder
  630. if (folder.Type == (sbyte) AssetType.LinkFolder)
  631. return false;
  632. InventoryFolderBase check = GetFolder(folder);
  633. if (check == null)
  634. return AddFolder(folder);
  635. if (check.Type != -1 || folder.Type != -1)
  636. {
  637. if (folder.Version > check.Version)
  638. return false;
  639. check.Version = folder.Version;
  640. check.Type = folder.Type;
  641. check.Version++;
  642. return m_Database.StoreFolder(check);
  643. }
  644. if (folder.Version < check.Version)
  645. folder.Version = check.Version;
  646. folder.ID = check.ID;
  647. folder.Version++;
  648. return m_Database.StoreFolder(folder);
  649. }
  650. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  651. public virtual bool MoveFolder(InventoryFolderBase folder)
  652. {
  653. object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
  654. if (remoteValue != null || m_doRemoteOnly)
  655. return remoteValue == null ? false : (bool) remoteValue;
  656. List<InventoryFolderBase> x = m_Database.GetFolders(
  657. new[] {"folderID"},
  658. new[] {folder.ID.ToString()});
  659. if (x.Count == 0)
  660. return false;
  661. x[0].ParentID = folder.ParentID;
  662. return m_Database.StoreFolder(x[0]);
  663. }
  664. // We don't check the principal's ID here
  665. //
  666. [CanBeReflected(ThreatLevel = ThreatLevel.High)]
  667. public virtual bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
  668. {
  669. object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, folderIDs);
  670. if (remoteValue != null || m_doRemoteOnly)
  671. return remoteValue == null ? false : (bool) remoteValue;
  672. if (!m_AllowDelete)
  673. {
  674. foreach (UUID id in folderIDs)
  675. {
  676. if (!ParentIsLinkFolder(id))
  677. continue;
  678. InventoryFolderBase f = new InventoryFolderBase {ID = id};
  679. PurgeFolder(f);
  680. m_Database.DeleteFolders("folderID", id.ToString(), true);
  681. }
  682. return true;
  683. }
  684. // Ignore principal ID, it's bogus at connector level
  685. //
  686. foreach (UUID id in folderIDs)
  687. {
  688. if (!ParentIsTrash(id))
  689. continue;
  690. InventoryFolderBase f = new InventoryFolderBase {ID = id};
  691. PurgeFolder(f);
  692. m_Database.DeleteFolders("folderID", id.ToString(), true);
  693. }
  694. return true;
  695. }
  696. [CanBeReflected(ThreatLevel = ThreatLevel.High)]
  697. public virtual bool PurgeFolder(InventoryFolderBase folder)
  698. {
  699. object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
  700. if (remoteValue != null || m_doRemoteOnly)
  701. return remoteValue == null ? false : (bool) remoteValue;
  702. if (!m_AllowDelete && !ParentIsLinkFolder(folder.ID))
  703. return false;
  704. if (!ParentIsTrash(folder.ID))
  705. return false;
  706. List<InventoryFolderBase> subFolders = m_Database.GetFolders(
  707. new[] {"parentFolderID"},
  708. new[] {folder.ID.ToString()});
  709. foreach (InventoryFolderBase x in subFolders)
  710. {
  711. PurgeFolder(x);
  712. m_Database.DeleteFolders("folderID", x.ID.ToString(), true);
  713. }
  714. m_Database.DeleteItems("parentFolderID", folder.ID.ToString());
  715. return true;
  716. }
  717. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  718. public virtual bool ForcePurgeFolder(InventoryFolderBase folder)
  719. {
  720. /*object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
  721. if (remoteValue != null || m_doRemoteOnly)
  722. return remoteValue == null ? false : (bool)remoteValue;*/
  723. List<InventoryFolderBase> subFolders = m_Database.GetFolders(
  724. new[] {"parentFolderID"},
  725. new[] {folder.ID.ToString()});
  726. foreach (InventoryFolderBase x in subFolders)
  727. {
  728. ForcePurgeFolder(x);
  729. m_Database.DeleteFolders("folderID", x.ID.ToString(), false);
  730. }
  731. m_Database.DeleteItems("parentFolderID", folder.ID.ToString());
  732. m_Database.DeleteFolders("folderID", folder.ID.ToString(), false);
  733. return true;
  734. }
  735. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  736. public virtual bool AddItem(InventoryItemBase item)
  737. {
  738. object remoteValue = DoRemoteByURL("InventoryServerURI", item);
  739. if (remoteValue != null || m_doRemoteOnly)
  740. return remoteValue == null ? false : (bool) remoteValue;
  741. return AddItem(item, true);
  742. }
  743. public virtual bool AddItem(InventoryItemBase item, bool doParentFolderCheck)
  744. {
  745. if (doParentFolderCheck)
  746. {
  747. InventoryFolderBase folder = GetFolder(new InventoryFolderBase(item.Folder));
  748. if (folder == null || folder.Owner != item.Owner)
  749. return false;
  750. }
  751. m_Database.IncrementFolder(item.Folder);
  752. return m_Database.StoreItem(item);
  753. }
  754. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  755. public virtual bool UpdateItem(InventoryItemBase item)
  756. {
  757. object remoteValue = DoRemoteByURL("InventoryServerURI", item);
  758. if (remoteValue != null || m_doRemoteOnly)
  759. return remoteValue == null ? false : (bool) remoteValue;
  760. if (!m_AllowDelete) //Initial item MUST be created as a link or link folder
  761. if (item.AssetType == (sbyte) AssetType.Link || item.AssetType == (sbyte) AssetType.LinkFolder)
  762. return false;
  763. m_Database.IncrementFolder(item.Folder);
  764. return m_Database.StoreItem(item);
  765. }
  766. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  767. public virtual bool UpdateAssetIDForItem(UUID itemID, UUID assetID)
  768. {
  769. object remoteValue = DoRemoteByURL("InventoryServerURI", itemID, assetID);
  770. if (remoteValue != null || m_doRemoteOnly)
  771. return remoteValue == null ? false : (bool) remoteValue;
  772. return m_Database.UpdateAssetIDForItem(itemID, assetID);
  773. }
  774. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  775. public virtual bool MoveItems(UUID principalID, List<InventoryItemBase> items)
  776. {
  777. object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, items);
  778. if (remoteValue != null || m_doRemoteOnly)
  779. return remoteValue == null ? false : (bool) remoteValue;
  780. foreach (InventoryItemBase i in items)
  781. {
  782. m_Database.IncrementFolder(i.Folder); //Increment the new folder
  783. m_Database.IncrementFolderByItem(i.ID);
  784. //And the old folder too (have to use this one because we don't know the old folder)
  785. m_Database.MoveItem(i.ID.ToString(), i.Folder.ToString());
  786. }
  787. return true;
  788. }
  789. [CanBeReflected(ThreatLevel = ThreatLevel.High)]
  790. public virtual bool DeleteItems(UUID principalID, List<UUID> itemIDs)
  791. {
  792. object remoteValue = DoRemoteByURL("InventoryServerURI", principalID, itemIDs);
  793. if (remoteValue != null || m_doRemoteOnly)
  794. return remoteValue == null ? false : (bool) remoteValue;
  795. if (!m_AllowDelete)
  796. {
  797. foreach (UUID id in itemIDs)
  798. {
  799. InventoryItemBase item = GetItem(principalID, id);
  800. m_Database.IncrementFolder(item.Folder);
  801. if (!ParentIsLinkFolder(item.Folder))
  802. continue;
  803. m_Database.DeleteItems("inventoryID", id.ToString());
  804. }
  805. return true;
  806. }
  807. // Just use the ID... *facepalms*
  808. //
  809. foreach (UUID id in itemIDs)
  810. {
  811. m_Database.IncrementFolderByItem(id);
  812. m_Database.DeleteItems("inventoryID", id.ToString());
  813. }
  814. return true;
  815. }
  816. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  817. public virtual InventoryItemBase GetItem(UUID userID, UUID inventoryID)
  818. {
  819. lock (_tempItemCache)
  820. {
  821. if (_tempItemCache.ContainsKey(inventoryID))
  822. return _tempItemCache[inventoryID];
  823. }
  824. object remoteValue = DoRemoteByURL("InventoryServerURI", userID, inventoryID);
  825. if (remoteValue != null || m_doRemoteOnly)
  826. return (InventoryItemBase) remoteValue;
  827. string[] fields = userID != UUID.Zero ? new[] {"inventoryID", "avatarID"} : new[] {"inventoryID"};
  828. string[] vals = userID != UUID.Zero
  829. ? new[] {inventoryID.ToString(), userID.ToString()}
  830. : new[] {inventoryID.ToString()};
  831. List<InventoryItemBase> items = m_Database.GetItems(userID,
  832. fields,
  833. vals);
  834. if (items.Count == 0)
  835. return null;
  836. return items[0];
  837. }
  838. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  839. public virtual UUID GetItemAssetID(UUID userID, UUID inventoryID)
  840. {
  841. lock (_tempItemCache)
  842. {
  843. if (_tempItemCache.ContainsKey(inventoryID))
  844. return _tempItemCache[inventoryID].AssetID;
  845. }
  846. object remoteValue = DoRemoteByURL("InventoryServerURI", userID, inventoryID);
  847. if (remoteValue != null || m_doRemoteOnly)
  848. return (UUID) remoteValue;
  849. List<UUID> items = m_Database.GetItemAssetIDs(userID,
  850. new[] {"inventoryID", "avatarID"},
  851. new[] {inventoryID.ToString(), userID.ToString()});
  852. if (items.Count == 0)
  853. return UUID.Zero;
  854. return items[0];
  855. }
  856. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  857. public virtual OSDArray GetOSDItem(UUID avatarID, UUID itemID)
  858. {
  859. /*object remoteValue = DoRemoteByURL("InventoryServerURI", avatarID, itemID);
  860. if (remoteValue != null || m_doRemoteOnly)
  861. return (OSDArray)remoteValue;*/
  862. if (avatarID != UUID.Zero)
  863. {
  864. return m_Database.GetLLSDItems(
  865. new string[2] {"inventoryID", "avatarID"},
  866. new string[2] {itemID.ToString(), avatarID.ToString()});
  867. }
  868. return m_Database.GetLLSDItems(
  869. new string[1] {"inventoryID"},
  870. new string[1] {itemID.ToString()});
  871. }
  872. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  873. public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder)
  874. {
  875. object remoteValue = DoRemoteByURL("InventoryServerURI", folder);
  876. if (remoteValue != null || m_doRemoteOnly)
  877. return (InventoryFolderBase) remoteValue;
  878. List<InventoryFolderBase> folders = m_Database.GetFolders(
  879. new[] {"folderID"},
  880. new[] {folder.ID.ToString()});
  881. if (folders.Count == 0)
  882. return null;
  883. return folders[0];
  884. }
  885. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  886. public virtual InventoryFolderBase GetFolderByOwnerAndName(UUID FolderOwner, string FolderName)
  887. {
  888. object remoteValue = DoRemoteByURL("InventoryServerURI", FolderOwner, FolderName);
  889. if (remoteValue != null || m_doRemoteOnly)
  890. return (InventoryFolderBase) remoteValue;
  891. List<InventoryFolderBase> folders = m_Database.GetFolders(
  892. new[] {"folderName", "agentID"},
  893. new[] {FolderName, FolderOwner.ToString()});
  894. if (folders.Count == 0)
  895. return null;
  896. return folders[0];
  897. }
  898. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  899. public virtual List<InventoryItemBase> GetActiveGestures(UUID principalID)
  900. {
  901. /*object remoteValue = DoRemoteByURL("InventoryServerURI", principalID);
  902. if (remoteValue != null || m_doRemoteOnly)
  903. return (List<InventoryItemBase>)remoteValue;*/
  904. return new List<InventoryItemBase>(m_Database.GetActiveGestures(principalID));
  905. }
  906. public object DeleteUserInformation(string name, object param)
  907. {
  908. UUID user = (UUID) param;
  909. var skel = GetInventorySkeleton(user);
  910. foreach (var folder in skel)
  911. {
  912. var items = GetFolderContent(user, folder.ID);
  913. DeleteItems(user, items.Items.ConvertAll<UUID>((item) => item.ID));
  914. ForcePurgeFolder(folder);
  915. }
  916. return null;
  917. }
  918. #endregion
  919. #region Asynchronous Commands
  920. protected ListCombiningTimedSaving<AddInventoryItemStore> _addInventoryItemQueue =
  921. new ListCombiningTimedSaving<AddInventoryItemStore>();
  922. protected ListCombiningTimedSaving<MoveInventoryItemStore> _moveInventoryItemQueue =
  923. new ListCombiningTimedSaving<MoveInventoryItemStore>();
  924. public void AddItemAsync(InventoryItemBase item, Action<InventoryItemBase> success)
  925. {
  926. if (item == null)
  927. return;
  928. lock (_tempItemCache)
  929. {
  930. if (!_tempItemCache.ContainsKey(item.ID))
  931. _tempItemCache.Add(item.ID, item);
  932. }
  933. _addInventoryItemQueue.Add(item.Owner, new AddInventoryItemStore(item, success));
  934. }
  935. public void MoveItemsAsync(UUID agentID, List<InventoryItemBase> items, NoParam success)
  936. {
  937. _moveInventoryItemQueue.Add(agentID, new MoveInventoryItemStore(items, success));
  938. }
  939. /// <summary>
  940. /// Give an entire inventory folder from one user to another. The entire contents (including all descendent
  941. /// folders) is given.
  942. /// </summary>
  943. /// <param name="recipientId"></param>
  944. /// <param name="senderId">ID of the sender of the item</param>
  945. /// <param name="folderId"></param>
  946. /// <param name="recipientParentFolderId">
  947. /// The id of the receipient folder in which the send folder should be placed. If UUID.Zero then the
  948. /// recipient folder is the root folder
  949. /// </param>
  950. /// <param name="success"></param>
  951. /// <returns>
  952. /// The inventory folder copy given, null if the copy was unsuccessful
  953. /// </returns>
  954. public void GiveInventoryFolderAsync(
  955. UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId, GiveFolderParam success)
  956. {
  957. Util.FireAndForget(o =>
  958. {
  959. // Retrieve the folder from the sender
  960. InventoryFolderBase folder = GetFolder(new InventoryFolderBase(folderId));
  961. if (null == folder)
  962. {
  963. MainConsole.Instance.ErrorFormat(
  964. "[InventoryService]: Could not find inventory folder {0} to give",
  965. folderId);
  966. success(null);
  967. return;
  968. }
  969. //Find the folder for the receiver
  970. if (recipientParentFolderId == UUID.Zero)
  971. {
  972. InventoryFolderBase recipientRootFolder = GetRootFolder(recipientId);
  973. if (recipientRootFolder != null)
  974. recipientParentFolderId = recipientRootFolder.ID;
  975. else
  976. {
  977. MainConsole.Instance.WarnFormat(
  978. "[InventoryService]: Unable to find root folder for receiving agent");
  979. success(null);
  980. return;
  981. }
  982. }
  983. UUID newFolderId = UUID.Random();
  984. InventoryFolderBase newFolder
  985. = new InventoryFolderBase(
  986. newFolderId, folder.Name, recipientId, folder.Type,
  987. recipientParentFolderId, folder.Version);
  988. AddFolder(newFolder);
  989. // Give all the subfolders
  990. InventoryCollection contents = GetFolderContent(senderId, folderId);
  991. foreach (InventoryFolderBase childFolder in contents.Folders)
  992. {
  993. GiveInventoryFolderAsync(recipientId, senderId, childFolder.ID, newFolder.ID,
  994. null);
  995. }
  996. // Give all the items
  997. foreach (InventoryItemBase item in contents.Items)
  998. {
  999. InnerGiveInventoryItem(recipientId, senderId, item, newFolder.ID, true);
  1000. }
  1001. success(newFolder);
  1002. });
  1003. }
  1004. /// <summary>
  1005. /// Give an inventory item from one user to another
  1006. /// </summary>
  1007. /// <param name="recipient"></param>
  1008. /// <param name="senderId">ID of the sender of the item</param>
  1009. /// <param name="itemId"></param>
  1010. /// <param name="recipientFolderId">
  1011. /// The id of the folder in which the copy item should go. If UUID.Zero then the item is placed in the most
  1012. /// appropriate default folder.
  1013. /// </param>
  1014. /// <param name="doOwnerCheck">This is for when the item is being given away publically, such as when it is posted on a group notice</param>
  1015. /// <param name="success"></param>
  1016. /// <returns>
  1017. /// The inventory item copy given, null if the give was unsuccessful
  1018. /// </returns>
  1019. public void GiveInventoryItemAsync(UUID recipient, UUID senderId, UUID itemId,
  1020. UUID recipientFolderId, bool doOwnerCheck, GiveItemParam success)
  1021. {
  1022. Util.FireAndForget(o =>
  1023. {
  1024. InventoryItemBase item = GetItem(senderId, itemId);
  1025. success(InnerGiveInventoryItem(recipient, senderId,
  1026. item, recipientFolderId, doOwnerCheck));
  1027. });
  1028. }
  1029. public InventoryItemBase InnerGiveInventoryItem(
  1030. UUID recipient, UUID senderId, InventoryItemBase item, UUID recipientFolderId, bool doOwnerCheck)
  1031. {
  1032. if (item == null)
  1033. {
  1034. MainConsole.Instance.Info("[InventoryService]: Could not find item to give to " + recipient);
  1035. return null;
  1036. }
  1037. if (!doOwnerCheck || item.Owner == senderId)
  1038. {
  1039. if ((item.CurrentPermissions & (uint) PermissionMask.Transfer) == 0)
  1040. return null;
  1041. // Insert a copy of the item into the recipient
  1042. InventoryItemBase itemCopy = new InventoryItemBase
  1043. {
  1044. Owner = recipient,
  1045. CreatorId = item.CreatorId,
  1046. CreatorData = item.CreatorData,
  1047. ID = UUID.Random(),
  1048. AssetID = item.AssetID,
  1049. Description = item.Description,
  1050. Name = item.Name,
  1051. AssetType = item.AssetType,
  1052. InvType = item.InvType,
  1053. Folder = recipientFolderId
  1054. };
  1055. if (recipient != senderId)
  1056. {
  1057. // Trying to do this right this time. This is evil. If
  1058. // you believe in Good, go elsewhere. Vampires and other
  1059. // evil creatores only beyond this point. You have been
  1060. // warned.
  1061. // We're going to mask a lot of things by the next perms
  1062. // Tweak the next perms to be nicer to our data
  1063. //
  1064. // In this mask, all the bits we do NOT want to mess
  1065. // with are set. These are:
  1066. //
  1067. // Transfer
  1068. // Copy
  1069. // Modufy
  1070. const uint permsMask = ~((uint) PermissionMask.Copy |
  1071. (uint) PermissionMask.Transfer |
  1072. (uint) PermissionMask.Modify);
  1073. // Now, reduce the next perms to the mask bits
  1074. // relevant to the operation
  1075. uint nextPerms = permsMask | (item.NextPermissions &
  1076. ((uint) PermissionMask.Copy |
  1077. (uint) PermissionMask.Transfer |
  1078. (uint) PermissionMask.Modify));
  1079. // nextPerms now has all bits set, except for the actual
  1080. // next permission bits.
  1081. // This checks for no mod, no copy, no trans.
  1082. // This indicates an error or messed up item. Do it like
  1083. // SL and assume trans
  1084. if (nextPerms == permsMask)
  1085. nextPerms |= (uint) PermissionMask.Transfer;
  1086. // Inventory owner perms are the logical AND of the
  1087. // folded perms and the root prim perms, however, if
  1088. // the root prim is mod, the inventory perms will be
  1089. // mod. This happens on "take" and is of little concern
  1090. // here, save for preventing escalation
  1091. // This hack ensures that items previously permalocked
  1092. // get unlocked when they're passed or rezzed
  1093. uint basePerms = item.BasePermissions |
  1094. (uint) PermissionMask.Move;
  1095. uint ownerPerms = item.CurrentPermissions;
  1096. // If this is an object, root prim perms may be more
  1097. // permissive than folded perms. Use folded perms as
  1098. // a mask
  1099. if (item.InvType == (int) InventoryType.Object)
  1100. {
  1101. // Create a safe mask for the current perms
  1102. uint foldedPerms = (item.CurrentPermissions & 7) << 13;
  1103. foldedPerms |= permsMask;
  1104. bool isRootMod = (item.CurrentPermissions &
  1105. (uint) PermissionMask.Modify) != 0;
  1106. // Mask the owner perms to the folded perms
  1107. ownerPerms &= foldedPerms;
  1108. basePerms &= foldedPerms;
  1109. // If the root was mod, let the mask reflect that
  1110. // We also need to adjust the base here, because
  1111. // we should be able to edit in-inventory perms
  1112. // for the root prim, if it's mod.
  1113. if (isRootMod)
  1114. {
  1115. ownerPerms |= (uint) PermissionMask.Modify;
  1116. basePerms |= (uint) PermissionMask.Modify;
  1117. }
  1118. }
  1119. // These will be applied to the root prim at next rez.
  1120. // The slam bit (bit 3) and folded permission (bits 0-2)
  1121. // are preserved due to the above mangling
  1122. ownerPerms &= nextPerms;
  1123. // Mask the base permissions. This is a conservative
  1124. // approach altering only the three main perms
  1125. basePerms &= nextPerms;
  1126. // Assign to the actual item. Make sure the slam bit is
  1127. // set, if it wasn't set before.
  1128. itemCopy.BasePermissions = basePerms;
  1129. itemCopy.CurrentPermissions = ownerPerms | 16; // Slam
  1130. itemCopy.NextPermissions = item.NextPermissions;
  1131. // This preserves "everyone can move"
  1132. itemCopy.EveryOnePermissions = item.EveryOnePermissions &
  1133. nextPerms;
  1134. // Intentionally killing "share with group" here, as
  1135. // the recipient will not have the group this is
  1136. // set to
  1137. itemCopy.GroupPermissions = 0;
  1138. }
  1139. else
  1140. {
  1141. itemCopy.CurrentPermissions = item.CurrentPermissions;
  1142. itemCopy.NextPermissions = item.NextPermissions;
  1143. itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions;
  1144. itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions;
  1145. itemCopy.BasePermissions = item.BasePermissions;
  1146. }
  1147. if (itemCopy.Folder == UUID.Zero)
  1148. {
  1149. InventoryFolderBase folder = GetFolderForType(recipient,
  1150. (InventoryType) itemCopy.InvType,
  1151. (AssetType) itemCopy.AssetType);
  1152. if (folder != null)
  1153. itemCopy.Folder = folder.ID;
  1154. }
  1155. itemCopy.GroupID = UUID.Zero;
  1156. itemCopy.GroupOwned = false;
  1157. itemCopy.Flags = item.Flags;
  1158. itemCopy.SalePrice = item.SalePrice;
  1159. itemCopy.SaleType = item.SaleType;
  1160. AddItem(itemCopy);
  1161. if ((item.CurrentPermissions & (uint) PermissionMask.Copy) == 0)
  1162. DeleteItems(senderId, new List<UUID> {item.ID});
  1163. return itemCopy;
  1164. }
  1165. MainConsole.Instance.WarnFormat(
  1166. "[InventoryService]: Failed to give item {0} as item does not belong to giver", item.ID.ToString());
  1167. return null;
  1168. }
  1169. #region Internal Classes
  1170. protected class AddInventoryItemStore
  1171. {
  1172. public AddInventoryItemStore(InventoryItemBase item, Action<InventoryItemBase> success)
  1173. {
  1174. Item = item;
  1175. Complete = success;
  1176. }
  1177. public InventoryItemBase Item;
  1178. public Action<InventoryItemBase> Complete;
  1179. }
  1180. protected class MoveInventoryItemStore
  1181. {
  1182. public MoveInventoryItemStore(List<InventoryItemBase> items, NoParam success)
  1183. {
  1184. Items = items;
  1185. Complete = success;
  1186. }
  1187. public List<InventoryItemBase> Items;
  1188. public NoParam Complete;
  1189. }
  1190. #endregion
  1191. #endregion
  1192. #region Console Commands
  1193. public virtual void FixInventory(string[] cmd)
  1194. {
  1195. string userName = MainConsole.Instance.Prompt("Name of user");
  1196. UserAccount account = m_UserAccountService.GetUserAccount(null, userName);
  1197. if (account == null)
  1198. {
  1199. MainConsole.Instance.Warn("Could not find user");
  1200. return;
  1201. }
  1202. InventoryFolderBase rootFolder = GetRootFolder(account.PrincipalID);
  1203. //Fix having a default root folder
  1204. if (rootFolder == null)
  1205. {
  1206. MainConsole.Instance.Warn("Fixing default root folder...");
  1207. List<InventoryFolderBase> skel = GetInventorySkeleton(account.PrincipalID);
  1208. if (skel.Count == 0)
  1209. {
  1210. CreateUserInventory(account.PrincipalID, false);
  1211. rootFolder = GetRootFolder(account.PrincipalID);
  1212. }
  1213. else
  1214. {
  1215. rootFolder = new InventoryFolderBase
  1216. {
  1217. Name = "My Inventory",
  1218. Type = (short) AssetType.RootFolder,
  1219. Version = 1,
  1220. ID = skel[0].ParentID,
  1221. Owner = account.PrincipalID,
  1222. ParentID = UUID.Zero
  1223. };
  1224. }
  1225. }
  1226. //Check against multiple root folders
  1227. List<InventoryFolderBase> rootFolders = GetRootFolders(account.PrincipalID);
  1228. List<UUID> badFolders = new List<UUID>();
  1229. if (rootFolders.Count != 1)
  1230. {
  1231. //No duplicate folders!
  1232. foreach (
  1233. InventoryFolderBase f in rootFolders.Where(f => !badFolders.Contains(f.ID) && f.ID != rootFolder.ID)
  1234. )
  1235. {
  1236. MainConsole.Instance.Warn("Removing duplicate root folder " + f.Name);
  1237. badFolders.Add(f.ID);
  1238. }
  1239. }
  1240. //Fix any root folders that shouldn't be root folders
  1241. List<InventoryFolderBase> skeleton = GetInventorySkeleton(account.PrincipalID);
  1242. List<UUID> foundFolders = new List<UUID>();
  1243. foreach (InventoryFolderBase f in skeleton)
  1244. {
  1245. if (!foundFolders.Contains(f.ID))
  1246. foundFolders.Add(f.ID);
  1247. if (f.Name == "My Inventory" && f.ParentID != UUID.Zero)
  1248. {
  1249. //Merge them all together
  1250. badFolders.Add(f.ID);
  1251. }
  1252. }
  1253. foreach (InventoryFolderBase f in skeleton)
  1254. {
  1255. if ((!foundFolders.Contains(f.ParentID) && f.ParentID != UUID.Zero) ||
  1256. f.ID == f.ParentID)
  1257. {
  1258. //The viewer loses the parentID when something goes wrong
  1259. //it puts it in the top where My Inventory should be
  1260. //We need to put it back in the My Inventory folder, as the sub folders are right for some reason
  1261. f.ParentID = rootFolder.ID;
  1262. m_Database.StoreFolder(f);
  1263. MainConsole.Instance.WarnFormat("Fixing folder {0}", f.Name);
  1264. }
  1265. else if (badFolders.Contains(f.ParentID))
  1266. {
  1267. //Put it back in the My Inventory folder
  1268. f.ParentID = rootFolder.ID;
  1269. m_Database.StoreFolder(f);
  1270. MainConsole.Instance.WarnFormat("Fixing folder {0}", f.Name);
  1271. }
  1272. else if (f.Type == (short) AssetType.CurrentOutfitFolder)
  1273. {
  1274. List<InventoryItemBase> items = GetFolderItems(account.PrincipalID, f.ID);
  1275. //Check the links!
  1276. List<UUID> brokenLinks = new List<UUID>();
  1277. foreach (InventoryItemBase item in items)
  1278. {
  1279. InventoryItemBase linkedItem = null;
  1280. if ((linkedItem = GetItem(account.PrincipalID, item.AssetID)) == null)
  1281. {
  1282. //Broken link...
  1283. brokenLinks.Add(item.ID);
  1284. }
  1285. else if (linkedItem.ID == AvatarWearable.DEFAULT_EYES_ITEM ||
  1286. linkedItem.ID == AvatarWearable.DEFAULT_BODY_ITEM ||
  1287. linkedItem.ID == AvatarWearable.DEFAULT_HAIR_ITEM ||
  1288. linkedItem.ID == AvatarWearable.DEFAULT_PANTS_ITEM ||
  1289. linkedItem.ID == AvatarWearable.DEFAULT_SHIRT_ITEM ||
  1290. linkedItem.ID == AvatarWearable.DEFAULT_SKIN_ITEM)
  1291. {
  1292. //Default item link, needs removed
  1293. brokenLinks.Add(item.ID);
  1294. }
  1295. }
  1296. if (brokenLinks.Count != 0)
  1297. DeleteItems(account.PrincipalID, brokenLinks);
  1298. }
  1299. else if (f.Type == (short) AssetType.Mesh)
  1300. {
  1301. ForcePurgeFolder(f);
  1302. }
  1303. }
  1304. foreach (UUID id in badFolders)
  1305. {
  1306. m_Database.DeleteFolders("folderID", id.ToString(), false);
  1307. }
  1308. //Make sure that all default folders exist
  1309. CreateUserInventory(account.PrincipalID, false);
  1310. //Refetch the skeleton now
  1311. skeleton = GetInventorySkeleton(account.PrincipalID);
  1312. Dictionary<int, UUID> defaultFolders = new Dictionary<int, UUID>();
  1313. Dictionary<UUID, UUID> changedFolders = new Dictionary<UUID, UUID>();
  1314. foreach (InventoryFolderBase folder in skeleton.Where(folder => folder.Type != -1))
  1315. {
  1316. if (!defaultFolders.ContainsKey(folder.Type))
  1317. defaultFolders[folder.Type] = folder.ID;
  1318. else
  1319. changedFolders.Add(folder.ID, defaultFolders[folder.Type]);
  1320. }
  1321. foreach (InventoryFolderBase folder in skeleton)
  1322. {
  1323. if (folder.Type != -1 && defaultFolders[folder.Type] != folder.ID)
  1324. {
  1325. //Delete the dup
  1326. ForcePurgeFolder(folder);
  1327. MainConsole.Instance.Warn("Purging duplicate default inventory type folder " + folder.Name);
  1328. }
  1329. if (changedFolders.ContainsKey(folder.ParentID))
  1330. {
  1331. folder.ParentID = changedFolders[folder.ParentID];
  1332. MainConsole.Instance.Warn("Merging child folder of default inventory type " + folder.Name);
  1333. m_Database.StoreFolder(folder);
  1334. }
  1335. }
  1336. MainConsole.Instance.Warn("Completed the check");
  1337. }
  1338. #endregion
  1339. #region Helpers
  1340. protected InventoryFolderBase CreateFolder(UUID principalID, UUID parentID, int type, string name)
  1341. {
  1342. InventoryFolderBase newFolder = new InventoryFolderBase
  1343. {
  1344. Name = name,
  1345. Type = (short) type,
  1346. Version = 1,
  1347. ID = UUID.Random(),
  1348. Owner = principalID,
  1349. ParentID = parentID
  1350. };
  1351. m_Database.StoreFolder(newFolder);
  1352. return newFolder;
  1353. }
  1354. protected virtual InventoryFolderBase[] GetSystemFolders(UUID principalID)
  1355. {
  1356. // MainConsole.Instance.DebugFormat("[XINVENTORY SERVICE]: Getting system folders for {0}", principalID);
  1357. InventoryFolderBase[] allFolders = m_Database.GetFolders(
  1358. new[] {"agentID"},
  1359. new[] {principalID.ToString()}).ToArray();
  1360. InventoryFolderBase[] sysFolders = Array.FindAll(
  1361. allFolders,
  1362. delegate(InventoryFolderBase f)
  1363. {
  1364. if (f.Type > 0)
  1365. return true;
  1366. return false;
  1367. });
  1368. // MainConsole.Instance.DebugFormat(
  1369. // "[XINVENTORY SERVICE]: Found {0} system folders for {1}", sysFolders.Length, principalID);
  1370. return sysFolders;
  1371. }
  1372. private bool ParentIsTrash(UUID folderID)
  1373. {
  1374. List<InventoryFolderBase> folder = m_Database.GetFolders(new[] {"folderID"}, new[] {folderID.ToString()});
  1375. if (folder.Count < 1)
  1376. return false;
  1377. if (folder[0].Type == (int) AssetType.TrashFolder ||
  1378. folder[0].Type == (int) AssetType.LostAndFoundFolder)
  1379. return true;
  1380. UUID parentFolder = folder[0].ParentID;
  1381. while (parentFolder != UUID.Zero)
  1382. {
  1383. List<InventoryFolderBase> parent = m_Database.GetFolders(new[] {"folderID"},
  1384. new[] {parentFolder.ToString()});
  1385. if (parent.Count < 1)
  1386. return false;
  1387. if (parent[0].Type == (int) AssetType.TrashFolder ||
  1388. parent[0].Type == (int) AssetType.LostAndFoundFolder)
  1389. return true;
  1390. if (parent[0].Type == (int) AssetType.RootFolder)
  1391. return false;
  1392. parentFolder = parent[0].ParentID;
  1393. }
  1394. return false;
  1395. }
  1396. private bool ParentIsLinkFolder(UUID folderID)
  1397. {
  1398. List<InventoryFolderBase> folder = m_Database.GetFolders(new[] {"folderID"}, new[] {folderID.ToString()});
  1399. if (folder.Count < 1)
  1400. return false;
  1401. if (folder[0].Type == (int) AssetType.LinkFolder)
  1402. return true;
  1403. UUID parentFolder = folder[0].ParentID;
  1404. while (parentFolder != UUID.Zero)
  1405. {
  1406. List<InventoryFolderBase> parent = m_Database.GetFolders(new[] {"folderID"},
  1407. new[] {parentFolder.ToString()});
  1408. if (parent.Count < 1)
  1409. return false;
  1410. if (parent[0].Type == (int) AssetType.LinkFolder)
  1411. return true;
  1412. if (parent[0].Type == (int) AssetType.RootFolder)
  1413. return false;
  1414. parentFolder = parent[0].ParentID;
  1415. }
  1416. return false;
  1417. }
  1418. #endregion
  1419. }
  1420. }