UpdateItemAsset.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. using System;
  2. using System.Collections;
  3. using System.IO;
  4. using System.Net;
  5. using System.Text;
  6. using System.Threading;
  7. using OpenMetaverse;
  8. using OpenMetaverse.StructuredData;
  9. using OpenSim.Framework;
  10. using OpenSim.Framework.Capabilities;
  11. using OpenSim.Region.Framework.Scenes;
  12. using OpenSim.Framework.Servers.HttpServer;
  13. using OSDMap = OpenMetaverse.StructuredData.OSDMap;
  14. namespace OpenSim.Region.ClientStack.Linden
  15. {
  16. public delegate UUID UpdateItem(UUID itemID, UUID objectID, byte[] data);
  17. public delegate UUID ItemUpdatedCallback(UUID userID, UUID itemID, UUID objectID, byte[] data);
  18. public partial class BunchOfCaps
  19. {
  20. public void UpdateNotecardItemAsset(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap map)
  21. {
  22. UpdateInventoryItemAsset(httpRequest, httpResponse, map, (byte)AssetType.Notecard);
  23. }
  24. public void UpdateAnimSetItemAsset(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap map)
  25. {
  26. //UpdateInventoryItemAsset(httpRequest, httpResponse, map, CustomInventoryType.AnimationSet);
  27. }
  28. public void UpdateScriptItemAsset(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap map)
  29. {
  30. UpdateInventoryItemAsset(httpRequest, httpResponse, map, (byte)AssetType.LSLText);
  31. }
  32. public void UpdateSettingsItemAsset(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap map)
  33. {
  34. UpdateInventoryItemAsset(httpRequest, httpResponse, map, (byte)AssetType.Settings);
  35. }
  36. public void UpdateGestureItemAsset(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap map)
  37. {
  38. UpdateInventoryItemAsset(httpRequest, httpResponse, map, (byte)AssetType.Gesture);
  39. }
  40. private void UpdateInventoryItemAsset(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap map, byte atype, bool taskSript = false)
  41. {
  42. m_log.Debug("[CAPS]: UpdateInventoryItemAsset Request in region: " + m_regionName + "\n");
  43. httpResponse.StatusCode = (int)HttpStatusCode.OK;
  44. UUID itemID = UUID.Zero;
  45. UUID objectID = UUID.Zero;
  46. try
  47. {
  48. if (map.TryGetValue("item_id", out OSD itmp))
  49. itemID = itmp;
  50. if (map.TryGetValue("task_id", out OSD tmp))
  51. objectID = tmp;
  52. }
  53. catch { }
  54. if (itemID == UUID.Zero)
  55. {
  56. LLSDAssetUploadError error = new LLSDAssetUploadError();
  57. error.message = "failed to recode request";
  58. error.identifier = UUID.Zero;
  59. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(error));
  60. return;
  61. }
  62. if (objectID != UUID.Zero)
  63. {
  64. SceneObjectPart sop = m_Scene.GetSceneObjectPart(objectID);
  65. if (sop == null)
  66. {
  67. LLSDAssetUploadError error = new LLSDAssetUploadError();
  68. error.message = "object not found";
  69. error.identifier = UUID.Zero;
  70. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(error));
  71. return;
  72. }
  73. if (!m_Scene.Permissions.CanEditObjectInventory(objectID, m_AgentID))
  74. {
  75. LLSDAssetUploadError error = new LLSDAssetUploadError();
  76. error.message = "No permissions to edit objec";
  77. error.identifier = UUID.Zero;
  78. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(error));
  79. return;
  80. }
  81. }
  82. string uploaderPath = GetNewCapPath();
  83. string protocol = m_HostCapsObj.SSLCaps ? "https://" : "http://";
  84. string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + uploaderPath;
  85. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  86. uploadResponse.uploader = uploaderURL;
  87. uploadResponse.state = "upload";
  88. ItemUpdater uploader = new ItemUpdater(itemID, objectID, atype, uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile);
  89. uploader.m_remoteAdress = httpRequest.RemoteIPEndPoint.Address;
  90. uploader.OnUpLoad += ItemUpdated;
  91. var uploaderHandler = new SimpleBinaryHandler("POST", uploaderPath, uploader.process);
  92. uploaderHandler.MaxDataSize = 10000000; // change per asset type?
  93. m_HostCapsObj.HttpListener.AddSimpleStreamHandler(uploaderHandler);
  94. // m_log.InfoFormat("[CAPS]: UpdateAgentInventoryAsset response: {0}",
  95. // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
  96. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(uploadResponse));
  97. }
  98. /// <summary>
  99. /// Called when new asset data for an inventory item update has been uploaded.
  100. /// </summary>
  101. /// <param name="itemID">Item to update</param>
  102. /// <param name="data">New asset data</param>
  103. /// <returns></returns>
  104. public UUID ItemUpdated(UUID itemID, UUID objectID, byte[] data)
  105. {
  106. if (ItemUpdatedCall != null)
  107. {
  108. return ItemUpdatedCall(m_HostCapsObj.AgentID, itemID, objectID, data);
  109. }
  110. return UUID.Zero;
  111. }
  112. /// <summary>
  113. /// Called by the script task update handler. Provides a URL to which the client can upload a new asset.
  114. /// </summary>
  115. /// <param name="httpRequest">HTTP request header object</param>
  116. /// <param name="httpResponse">HTTP response header object</param>
  117. /// <returns></returns>
  118. public void UpdateScriptTaskInventory(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, OSDMap map)
  119. {
  120. httpResponse.StatusCode = (int)HttpStatusCode.OK;
  121. try
  122. {
  123. //m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName);
  124. //m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param);
  125. UUID itemID = UUID.Zero;
  126. UUID objectID = UUID.Zero;
  127. bool is_script_running = false;
  128. OSD tmp;
  129. try
  130. {
  131. if (map.TryGetValue("item_id", out tmp))
  132. itemID = tmp;
  133. if (map.TryGetValue("task_id", out tmp))
  134. objectID = tmp;
  135. if (map.TryGetValue("is_script_running", out tmp))
  136. is_script_running = tmp;
  137. }
  138. catch { }
  139. if (itemID == UUID.Zero || objectID == UUID.Zero)
  140. {
  141. LLSDAssetUploadError error = new LLSDAssetUploadError();
  142. error.message = "failed to recode request";
  143. error.identifier = UUID.Zero;
  144. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(error));
  145. return;
  146. }
  147. SceneObjectPart sop = m_Scene.GetSceneObjectPart(objectID);
  148. if (sop == null)
  149. {
  150. LLSDAssetUploadError error = new LLSDAssetUploadError();
  151. error.message = "object not found";
  152. error.identifier = UUID.Zero;
  153. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(error));
  154. return;
  155. }
  156. if (!m_Scene.Permissions.CanEditObjectInventory(objectID, m_AgentID))
  157. {
  158. LLSDAssetUploadError error = new LLSDAssetUploadError();
  159. error.message = "No permissions to edit objec";
  160. error.identifier = UUID.Zero;
  161. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(error));
  162. return;
  163. }
  164. if (!m_Scene.Permissions.CanEditScript(itemID, objectID, m_AgentID))
  165. {
  166. LLSDAssetUploadError error = new LLSDAssetUploadError();
  167. error.message = "No permissions to edit script";
  168. error.identifier = UUID.Zero;
  169. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(error));
  170. return;
  171. }
  172. string uploaderPath = GetNewCapPath();
  173. string protocol = m_HostCapsObj.SSLCaps ? "https://" : "http://";
  174. string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + uploaderPath;
  175. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  176. uploadResponse.uploader = uploaderURL;
  177. uploadResponse.state = "upload";
  178. TaskInventoryScriptUpdater uploader = new TaskInventoryScriptUpdater(itemID, objectID, is_script_running,
  179. uploaderPath, m_HostCapsObj.HttpListener, httpRequest.RemoteIPEndPoint.Address, m_dumpAssetsToFile);
  180. uploader.OnUpLoad += TaskScriptUpdated;
  181. var uploaderHandler = new SimpleBinaryHandler("POST", uploaderPath, uploader.process);
  182. uploaderHandler.MaxDataSize = 10000000; // change per asset type?
  183. m_HostCapsObj.HttpListener.AddSimpleStreamHandler(uploaderHandler);
  184. // m_log.InfoFormat("[CAPS]: " +
  185. // "ScriptTaskInventory response: {0}",
  186. // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
  187. httpResponse.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(uploadResponse));
  188. }
  189. catch (Exception e)
  190. {
  191. m_log.Error("[UpdateScriptTaskInventory]: " + e.ToString());
  192. }
  193. }
  194. /// <summary>
  195. /// Called when new asset data for an agent inventory item update has been uploaded.
  196. /// </summary>
  197. /// <param name="itemID">Item to update</param>
  198. /// <param name="primID">Prim containing item to update</param>
  199. /// <param name="isScriptRunning">Signals whether the script to update is currently running</param>
  200. /// <param name="data">New asset data</param>
  201. public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors)
  202. {
  203. if (TaskScriptUpdatedCall != null)
  204. {
  205. ArrayList e = TaskScriptUpdatedCall(m_HostCapsObj.AgentID, itemID, primID, isScriptRunning, data);
  206. foreach (Object item in e)
  207. errors.Add(item);
  208. }
  209. }
  210. static public bool ValidateAssetData(byte assetType, byte[] data)
  211. {
  212. return true;
  213. }
  214. /// <summary>
  215. /// This class is a callback invoked when a client sends asset data to
  216. /// an agent inventory notecard update url
  217. /// </summary>
  218. public class ItemUpdater : ExpiringCapBase
  219. {
  220. public event UpdateItem OnUpLoad = null;
  221. private UUID m_inventoryItemID;
  222. private UUID m_objectID;
  223. private bool m_dumpAssetToFile;
  224. public IPAddress m_remoteAdress;
  225. private byte m_assetType;
  226. public ItemUpdater(UUID inventoryItem, UUID objectid, byte aType, string path, IHttpServer httpServer, bool dumpAssetToFile):
  227. base(httpServer, path)
  228. {
  229. m_dumpAssetToFile = dumpAssetToFile;
  230. m_inventoryItemID = inventoryItem;
  231. m_objectID = objectid;
  232. m_httpListener = httpServer;
  233. m_assetType = aType;
  234. Start(30000);
  235. }
  236. /// <summary>
  237. /// Handle raw uploaded asset data.
  238. /// </summary>
  239. /// <param name="data"></param>
  240. /// <param name="path"></param>
  241. /// <param name="param"></param>
  242. /// <returns></returns>
  243. public void process(IOSHttpRequest request, IOSHttpResponse response, byte[] data)
  244. {
  245. Stop();
  246. if (!request.RemoteIPEndPoint.Address.Equals(m_remoteAdress))
  247. {
  248. response.StatusCode = (int)HttpStatusCode.Unauthorized;
  249. return;
  250. }
  251. string res = String.Empty;
  252. if (OnUpLoad == null)
  253. {
  254. response.StatusCode = (int)HttpStatusCode.Gone;
  255. return;
  256. }
  257. if (!BunchOfCaps.ValidateAssetData(m_assetType, data))
  258. {
  259. response.StatusCode = (int)HttpStatusCode.BadRequest;
  260. return;
  261. }
  262. UUID assetID = OnUpLoad(m_inventoryItemID, m_objectID, data);
  263. if (assetID == UUID.Zero)
  264. {
  265. LLSDAssetUploadError uperror = new LLSDAssetUploadError();
  266. uperror.message = "Failed to update inventory item asset";
  267. uperror.identifier = m_inventoryItemID;
  268. res = LLSDHelpers.SerialiseLLSDReply(uperror);
  269. }
  270. else
  271. {
  272. LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
  273. uploadComplete.new_asset = assetID.ToString();
  274. uploadComplete.new_inventory_item = m_inventoryItemID;
  275. uploadComplete.state = "complete";
  276. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  277. }
  278. if (m_dumpAssetToFile)
  279. {
  280. Util.SaveAssetToFile("updateditem" + Util.RandomClass.Next(1, 1000) + ".dat", data);
  281. }
  282. response.StatusCode = (int)HttpStatusCode.OK;
  283. response.RawBuffer = Util.UTF8NBGetbytes(res);
  284. }
  285. }
  286. /// <summary>
  287. /// This class is a callback invoked when a client sends asset data to
  288. /// a task inventory script update url
  289. /// </summary>
  290. public class TaskInventoryScriptUpdater : ExpiringCapBase
  291. {
  292. public event UpdateTaskScript OnUpLoad;
  293. private UUID m_inventoryItemID;
  294. private UUID m_primID;
  295. private bool m_isScriptRunning;
  296. private bool m_dumpAssetToFile;
  297. public IPAddress m_remoteAddress;
  298. public TaskInventoryScriptUpdater(UUID inventoryItemID, UUID primID, bool isScriptRunning,
  299. string path, IHttpServer httpServer, IPAddress address,
  300. bool dumpAssetToFile) : base(httpServer, path)
  301. {
  302. m_dumpAssetToFile = dumpAssetToFile;
  303. m_inventoryItemID = inventoryItemID;
  304. m_primID = primID;
  305. m_isScriptRunning = isScriptRunning;
  306. m_remoteAddress = address;
  307. Start(30000);
  308. }
  309. /// <summary>
  310. ///
  311. /// </summary>
  312. /// <param name="data"></param>
  313. /// <param name="path"></param>
  314. /// <param name="param"></param>
  315. /// <returns></returns>
  316. public void process(IOSHttpRequest request, IOSHttpResponse response, byte[] data)
  317. {
  318. Stop();
  319. if (!request.RemoteIPEndPoint.Address.Equals(m_remoteAddress))
  320. {
  321. response.StatusCode = (int)HttpStatusCode.Unauthorized;
  322. return;
  323. }
  324. if (OnUpLoad == null)
  325. {
  326. response.StatusCode = (int)HttpStatusCode.Gone;
  327. return;
  328. }
  329. if (!BunchOfCaps.ValidateAssetData((byte)AssetType.LSLText, data))
  330. {
  331. response.StatusCode = (int)HttpStatusCode.BadRequest;
  332. return;
  333. }
  334. response.StatusCode = (int)HttpStatusCode.OK;
  335. try
  336. {
  337. string res = String.Empty;
  338. LLSDTaskScriptUploadComplete uploadComplete = new LLSDTaskScriptUploadComplete();
  339. ArrayList errors = new ArrayList();
  340. OnUpLoad?.Invoke(m_inventoryItemID, m_primID, m_isScriptRunning, data, ref errors);
  341. uploadComplete.new_asset = m_inventoryItemID;
  342. uploadComplete.compiled = errors.Count > 0 ? false : true;
  343. uploadComplete.state = "complete";
  344. uploadComplete.errors = new OpenSim.Framework.Capabilities.OSDArray();
  345. uploadComplete.errors.Array = errors;
  346. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  347. if (m_dumpAssetToFile)
  348. {
  349. Util.SaveAssetToFile("updatedtaskscript" + Util.RandomClass.Next(1, 1000) + ".dat", data);
  350. }
  351. // m_log.InfoFormat("[CAPS]: TaskInventoryScriptUpdater.uploaderCaps res: {0}", res);
  352. response.RawBuffer = Util.UTF8NBGetbytes(res);
  353. }
  354. catch
  355. {
  356. LLSDAssetUploadError error = new LLSDAssetUploadError();
  357. error.message = "could not compile script";
  358. error.identifier = UUID.Zero;
  359. response.RawBuffer = Util.UTF8NBGetbytes(LLSDHelpers.SerialiseLLSDReply(error));
  360. return;
  361. }
  362. }
  363. }
  364. }
  365. }