SimianInventoryServiceConnector.cs 36 KB

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