SimianInventoryServiceConnector.cs 36 KB

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