SimianInventoryServiceConnector.cs 36 KB

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