XInventoryServicesConnector.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  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 log4net;
  28. using System;
  29. using System.Collections.Generic;
  30. using System.IO;
  31. using System.Reflection;
  32. using Nini.Config;
  33. using OpenSim.Framework;
  34. using OpenSim.Framework.Console;
  35. using OpenSim.Framework.Communications;
  36. using OpenSim.Framework.Monitoring;
  37. using OpenSim.Services.Interfaces;
  38. using OpenSim.Server.Base;
  39. using OpenMetaverse;
  40. namespace OpenSim.Services.Connectors
  41. {
  42. public class XInventoryServicesConnector : BaseServiceConnector, IInventoryService
  43. {
  44. private static readonly ILog m_log =
  45. LogManager.GetLogger(
  46. MethodBase.GetCurrentMethod().DeclaringType);
  47. /// <summary>
  48. /// Number of requests made to the remote inventory service.
  49. /// </summary>
  50. public int RequestsMade { get; private set; }
  51. private string m_ServerURI = String.Empty;
  52. /// <summary>
  53. /// Timeout for remote requests.
  54. /// </summary>
  55. /// <remarks>
  56. /// In this case, -1 is default timeout (100 seconds), not infinite.
  57. /// </remarks>
  58. private int m_requestTimeoutSecs = -1;
  59. public XInventoryServicesConnector()
  60. {
  61. }
  62. public XInventoryServicesConnector(string serverURI)
  63. {
  64. m_ServerURI = serverURI.TrimEnd('/');
  65. }
  66. public XInventoryServicesConnector(IConfigSource source)
  67. : base(source, "InventoryService")
  68. {
  69. Initialise(source);
  70. }
  71. public virtual void Initialise(IConfigSource source)
  72. {
  73. IConfig config = source.Configs["InventoryService"];
  74. if (config == null)
  75. {
  76. m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini");
  77. throw new Exception("Inventory connector init error");
  78. }
  79. string serviceURI = config.GetString("InventoryServerURI",
  80. String.Empty);
  81. if (serviceURI == String.Empty)
  82. {
  83. m_log.Error("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService");
  84. throw new Exception("Inventory connector init error");
  85. }
  86. m_ServerURI = serviceURI;
  87. m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs);
  88. StatsManager.RegisterStat(
  89. new Stat(
  90. "RequestsMade",
  91. "Requests made",
  92. "Number of requests made to the remove inventory service",
  93. "requests",
  94. "inventory",
  95. serviceURI,
  96. StatType.Pull,
  97. MeasuresOfInterest.AverageChangeOverTime,
  98. s => s.Value = RequestsMade,
  99. StatVerbosity.Debug));
  100. }
  101. private bool CheckReturn(Dictionary<string, object> ret)
  102. {
  103. if (ret == null)
  104. return false;
  105. if (ret.Count == 0)
  106. return false;
  107. if (ret.ContainsKey("RESULT"))
  108. {
  109. if (ret["RESULT"] is string)
  110. {
  111. bool result;
  112. if (bool.TryParse((string)ret["RESULT"], out result))
  113. return result;
  114. return false;
  115. }
  116. }
  117. return true;
  118. }
  119. public bool CreateUserInventory(UUID principalID)
  120. {
  121. Dictionary<string,object> ret = MakeRequest("CREATEUSERINVENTORY",
  122. new Dictionary<string,object> {
  123. { "PRINCIPAL", principalID.ToString() }
  124. });
  125. return CheckReturn(ret);
  126. }
  127. public List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
  128. {
  129. Dictionary<string,object> ret = MakeRequest("GETINVENTORYSKELETON",
  130. new Dictionary<string,object> {
  131. { "PRINCIPAL", principalID.ToString() }
  132. });
  133. if (!CheckReturn(ret))
  134. return null;
  135. Dictionary<string, object> folders = (Dictionary<string, object>)ret["FOLDERS"];
  136. List<InventoryFolderBase> fldrs = new List<InventoryFolderBase>();
  137. try
  138. {
  139. foreach (Object o in folders.Values)
  140. fldrs.Add(BuildFolder((Dictionary<string, object>)o));
  141. }
  142. catch (Exception e)
  143. {
  144. m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception unwrapping folder list: ", e);
  145. }
  146. return fldrs;
  147. }
  148. public InventoryFolderBase GetRootFolder(UUID principalID)
  149. {
  150. Dictionary<string,object> ret = MakeRequest("GETROOTFOLDER",
  151. new Dictionary<string,object> {
  152. { "PRINCIPAL", principalID.ToString() }
  153. });
  154. if (!CheckReturn(ret))
  155. return null;
  156. return BuildFolder((Dictionary<string, object>)ret["folder"]);
  157. }
  158. public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
  159. {
  160. Dictionary<string,object> ret = MakeRequest("GETFOLDERFORTYPE",
  161. new Dictionary<string,object> {
  162. { "PRINCIPAL", principalID.ToString() },
  163. { "TYPE", ((int)type).ToString() }
  164. });
  165. if (!CheckReturn(ret))
  166. return null;
  167. return BuildFolder((Dictionary<string, object>)ret["folder"]);
  168. }
  169. public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
  170. {
  171. InventoryCollection inventory = new InventoryCollection();
  172. inventory.Folders = new List<InventoryFolderBase>();
  173. inventory.Items = new List<InventoryItemBase>();
  174. inventory.UserID = principalID;
  175. try
  176. {
  177. Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
  178. new Dictionary<string,object> {
  179. { "PRINCIPAL", principalID.ToString() },
  180. { "FOLDER", folderID.ToString() }
  181. });
  182. if (!CheckReturn(ret))
  183. return null;
  184. Dictionary<string,object> folders =
  185. (Dictionary<string,object>)ret["FOLDERS"];
  186. Dictionary<string,object> items =
  187. (Dictionary<string,object>)ret["ITEMS"];
  188. foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
  189. inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
  190. foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
  191. inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
  192. }
  193. catch (Exception e)
  194. {
  195. m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolderContent: {0}", e.Message);
  196. }
  197. return inventory;
  198. }
  199. public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
  200. {
  201. Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS",
  202. new Dictionary<string,object> {
  203. { "PRINCIPAL", principalID.ToString() },
  204. { "FOLDER", folderID.ToString() }
  205. });
  206. if (!CheckReturn(ret))
  207. return null;
  208. Dictionary<string, object> items = (Dictionary<string, object>)ret["ITEMS"];
  209. List<InventoryItemBase> fitems = new List<InventoryItemBase>();
  210. foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
  211. fitems.Add(BuildItem((Dictionary<string, object>)o));
  212. return fitems;
  213. }
  214. public bool AddFolder(InventoryFolderBase folder)
  215. {
  216. Dictionary<string,object> ret = MakeRequest("ADDFOLDER",
  217. new Dictionary<string,object> {
  218. { "ParentID", folder.ParentID.ToString() },
  219. { "Type", folder.Type.ToString() },
  220. { "Version", folder.Version.ToString() },
  221. { "Name", folder.Name.ToString() },
  222. { "Owner", folder.Owner.ToString() },
  223. { "ID", folder.ID.ToString() }
  224. });
  225. return CheckReturn(ret);
  226. }
  227. public bool UpdateFolder(InventoryFolderBase folder)
  228. {
  229. Dictionary<string,object> ret = MakeRequest("UPDATEFOLDER",
  230. new Dictionary<string,object> {
  231. { "ParentID", folder.ParentID.ToString() },
  232. { "Type", folder.Type.ToString() },
  233. { "Version", folder.Version.ToString() },
  234. { "Name", folder.Name.ToString() },
  235. { "Owner", folder.Owner.ToString() },
  236. { "ID", folder.ID.ToString() }
  237. });
  238. return CheckReturn(ret);
  239. }
  240. public bool MoveFolder(InventoryFolderBase folder)
  241. {
  242. Dictionary<string,object> ret = MakeRequest("MOVEFOLDER",
  243. new Dictionary<string,object> {
  244. { "ParentID", folder.ParentID.ToString() },
  245. { "ID", folder.ID.ToString() },
  246. { "PRINCIPAL", folder.Owner.ToString() }
  247. });
  248. return CheckReturn(ret);
  249. }
  250. public bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
  251. {
  252. List<string> slist = new List<string>();
  253. foreach (UUID f in folderIDs)
  254. slist.Add(f.ToString());
  255. Dictionary<string,object> ret = MakeRequest("DELETEFOLDERS",
  256. new Dictionary<string,object> {
  257. { "PRINCIPAL", principalID.ToString() },
  258. { "FOLDERS", slist }
  259. });
  260. return CheckReturn(ret);
  261. }
  262. public bool PurgeFolder(InventoryFolderBase folder)
  263. {
  264. Dictionary<string,object> ret = MakeRequest("PURGEFOLDER",
  265. new Dictionary<string,object> {
  266. { "ID", folder.ID.ToString() }
  267. });
  268. return CheckReturn(ret);
  269. }
  270. public bool AddItem(InventoryItemBase item)
  271. {
  272. if (item.CreatorData == null)
  273. item.CreatorData = String.Empty;
  274. Dictionary<string,object> ret = MakeRequest("ADDITEM",
  275. new Dictionary<string,object> {
  276. { "AssetID", item.AssetID.ToString() },
  277. { "AssetType", item.AssetType.ToString() },
  278. { "Name", item.Name.ToString() },
  279. { "Owner", item.Owner.ToString() },
  280. { "ID", item.ID.ToString() },
  281. { "InvType", item.InvType.ToString() },
  282. { "Folder", item.Folder.ToString() },
  283. { "CreatorId", item.CreatorId.ToString() },
  284. { "CreatorData", item.CreatorData.ToString() },
  285. { "Description", item.Description.ToString() },
  286. { "NextPermissions", item.NextPermissions.ToString() },
  287. { "CurrentPermissions", item.CurrentPermissions.ToString() },
  288. { "BasePermissions", item.BasePermissions.ToString() },
  289. { "EveryOnePermissions", item.EveryOnePermissions.ToString() },
  290. { "GroupPermissions", item.GroupPermissions.ToString() },
  291. { "GroupID", item.GroupID.ToString() },
  292. { "GroupOwned", item.GroupOwned.ToString() },
  293. { "SalePrice", item.SalePrice.ToString() },
  294. { "SaleType", item.SaleType.ToString() },
  295. { "Flags", item.Flags.ToString() },
  296. { "CreationDate", item.CreationDate.ToString() }
  297. });
  298. return CheckReturn(ret);
  299. }
  300. public bool UpdateItem(InventoryItemBase item)
  301. {
  302. if (item.CreatorData == null)
  303. item.CreatorData = String.Empty;
  304. Dictionary<string,object> ret = MakeRequest("UPDATEITEM",
  305. new Dictionary<string,object> {
  306. { "AssetID", item.AssetID.ToString() },
  307. { "AssetType", item.AssetType.ToString() },
  308. { "Name", item.Name.ToString() },
  309. { "Owner", item.Owner.ToString() },
  310. { "ID", item.ID.ToString() },
  311. { "InvType", item.InvType.ToString() },
  312. { "Folder", item.Folder.ToString() },
  313. { "CreatorId", item.CreatorId.ToString() },
  314. { "CreatorData", item.CreatorData.ToString() },
  315. { "Description", item.Description.ToString() },
  316. { "NextPermissions", item.NextPermissions.ToString() },
  317. { "CurrentPermissions", item.CurrentPermissions.ToString() },
  318. { "BasePermissions", item.BasePermissions.ToString() },
  319. { "EveryOnePermissions", item.EveryOnePermissions.ToString() },
  320. { "GroupPermissions", item.GroupPermissions.ToString() },
  321. { "GroupID", item.GroupID.ToString() },
  322. { "GroupOwned", item.GroupOwned.ToString() },
  323. { "SalePrice", item.SalePrice.ToString() },
  324. { "SaleType", item.SaleType.ToString() },
  325. { "Flags", item.Flags.ToString() },
  326. { "CreationDate", item.CreationDate.ToString() }
  327. });
  328. return CheckReturn(ret);
  329. }
  330. public bool MoveItems(UUID principalID, List<InventoryItemBase> items)
  331. {
  332. List<string> idlist = new List<string>();
  333. List<string> destlist = new List<string>();
  334. foreach (InventoryItemBase item in items)
  335. {
  336. idlist.Add(item.ID.ToString());
  337. destlist.Add(item.Folder.ToString());
  338. }
  339. Dictionary<string,object> ret = MakeRequest("MOVEITEMS",
  340. new Dictionary<string,object> {
  341. { "PRINCIPAL", principalID.ToString() },
  342. { "IDLIST", idlist },
  343. { "DESTLIST", destlist }
  344. });
  345. return CheckReturn(ret);
  346. }
  347. public bool DeleteItems(UUID principalID, List<UUID> itemIDs)
  348. {
  349. List<string> slist = new List<string>();
  350. foreach (UUID f in itemIDs)
  351. slist.Add(f.ToString());
  352. Dictionary<string,object> ret = MakeRequest("DELETEITEMS",
  353. new Dictionary<string,object> {
  354. { "PRINCIPAL", principalID.ToString() },
  355. { "ITEMS", slist }
  356. });
  357. return CheckReturn(ret);
  358. }
  359. public InventoryItemBase GetItem(InventoryItemBase item)
  360. {
  361. try
  362. {
  363. Dictionary<string, object> ret = MakeRequest("GETITEM",
  364. new Dictionary<string, object> {
  365. { "ID", item.ID.ToString() }
  366. });
  367. if (!CheckReturn(ret))
  368. return null;
  369. return BuildItem((Dictionary<string, object>)ret["item"]);
  370. }
  371. catch (Exception e)
  372. {
  373. m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e);
  374. }
  375. return null;
  376. }
  377. public InventoryFolderBase GetFolder(InventoryFolderBase folder)
  378. {
  379. try
  380. {
  381. Dictionary<string, object> ret = MakeRequest("GETFOLDER",
  382. new Dictionary<string, object> {
  383. { "ID", folder.ID.ToString() }
  384. });
  385. if (!CheckReturn(ret))
  386. return null;
  387. return BuildFolder((Dictionary<string, object>)ret["folder"]);
  388. }
  389. catch (Exception e)
  390. {
  391. m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolder: ", e);
  392. }
  393. return null;
  394. }
  395. public List<InventoryItemBase> GetActiveGestures(UUID principalID)
  396. {
  397. Dictionary<string,object> ret = MakeRequest("GETACTIVEGESTURES",
  398. new Dictionary<string,object> {
  399. { "PRINCIPAL", principalID.ToString() }
  400. });
  401. if (!CheckReturn(ret))
  402. return null;
  403. List<InventoryItemBase> items = new List<InventoryItemBase>();
  404. foreach (Object o in ((Dictionary<string,object>)ret["ITEMS"]).Values)
  405. items.Add(BuildItem((Dictionary<string, object>)o));
  406. return items;
  407. }
  408. public int GetAssetPermissions(UUID principalID, UUID assetID)
  409. {
  410. Dictionary<string,object> ret = MakeRequest("GETASSETPERMISSIONS",
  411. new Dictionary<string,object> {
  412. { "PRINCIPAL", principalID.ToString() },
  413. { "ASSET", assetID.ToString() }
  414. });
  415. // We cannot use CheckReturn() here because valid values for RESULT are "false" (in the case of request failure) or an int
  416. if (ret == null)
  417. return 0;
  418. if (ret.ContainsKey("RESULT"))
  419. {
  420. if (ret["RESULT"] is string)
  421. {
  422. int intResult;
  423. if (int.TryParse ((string)ret["RESULT"], out intResult))
  424. return intResult;
  425. }
  426. }
  427. return 0;
  428. }
  429. public bool HasInventoryForUser(UUID principalID)
  430. {
  431. return false;
  432. }
  433. // Helpers
  434. //
  435. private Dictionary<string,object> MakeRequest(string method,
  436. Dictionary<string,object> sendData)
  437. {
  438. // Add "METHOD" as the first key in the dictionary. This ensures that it will be
  439. // visible even when using partial logging ("debug http all 5").
  440. Dictionary<string, object> temp = sendData;
  441. sendData = new Dictionary<string,object>{ { "METHOD", method } };
  442. foreach (KeyValuePair<string, object> kvp in temp)
  443. sendData.Add(kvp.Key, kvp.Value);
  444. RequestsMade++;
  445. string reply
  446. = SynchronousRestFormsRequester.MakeRequest(
  447. "POST", m_ServerURI + "/xinventory",
  448. ServerUtils.BuildQueryString(sendData), m_requestTimeoutSecs, m_Auth);
  449. Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
  450. reply);
  451. return replyData;
  452. }
  453. private InventoryFolderBase BuildFolder(Dictionary<string,object> data)
  454. {
  455. InventoryFolderBase folder = new InventoryFolderBase();
  456. try
  457. {
  458. folder.ParentID = new UUID(data["ParentID"].ToString());
  459. folder.Type = short.Parse(data["Type"].ToString());
  460. folder.Version = ushort.Parse(data["Version"].ToString());
  461. folder.Name = data["Name"].ToString();
  462. folder.Owner = new UUID(data["Owner"].ToString());
  463. folder.ID = new UUID(data["ID"].ToString());
  464. }
  465. catch (Exception e)
  466. {
  467. m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception building folder: ", e);
  468. }
  469. return folder;
  470. }
  471. private InventoryItemBase BuildItem(Dictionary<string,object> data)
  472. {
  473. InventoryItemBase item = new InventoryItemBase();
  474. try
  475. {
  476. item.AssetID = new UUID(data["AssetID"].ToString());
  477. item.AssetType = int.Parse(data["AssetType"].ToString());
  478. item.Name = data["Name"].ToString();
  479. item.Owner = new UUID(data["Owner"].ToString());
  480. item.ID = new UUID(data["ID"].ToString());
  481. item.InvType = int.Parse(data["InvType"].ToString());
  482. item.Folder = new UUID(data["Folder"].ToString());
  483. item.CreatorId = data["CreatorId"].ToString();
  484. if (data.ContainsKey("CreatorData"))
  485. item.CreatorData = data["CreatorData"].ToString();
  486. else
  487. item.CreatorData = String.Empty;
  488. item.Description = data["Description"].ToString();
  489. item.NextPermissions = uint.Parse(data["NextPermissions"].ToString());
  490. item.CurrentPermissions = uint.Parse(data["CurrentPermissions"].ToString());
  491. item.BasePermissions = uint.Parse(data["BasePermissions"].ToString());
  492. item.EveryOnePermissions = uint.Parse(data["EveryOnePermissions"].ToString());
  493. item.GroupPermissions = uint.Parse(data["GroupPermissions"].ToString());
  494. item.GroupID = new UUID(data["GroupID"].ToString());
  495. item.GroupOwned = bool.Parse(data["GroupOwned"].ToString());
  496. item.SalePrice = int.Parse(data["SalePrice"].ToString());
  497. item.SaleType = byte.Parse(data["SaleType"].ToString());
  498. item.Flags = uint.Parse(data["Flags"].ToString());
  499. item.CreationDate = int.Parse(data["CreationDate"].ToString());
  500. }
  501. catch (Exception e)
  502. {
  503. m_log.Error("[XINVENTORY CONNECTOR]: Exception building item: ", e);
  504. }
  505. return item;
  506. }
  507. }
  508. }