SimianInventoryServiceConnector.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  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. using System;
  28. using System.Collections.Generic;
  29. using System.Collections.Specialized;
  30. using System.Reflection;
  31. using log4net;
  32. using Mono.Addins;
  33. using Nini.Config;
  34. using OpenMetaverse;
  35. using OpenMetaverse.StructuredData;
  36. using OpenSim.Framework;
  37. using OpenSim.Region.Framework.Interfaces;
  38. using OpenSim.Region.Framework.Scenes;
  39. using OpenSim.Services.Interfaces;
  40. using PermissionMask = OpenSim.Framework.PermissionMask;
  41. namespace OpenSim.Services.Connectors.SimianGrid
  42. {
  43. /// <summary>
  44. /// Permissions bitflags
  45. /// </summary>
  46. /*
  47. [Flags]
  48. public enum PermissionMask : uint
  49. {
  50. None = 0,
  51. Transfer = 1 << 13,
  52. Modify = 1 << 14,
  53. Copy = 1 << 15,
  54. Move = 1 << 19,
  55. Damage = 1 << 20,
  56. All = 0x7FFFFFFF
  57. }
  58. */
  59. /// <summary>
  60. /// Connects avatar inventories to the SimianGrid backend
  61. /// </summary>
  62. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianInventoryServiceConnector")]
  63. public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule
  64. {
  65. private static readonly ILog m_log =
  66. LogManager.GetLogger(
  67. MethodBase.GetCurrentMethod().DeclaringType);
  68. private string m_serverUrl = String.Empty;
  69. private string m_userServerUrl = String.Empty;
  70. // private object m_gestureSyncRoot = new object();
  71. private bool m_Enabled = false;
  72. private const double CACHE_EXPIRATION_SECONDS = 20.0;
  73. private static ExpiringCache<UUID, InventoryItemBase> m_ItemCache;
  74. #region ISharedRegionModule
  75. public Type ReplaceableInterface { get { return null; } }
  76. public void RegionLoaded(Scene scene) { }
  77. public void PostInitialise() { }
  78. public void Close() { }
  79. public SimianInventoryServiceConnector() { }
  80. public string Name { get { return "SimianInventoryServiceConnector"; } }
  81. public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IInventoryService>(this); } }
  82. public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IInventoryService>(this); } }
  83. #endregion ISharedRegionModule
  84. public SimianInventoryServiceConnector(IConfigSource source)
  85. {
  86. CommonInit(source);
  87. }
  88. public SimianInventoryServiceConnector(string url)
  89. {
  90. if (!url.EndsWith("/") && !url.EndsWith("="))
  91. url = url + '/';
  92. m_serverUrl = url;
  93. if (m_ItemCache == null)
  94. m_ItemCache = new ExpiringCache<UUID, InventoryItemBase>();
  95. }
  96. public void Initialise(IConfigSource source)
  97. {
  98. IConfig moduleConfig = source.Configs["Modules"];
  99. if (moduleConfig != null)
  100. {
  101. string name = moduleConfig.GetString("InventoryServices", "");
  102. if (name == Name)
  103. CommonInit(source);
  104. }
  105. }
  106. private void CommonInit(IConfigSource source)
  107. {
  108. IConfig gridConfig = source.Configs["InventoryService"];
  109. if (gridConfig != null)
  110. {
  111. string serviceUrl = gridConfig.GetString("InventoryServerURI");
  112. if (!String.IsNullOrEmpty(serviceUrl))
  113. {
  114. if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
  115. serviceUrl = serviceUrl + '/';
  116. m_serverUrl = serviceUrl;
  117. gridConfig = source.Configs["UserAccountService"];
  118. if (gridConfig != null)
  119. {
  120. serviceUrl = gridConfig.GetString("UserAccountServerURI");
  121. if (!String.IsNullOrEmpty(serviceUrl))
  122. {
  123. m_userServerUrl = serviceUrl;
  124. m_Enabled = true;
  125. if (m_ItemCache == null)
  126. m_ItemCache = new ExpiringCache<UUID, InventoryItemBase>();
  127. }
  128. }
  129. }
  130. }
  131. if (String.IsNullOrEmpty(m_serverUrl))
  132. m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No InventoryServerURI specified, disabling connector");
  133. else if (String.IsNullOrEmpty(m_userServerUrl))
  134. m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No UserAccountServerURI specified, disabling connector");
  135. }
  136. /// <summary>
  137. /// Create the entire inventory for a given user
  138. /// </summary>
  139. /// <param name="user"></param>
  140. /// <returns></returns>
  141. public bool CreateUserInventory(UUID userID)
  142. {
  143. NameValueCollection requestArgs = new NameValueCollection
  144. {
  145. { "RequestMethod", "AddInventory" },
  146. { "OwnerID", userID.ToString() }
  147. };
  148. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  149. bool success = response["Success"].AsBoolean();
  150. if (!success)
  151. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Inventory creation for " + userID + " failed: " + response["Message"].AsString());
  152. return success;
  153. }
  154. /// <summary>
  155. /// Gets the skeleton of the inventory -- folders only
  156. /// </summary>
  157. /// <param name="userID"></param>
  158. /// <returns></returns>
  159. public List<InventoryFolderBase> GetInventorySkeleton(UUID userID)
  160. {
  161. NameValueCollection requestArgs = new NameValueCollection
  162. {
  163. { "RequestMethod", "GetInventoryNode" },
  164. { "ItemID", userID.ToString() },
  165. { "OwnerID", userID.ToString() },
  166. { "IncludeFolders", "1" },
  167. { "IncludeItems", "0" },
  168. { "ChildrenOnly", "0" }
  169. };
  170. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  171. if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
  172. {
  173. OSDArray items = (OSDArray)response["Items"];
  174. return GetFoldersFromResponse(items, userID, true);
  175. }
  176. else
  177. {
  178. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to retrieve inventory skeleton for " + userID + ": " +
  179. response["Message"].AsString());
  180. return new List<InventoryFolderBase>(0);
  181. }
  182. }
  183. /// <summary>
  184. /// Retrieve the root inventory folder for the given user.
  185. /// </summary>
  186. /// <param name="userID"></param>
  187. /// <returns>null if no root folder was found</returns>
  188. public InventoryFolderBase GetRootFolder(UUID userID)
  189. {
  190. NameValueCollection requestArgs = new NameValueCollection
  191. {
  192. { "RequestMethod", "GetInventoryNode" },
  193. { "ItemID", userID.ToString() },
  194. { "OwnerID", userID.ToString() },
  195. { "IncludeFolders", "1" },
  196. { "IncludeItems", "0" },
  197. { "ChildrenOnly", "1" }
  198. };
  199. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  200. if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
  201. {
  202. OSDArray items = (OSDArray)response["Items"];
  203. List<InventoryFolderBase> folders = GetFoldersFromResponse(items, userID, true);
  204. if (folders.Count > 0)
  205. return folders[0];
  206. }
  207. return null;
  208. }
  209. /// <summary>
  210. /// Gets the user folder for the given folder-type
  211. /// </summary>
  212. /// <param name="userID"></param>
  213. /// <param name="type"></param>
  214. /// <returns></returns>
  215. public InventoryFolderBase GetFolderForType(UUID userID, FolderType type)
  216. {
  217. string contentType = SLUtil.SLAssetTypeToContentType((int)type);
  218. NameValueCollection requestArgs = new NameValueCollection
  219. {
  220. { "RequestMethod", "GetFolderForType" },
  221. { "ContentType", contentType },
  222. { "OwnerID", userID.ToString() }
  223. };
  224. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  225. if (response["Success"].AsBoolean() && response["Folder"] is OSDMap)
  226. {
  227. OSDMap folder = (OSDMap)response["Folder"];
  228. return new InventoryFolderBase(
  229. folder["ID"].AsUUID(),
  230. folder["Name"].AsString(),
  231. folder["OwnerID"].AsUUID(),
  232. (short)SLUtil.ContentTypeToSLAssetType(folder["ContentType"].AsString()),
  233. folder["ParentID"].AsUUID(),
  234. (ushort)folder["Version"].AsInteger()
  235. );
  236. }
  237. else
  238. {
  239. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Default folder not found for content type " + contentType + ": " + response["Message"].AsString());
  240. return GetRootFolder(userID);
  241. }
  242. }
  243. /// <summary>
  244. /// Get an item, given by its UUID
  245. /// </summary>
  246. /// <param name="item"></param>
  247. /// <returns></returns>
  248. public InventoryItemBase GetItem(InventoryItemBase item)
  249. {
  250. InventoryItemBase retrieved = null;
  251. if (m_ItemCache.TryGetValue(item.ID, out retrieved))
  252. return retrieved;
  253. NameValueCollection requestArgs = new NameValueCollection
  254. {
  255. { "RequestMethod", "GetInventoryNode" },
  256. { "ItemID", item.ID.ToString() },
  257. { "OwnerID", item.Owner.ToString() },
  258. { "IncludeFolders", "1" },
  259. { "IncludeItems", "1" },
  260. { "ChildrenOnly", "1" }
  261. };
  262. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  263. if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
  264. {
  265. List<InventoryItemBase> items = GetItemsFromResponse((OSDArray)response["Items"]);
  266. if (items.Count > 0)
  267. {
  268. // The requested item should be the first in this list, but loop through
  269. // and sanity check just in case
  270. for (int i = 0; i < items.Count; i++)
  271. {
  272. if (items[i].ID == item.ID)
  273. {
  274. retrieved = items[i];
  275. m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS);
  276. return retrieved;
  277. }
  278. }
  279. }
  280. }
  281. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Item " + item.ID + " owned by " + item.Owner + " not found");
  282. return null;
  283. }
  284. public InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
  285. {
  286. InventoryItemBase[] result = new InventoryItemBase[itemIDs.Length];
  287. int i = 0;
  288. InventoryItemBase item = new InventoryItemBase();
  289. item.Owner = principalID;
  290. foreach (UUID id in itemIDs)
  291. {
  292. item.ID = id;
  293. result[i++] = GetItem(item);
  294. }
  295. return result;
  296. }
  297. /// <summary>
  298. /// Get a folder, given by its UUID
  299. /// </summary>
  300. /// <param name="folder"></param>
  301. /// <returns></returns>
  302. public InventoryFolderBase GetFolder(InventoryFolderBase folder)
  303. {
  304. NameValueCollection requestArgs = new NameValueCollection
  305. {
  306. { "RequestMethod", "GetInventoryNode" },
  307. { "ItemID", folder.ID.ToString() },
  308. { "OwnerID", folder.Owner.ToString() },
  309. { "IncludeFolders", "1" },
  310. { "IncludeItems", "0" },
  311. { "ChildrenOnly", "1" }
  312. };
  313. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  314. if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
  315. {
  316. OSDArray items = (OSDArray)response["Items"];
  317. List<InventoryFolderBase> folders = GetFoldersFromResponse(items, folder.ID, true);
  318. if (folders.Count > 0)
  319. return folders[0];
  320. }
  321. return null;
  322. }
  323. /// <summary>
  324. /// Gets everything (folders and items) inside a folder
  325. /// </summary>
  326. /// <param name="userID"></param>
  327. /// <param name="folderID"></param>
  328. /// <returns></returns>
  329. public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
  330. {
  331. InventoryCollection inventory = new InventoryCollection();
  332. inventory.OwnerID = userID;
  333. NameValueCollection requestArgs = new NameValueCollection
  334. {
  335. { "RequestMethod", "GetInventoryNode" },
  336. { "ItemID", folderID.ToString() },
  337. { "OwnerID", userID.ToString() },
  338. { "IncludeFolders", "1" },
  339. { "IncludeItems", "1" },
  340. { "ChildrenOnly", "1" }
  341. };
  342. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  343. if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
  344. {
  345. OSDArray items = (OSDArray)response["Items"];
  346. inventory.Folders = GetFoldersFromResponse(items, folderID, false);
  347. inventory.Items = GetItemsFromResponse(items);
  348. }
  349. else
  350. {
  351. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID + " content for " + userID + ": " +
  352. response["Message"].AsString());
  353. inventory.Folders = new List<InventoryFolderBase>(0);
  354. inventory.Items = new List<InventoryItemBase>(0);
  355. }
  356. return inventory;
  357. }
  358. public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
  359. {
  360. InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
  361. int i = 0;
  362. foreach (UUID fid in folderIDs)
  363. {
  364. invColl[i++] = GetFolderContent(principalID, fid);
  365. }
  366. return invColl;
  367. }
  368. /// <summary>
  369. /// Gets the items inside a folder
  370. /// </summary>
  371. /// <param name="userID"></param>
  372. /// <param name="folderID"></param>
  373. /// <returns></returns>
  374. public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
  375. {
  376. InventoryCollection inventory = new InventoryCollection();
  377. inventory.OwnerID = userID;
  378. NameValueCollection requestArgs = new NameValueCollection
  379. {
  380. { "RequestMethod", "GetInventoryNode" },
  381. { "ItemID", folderID.ToString() },
  382. { "OwnerID", userID.ToString() },
  383. { "IncludeFolders", "0" },
  384. { "IncludeItems", "1" },
  385. { "ChildrenOnly", "1" }
  386. };
  387. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  388. if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
  389. {
  390. OSDArray items = (OSDArray)response["Items"];
  391. return GetItemsFromResponse(items);
  392. }
  393. else
  394. {
  395. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID + " for " + userID + ": " +
  396. response["Message"].AsString());
  397. return new List<InventoryItemBase>(0);
  398. }
  399. }
  400. /// <summary>
  401. /// Add a new folder to the user's inventory
  402. /// </summary>
  403. /// <param name="folder"></param>
  404. /// <returns>true if the folder was successfully added</returns>
  405. public bool AddFolder(InventoryFolderBase folder)
  406. {
  407. NameValueCollection requestArgs = new NameValueCollection
  408. {
  409. { "RequestMethod", "AddInventoryFolder" },
  410. { "FolderID", folder.ID.ToString() },
  411. { "ParentID", folder.ParentID.ToString() },
  412. { "OwnerID", folder.Owner.ToString() },
  413. { "Name", folder.Name },
  414. { "ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) }
  415. };
  416. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  417. bool success = response["Success"].AsBoolean();
  418. if (!success)
  419. {
  420. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error creating folder " + folder.Name + " for " + folder.Owner + ": " +
  421. response["Message"].AsString());
  422. }
  423. return success;
  424. }
  425. /// <summary>
  426. /// Update a folder in the user's inventory
  427. /// </summary>
  428. /// <param name="folder"></param>
  429. /// <returns>true if the folder was successfully updated</returns>
  430. public bool UpdateFolder(InventoryFolderBase folder)
  431. {
  432. return AddFolder(folder);
  433. }
  434. /// <summary>
  435. /// Move an inventory folder to a new location
  436. /// </summary>
  437. /// <param name="folder">A folder containing the details of the new location</param>
  438. /// <returns>true if the folder was successfully moved</returns>
  439. public bool MoveFolder(InventoryFolderBase folder)
  440. {
  441. return AddFolder(folder);
  442. }
  443. /// <summary>
  444. /// Delete an item from the user's inventory
  445. /// </summary>
  446. /// <param name="item"></param>
  447. /// <returns>true if the item was successfully deleted</returns>
  448. //bool DeleteItem(InventoryItemBase item);
  449. public bool DeleteFolders(UUID userID, List<UUID> folderIDs)
  450. {
  451. return DeleteItems(userID, folderIDs);
  452. }
  453. /// <summary>
  454. /// Delete an item from the user's inventory
  455. /// </summary>
  456. /// <param name="item"></param>
  457. /// <returns>true if the item was successfully deleted</returns>
  458. public bool DeleteItems(UUID userID, List<UUID> itemIDs)
  459. {
  460. // TODO: RemoveInventoryNode should be replaced with RemoveInventoryNodes
  461. bool allSuccess = true;
  462. for (int i = 0; i < itemIDs.Count; i++)
  463. {
  464. UUID itemID = itemIDs[i];
  465. NameValueCollection requestArgs = new NameValueCollection
  466. {
  467. { "RequestMethod", "RemoveInventoryNode" },
  468. { "OwnerID", userID.ToString() },
  469. { "ItemID", itemID.ToString() }
  470. };
  471. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  472. bool success = response["Success"].AsBoolean();
  473. if (!success)
  474. {
  475. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error removing item " + itemID + " for " + userID + ": " +
  476. response["Message"].AsString());
  477. allSuccess = false;
  478. }
  479. }
  480. return allSuccess;
  481. }
  482. /// <summary>
  483. /// Purge an inventory folder of all its items and subfolders.
  484. /// </summary>
  485. /// <param name="folder"></param>
  486. /// <returns>true if the folder was successfully purged</returns>
  487. public bool PurgeFolder(InventoryFolderBase folder)
  488. {
  489. NameValueCollection requestArgs = new NameValueCollection
  490. {
  491. { "RequestMethod", "PurgeInventoryFolder" },
  492. { "OwnerID", folder.Owner.ToString() },
  493. { "FolderID", folder.ID.ToString() }
  494. };
  495. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  496. bool success = response["Success"].AsBoolean();
  497. if (!success)
  498. {
  499. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error purging folder " + folder.ID + " for " + folder.Owner + ": " +
  500. response["Message"].AsString());
  501. }
  502. return success;
  503. }
  504. /// <summary>
  505. /// Add a new item to the user's inventory
  506. /// </summary>
  507. /// <param name="item"></param>
  508. /// <returns>true if the item was successfully added</returns>
  509. public bool AddItem(InventoryItemBase item)
  510. {
  511. // A folder of UUID.Zero means we need to find the most appropriate home for this item
  512. if (item.Folder == UUID.Zero)
  513. {
  514. InventoryFolderBase folder = null;
  515. if (Enum.IsDefined(typeof(FolderType), (sbyte)item.AssetType))
  516. folder = GetFolderForType(item.Owner, (FolderType)item.AssetType);
  517. if (folder != null && folder.ID != UUID.Zero)
  518. item.Folder = folder.ID;
  519. else
  520. item.Folder = item.Owner; // Root folder
  521. }
  522. if ((AssetType)item.AssetType == AssetType.Gesture)
  523. UpdateGesture(item.Owner, item.ID, item.Flags == 1);
  524. if (item.BasePermissions == 0)
  525. m_log.WarnFormat("[SIMIAN INVENTORY CONNECTOR]: Adding inventory item {0} ({1}) with no base permissions", item.Name, item.ID);
  526. OSDMap permissions = new OSDMap
  527. {
  528. { "BaseMask", OSD.FromInteger(item.BasePermissions) },
  529. { "EveryoneMask", OSD.FromInteger(item.EveryOnePermissions) },
  530. { "GroupMask", OSD.FromInteger(item.GroupPermissions) },
  531. { "NextOwnerMask", OSD.FromInteger(item.NextPermissions) },
  532. { "OwnerMask", OSD.FromInteger(item.CurrentPermissions) }
  533. };
  534. OSDMap extraData = new OSDMap()
  535. {
  536. { "Flags", OSD.FromInteger(item.Flags) },
  537. { "GroupID", OSD.FromUUID(item.GroupID) },
  538. { "GroupOwned", OSD.FromBoolean(item.GroupOwned) },
  539. { "SalePrice", OSD.FromInteger(item.SalePrice) },
  540. { "SaleType", OSD.FromInteger(item.SaleType) },
  541. { "Permissions", permissions }
  542. };
  543. // Add different asset type only if it differs from inventory type
  544. // (needed for links)
  545. string invContentType = SLUtil.SLInvTypeToContentType(item.InvType);
  546. string assetContentType = SLUtil.SLAssetTypeToContentType(item.AssetType);
  547. if (invContentType != assetContentType)
  548. extraData["LinkedItemType"] = OSD.FromString(assetContentType);
  549. NameValueCollection requestArgs = new NameValueCollection
  550. {
  551. { "RequestMethod", "AddInventoryItem" },
  552. { "ItemID", item.ID.ToString() },
  553. { "AssetID", item.AssetID.ToString() },
  554. { "ParentID", item.Folder.ToString() },
  555. { "OwnerID", item.Owner.ToString() },
  556. { "Name", item.Name },
  557. { "Description", item.Description },
  558. { "CreatorID", item.CreatorId },
  559. { "CreatorData", item.CreatorData },
  560. { "ContentType", invContentType },
  561. { "ExtraData", OSDParser.SerializeJsonString(extraData) }
  562. };
  563. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  564. bool success = response["Success"].AsBoolean();
  565. if (!success)
  566. {
  567. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error creating item " + item.Name + " for " + item.Owner + ": " +
  568. response["Message"].AsString());
  569. }
  570. return success;
  571. }
  572. /// <summary>
  573. /// Update an item in the user's inventory
  574. /// </summary>
  575. /// <param name="item"></param>
  576. /// <returns>true if the item was successfully updated</returns>
  577. public bool UpdateItem(InventoryItemBase item)
  578. {
  579. if (item.AssetID != UUID.Zero)
  580. {
  581. return AddItem(item);
  582. }
  583. else
  584. {
  585. // This is actually a folder update
  586. InventoryFolderBase folder = new InventoryFolderBase(item.ID, item.Name, item.Owner, (short)item.AssetType, item.Folder, 0);
  587. return UpdateFolder(folder);
  588. }
  589. }
  590. public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
  591. {
  592. bool success = true;
  593. while (items.Count > 0)
  594. {
  595. List<InventoryItemBase> currentItems = new List<InventoryItemBase>();
  596. UUID destFolderID = items[0].Folder;
  597. // Find all of the items being moved to the current destination folder
  598. for (int i = 0; i < items.Count; i++)
  599. {
  600. InventoryItemBase item = items[i];
  601. if (item.Folder == destFolderID)
  602. currentItems.Add(item);
  603. }
  604. // Do the inventory move for the current items
  605. success &= MoveItems(ownerID, items, destFolderID);
  606. // Remove the processed items from the list
  607. for (int i = 0; i < currentItems.Count; i++)
  608. items.Remove(currentItems[i]);
  609. }
  610. return success;
  611. }
  612. /// <summary>
  613. /// Does the given user have an inventory structure?
  614. /// </summary>
  615. /// <param name="userID"></param>
  616. /// <returns></returns>
  617. public bool HasInventoryForUser(UUID userID)
  618. {
  619. return GetRootFolder(userID) != null;
  620. }
  621. /// <summary>
  622. /// Get the active gestures of the agent.
  623. /// </summary>
  624. /// <param name="userID"></param>
  625. /// <returns></returns>
  626. public List<InventoryItemBase> GetActiveGestures(UUID userID)
  627. {
  628. OSDArray items = FetchGestures(userID);
  629. string[] itemIDs = new string[items.Count];
  630. for (int i = 0; i < items.Count; i++)
  631. itemIDs[i] = items[i].AsUUID().ToString();
  632. // NameValueCollection requestArgs = new NameValueCollection
  633. // {
  634. // { "RequestMethod", "GetInventoryNodes" },
  635. // { "OwnerID", userID.ToString() },
  636. // { "Items", String.Join(",", itemIDs) }
  637. // };
  638. // FIXME: Implement this in SimianGrid
  639. return new List<InventoryItemBase>(0);
  640. }
  641. /// <summary>
  642. /// Get the union of permissions of all inventory items
  643. /// that hold the given assetID.
  644. /// </summary>
  645. /// <param name="userID"></param>
  646. /// <param name="assetID"></param>
  647. /// <returns>The permissions or 0 if no such asset is found in
  648. /// the user's inventory</returns>
  649. public int GetAssetPermissions(UUID userID, UUID assetID)
  650. {
  651. // NameValueCollection requestArgs = new NameValueCollection
  652. // {
  653. // { "RequestMethod", "GetInventoryNodes" },
  654. // { "OwnerID", userID.ToString() },
  655. // { "AssetID", assetID.ToString() }
  656. // };
  657. // FIXME: Implement this in SimianGrid
  658. return (int)PermissionMask.All;
  659. }
  660. private List<InventoryFolderBase> GetFoldersFromResponse(OSDArray items, UUID baseFolder, bool includeBaseFolder)
  661. {
  662. List<InventoryFolderBase> invFolders = new List<InventoryFolderBase>(items.Count);
  663. for (int i = 0; i < items.Count; i++)
  664. {
  665. OSDMap item = items[i] as OSDMap;
  666. if (item != null && item["Type"].AsString() == "Folder")
  667. {
  668. UUID folderID = item["ID"].AsUUID();
  669. if (folderID == baseFolder && !includeBaseFolder)
  670. continue;
  671. invFolders.Add(new InventoryFolderBase(
  672. folderID,
  673. item["Name"].AsString(),
  674. item["OwnerID"].AsUUID(),
  675. (short)SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString()),
  676. item["ParentID"].AsUUID(),
  677. (ushort)item["Version"].AsInteger()
  678. ));
  679. }
  680. }
  681. // m_log.Debug("[SIMIAN INVENTORY CONNECTOR]: Parsed " + invFolders.Count + " folders from SimianGrid response");
  682. return invFolders;
  683. }
  684. private List<InventoryItemBase> GetItemsFromResponse(OSDArray items)
  685. {
  686. List<InventoryItemBase> invItems = new List<InventoryItemBase>(items.Count);
  687. for (int i = 0; i < items.Count; i++)
  688. {
  689. OSDMap item = items[i] as OSDMap;
  690. if (item != null && item["Type"].AsString() == "Item")
  691. {
  692. InventoryItemBase invItem = new InventoryItemBase();
  693. invItem.AssetID = item["AssetID"].AsUUID();
  694. invItem.AssetType = SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString());
  695. invItem.CreationDate = item["CreationDate"].AsInteger();
  696. invItem.CreatorId = item["CreatorID"].AsString();
  697. invItem.CreatorData = item["CreatorData"].AsString();
  698. invItem.Description = item["Description"].AsString();
  699. invItem.Folder = item["ParentID"].AsUUID();
  700. invItem.ID = item["ID"].AsUUID();
  701. invItem.InvType = SLUtil.ContentTypeToSLInvType(item["ContentType"].AsString());
  702. invItem.Name = item["Name"].AsString();
  703. invItem.Owner = item["OwnerID"].AsUUID();
  704. OSDMap extraData = item["ExtraData"] as OSDMap;
  705. if (extraData != null && extraData.Count > 0)
  706. {
  707. invItem.Flags = extraData["Flags"].AsUInteger();
  708. invItem.GroupID = extraData["GroupID"].AsUUID();
  709. invItem.GroupOwned = extraData["GroupOwned"].AsBoolean();
  710. invItem.SalePrice = extraData["SalePrice"].AsInteger();
  711. invItem.SaleType = (byte)extraData["SaleType"].AsInteger();
  712. OSDMap perms = extraData["Permissions"] as OSDMap;
  713. if (perms != null)
  714. {
  715. invItem.BasePermissions = perms["BaseMask"].AsUInteger();
  716. invItem.CurrentPermissions = perms["OwnerMask"].AsUInteger();
  717. invItem.EveryOnePermissions = perms["EveryoneMask"].AsUInteger();
  718. invItem.GroupPermissions = perms["GroupMask"].AsUInteger();
  719. invItem.NextPermissions = perms["NextOwnerMask"].AsUInteger();
  720. }
  721. if (extraData.ContainsKey("LinkedItemType"))
  722. invItem.AssetType = SLUtil.ContentTypeToSLAssetType(extraData["LinkedItemType"].AsString());
  723. }
  724. if (invItem.BasePermissions == 0)
  725. {
  726. m_log.InfoFormat("[SIMIAN INVENTORY CONNECTOR]: Forcing item permissions to full for item {0} ({1})",
  727. invItem.Name, invItem.ID);
  728. invItem.BasePermissions = (uint)PermissionMask.All;
  729. invItem.CurrentPermissions = (uint)PermissionMask.All;
  730. invItem.EveryOnePermissions = (uint)PermissionMask.All;
  731. invItem.GroupPermissions = (uint)PermissionMask.All;
  732. invItem.NextPermissions = (uint)PermissionMask.All;
  733. }
  734. invItems.Add(invItem);
  735. }
  736. }
  737. // m_log.Debug("[SIMIAN INVENTORY CONNECTOR]: Parsed " + invItems.Count + " items from SimianGrid response");
  738. return invItems;
  739. }
  740. private bool MoveItems(UUID ownerID, List<InventoryItemBase> items, UUID destFolderID)
  741. {
  742. string[] itemIDs = new string[items.Count];
  743. for (int i = 0; i < items.Count; i++)
  744. itemIDs[i] = items[i].ID.ToString();
  745. NameValueCollection requestArgs = new NameValueCollection
  746. {
  747. { "RequestMethod", "MoveInventoryNodes" },
  748. { "OwnerID", ownerID.ToString() },
  749. { "FolderID", destFolderID.ToString() },
  750. { "Items", String.Join(",", itemIDs) }
  751. };
  752. OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
  753. bool success = response["Success"].AsBoolean();
  754. if (!success)
  755. {
  756. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to move " + items.Count + " items to " +
  757. destFolderID + ": " + response["Message"].AsString());
  758. }
  759. return success;
  760. }
  761. private void UpdateGesture(UUID userID, UUID itemID, bool enabled)
  762. {
  763. OSDArray gestures = FetchGestures(userID);
  764. OSDArray newGestures = new OSDArray();
  765. for (int i = 0; i < gestures.Count; i++)
  766. {
  767. UUID gesture = gestures[i].AsUUID();
  768. if (gesture != itemID)
  769. newGestures.Add(OSD.FromUUID(gesture));
  770. }
  771. if (enabled)
  772. newGestures.Add(OSD.FromUUID(itemID));
  773. SaveGestures(userID, newGestures);
  774. }
  775. private OSDArray FetchGestures(UUID userID)
  776. {
  777. NameValueCollection requestArgs = new NameValueCollection
  778. {
  779. { "RequestMethod", "GetUser" },
  780. { "UserID", userID.ToString() }
  781. };
  782. OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
  783. if (response["Success"].AsBoolean())
  784. {
  785. OSDMap user = response["User"] as OSDMap;
  786. if (user != null && response.ContainsKey("Gestures"))
  787. {
  788. OSD gestures = OSDParser.DeserializeJson(response["Gestures"].AsString());
  789. if (gestures != null && gestures is OSDArray)
  790. return (OSDArray)gestures;
  791. else
  792. m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Unrecognized active gestures data for " + userID);
  793. }
  794. }
  795. else
  796. {
  797. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to fetch active gestures for " + userID + ": " +
  798. response["Message"].AsString());
  799. }
  800. return new OSDArray();
  801. }
  802. private void SaveGestures(UUID userID, OSDArray gestures)
  803. {
  804. NameValueCollection requestArgs = new NameValueCollection
  805. {
  806. { "RequestMethod", "AddUserData" },
  807. { "UserID", userID.ToString() },
  808. { "Gestures", OSDParser.SerializeJsonString(gestures) }
  809. };
  810. OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
  811. if (!response["Success"].AsBoolean())
  812. {
  813. m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to save active gestures for " + userID + ": " +
  814. response["Message"].AsString());
  815. }
  816. }
  817. }
  818. }