BunchOfCaps.cs 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228
  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;
  29. using System.Collections.Generic;
  30. using System.IO;
  31. using System.Reflection;
  32. using System.Text;
  33. using OpenMetaverse;
  34. using OpenMetaverse.StructuredData;
  35. using Nini.Config;
  36. using log4net;
  37. using OpenSim.Framework;
  38. using OpenSim.Framework.Capabilities;
  39. using OpenSim.Region.Framework;
  40. using OpenSim.Region.Framework.Scenes;
  41. using OpenSim.Region.Framework.Scenes.Serialization;
  42. using OpenSim.Framework.Servers;
  43. using OpenSim.Framework.Servers.HttpServer;
  44. using OpenSim.Services.Interfaces;
  45. using Caps = OpenSim.Framework.Capabilities.Caps;
  46. using OSDArray = OpenMetaverse.StructuredData.OSDArray;
  47. using OSDMap = OpenMetaverse.StructuredData.OSDMap;
  48. using PermissionMask = OpenSim.Framework.PermissionMask;
  49. namespace OpenSim.Region.ClientStack.Linden
  50. {
  51. public delegate void UpLoadedAsset(
  52. string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
  53. byte[] data, string inventoryType, string assetType);
  54. public delegate UUID UpdateItem(UUID itemID, byte[] data);
  55. public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
  56. public delegate void NewInventoryItem(UUID userID, InventoryItemBase item);
  57. public delegate void NewAsset(AssetBase asset);
  58. public delegate UUID ItemUpdatedCallback(UUID userID, UUID itemID, byte[] data);
  59. public delegate ArrayList TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID,
  60. bool isScriptRunning, byte[] data);
  61. public delegate InventoryCollection FetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID,
  62. bool fetchFolders, bool fetchItems, int sortOrder, out int version);
  63. /// <summary>
  64. /// XXX Probably not a particularly nice way of allow us to get the scene presence from the scene (chiefly so that
  65. /// we can popup a message on the user's client if the inventory service has permanently failed). But I didn't want
  66. /// to just pass the whole Scene into CAPS.
  67. /// </summary>
  68. public delegate IClientAPI GetClientDelegate(UUID agentID);
  69. public class BunchOfCaps
  70. {
  71. private static readonly ILog m_log =
  72. LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  73. private Scene m_Scene;
  74. private Caps m_HostCapsObj;
  75. private static readonly string m_requestPath = "0000/";
  76. // private static readonly string m_mapLayerPath = "0001/";
  77. private static readonly string m_newInventory = "0002/";
  78. //private static readonly string m_requestTexture = "0003/";
  79. private static readonly string m_notecardUpdatePath = "0004/";
  80. private static readonly string m_notecardTaskUpdatePath = "0005/";
  81. // private static readonly string m_fetchInventoryPath = "0006/";
  82. private static readonly string m_copyFromNotecardPath = "0007/";
  83. // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
  84. private static readonly string m_getObjectPhysicsDataPath = "0101/";
  85. /* 0102 - 0103 RESERVED */
  86. private static readonly string m_UpdateAgentInformationPath = "0500/";
  87. // These are callbacks which will be setup by the scene so that we can update scene data when we
  88. // receive capability calls
  89. public NewInventoryItem AddNewInventoryItem = null;
  90. public NewAsset AddNewAsset = null;
  91. public ItemUpdatedCallback ItemUpdatedCall = null;
  92. public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null;
  93. public FetchInventoryDescendentsCAPS CAPSFetchInventoryDescendents = null;
  94. public GetClientDelegate GetClient = null;
  95. private bool m_persistBakedTextures = false;
  96. private IAssetService m_assetService;
  97. private bool m_dumpAssetsToFile = false;
  98. private string m_regionName;
  99. private int m_levelUpload = 0;
  100. public BunchOfCaps(Scene scene, Caps caps)
  101. {
  102. m_Scene = scene;
  103. m_HostCapsObj = caps;
  104. IConfigSource config = m_Scene.Config;
  105. if (config != null)
  106. {
  107. IConfig sconfig = config.Configs["Startup"];
  108. if (sconfig != null)
  109. {
  110. m_levelUpload = sconfig.GetInt("LevelUpload", 0);
  111. }
  112. IConfig appearanceConfig = config.Configs["Appearance"];
  113. if (appearanceConfig != null)
  114. {
  115. m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
  116. }
  117. }
  118. m_assetService = m_Scene.AssetService;
  119. m_regionName = m_Scene.RegionInfo.RegionName;
  120. RegisterHandlers();
  121. AddNewInventoryItem = m_Scene.AddUploadedInventoryItem;
  122. ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
  123. TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
  124. GetClient = m_Scene.SceneGraph.GetControllingClient;
  125. }
  126. /// <summary>
  127. /// Register a bunch of CAPS http service handlers
  128. /// </summary>
  129. public void RegisterHandlers()
  130. {
  131. string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
  132. RegisterRegionServiceHandlers(capsBase);
  133. RegisterInventoryServiceHandlers(capsBase);
  134. }
  135. public void RegisterRegionServiceHandlers(string capsBase)
  136. {
  137. try
  138. {
  139. // the root of all evil
  140. m_HostCapsObj.RegisterHandler(
  141. "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
  142. // m_log.DebugFormat(
  143. // "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
  144. //m_capsHandlers["MapLayer"] =
  145. // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
  146. // capsBase + m_mapLayerPath,
  147. // GetMapLayer);
  148. IRequestHandler req
  149. = new RestStreamHandler(
  150. "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null);
  151. m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
  152. m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
  153. }
  154. catch (Exception e)
  155. {
  156. m_log.Error("[CAPS]: " + e.ToString());
  157. }
  158. }
  159. public void RegisterInventoryServiceHandlers(string capsBase)
  160. {
  161. try
  162. {
  163. // I don't think this one works...
  164. m_HostCapsObj.RegisterHandler(
  165. "NewFileAgentInventory",
  166. new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
  167. "POST",
  168. capsBase + m_newInventory,
  169. NewAgentInventoryRequest,
  170. "NewFileAgentInventory",
  171. null));
  172. IRequestHandler req
  173. = new RestStreamHandler(
  174. "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null);
  175. m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
  176. m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
  177. m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
  178. IRequestHandler getObjectPhysicsDataHandler
  179. = new RestStreamHandler(
  180. "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
  181. m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
  182. IRequestHandler UpdateAgentInformationHandler
  183. = new RestStreamHandler(
  184. "POST", capsBase + m_UpdateAgentInformationPath, UpdateAgentInformation, "UpdateAgentInformation", null);
  185. m_HostCapsObj.RegisterHandler("UpdateAgentInformation", UpdateAgentInformationHandler);
  186. m_HostCapsObj.RegisterHandler(
  187. "CopyInventoryFromNotecard",
  188. new RestStreamHandler(
  189. "POST", capsBase + m_copyFromNotecardPath, CopyInventoryFromNotecard, "CopyInventoryFromNotecard", null));
  190. // As of RC 1.22.9 of the Linden client this is
  191. // supported
  192. //m_capsHandlers["WebFetchInventoryDescendents"] =new RestStreamHandler("POST", capsBase + m_fetchInventoryPath, FetchInventoryDescendentsRequest);
  193. // justincc: I've disabled the CAPS service for now to fix problems with selecting textures, and
  194. // subsequent inventory breakage, in the edit object pane (such as mantis 1085). This requires
  195. // enhancements (probably filling out the folder part of the LLSD reply) to our CAPS service,
  196. // but when I went on the Linden grid, the
  197. // simulators I visited (version 1.21) were, surprisingly, no longer supplying this capability. Instead,
  198. // the 1.19.1.4 client appeared to be happily flowing inventory data over UDP
  199. //
  200. // This is very probably just a temporary measure - once the CAPS service appears again on the Linden grid
  201. // we will be
  202. // able to get the data we need to implement the necessary part of the protocol to fix the issue above.
  203. // m_capsHandlers["FetchInventoryDescendents"] =
  204. // new RestStreamHandler("POST", capsBase + m_fetchInventoryPath, FetchInventoryRequest);
  205. // m_capsHandlers["FetchInventoryDescendents"] =
  206. // new LLSDStreamhandler<LLSDFetchInventoryDescendents, LLSDInventoryDescendents>("POST",
  207. // capsBase + m_fetchInventory,
  208. // FetchInventory));
  209. // m_capsHandlers["RequestTextureDownload"] = new RestStreamHandler("POST",
  210. // capsBase + m_requestTexture,
  211. // RequestTexture);
  212. }
  213. catch (Exception e)
  214. {
  215. m_log.Error("[CAPS]: " + e.ToString());
  216. }
  217. }
  218. /// <summary>
  219. /// Construct a client response detailing all the capabilities this server can provide.
  220. /// </summary>
  221. /// <param name="request"></param>
  222. /// <param name="path"></param>
  223. /// <param name="param"></param>
  224. /// <param name="httpRequest">HTTP request header object</param>
  225. /// <param name="httpResponse">HTTP response header object</param>
  226. /// <returns></returns>
  227. public string SeedCapRequest(string request, string path, string param,
  228. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  229. {
  230. m_log.DebugFormat(
  231. "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
  232. if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
  233. {
  234. m_log.WarnFormat(
  235. "[CAPS]: Unauthorized CAPS client {0} from {1}",
  236. m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
  237. return string.Empty;
  238. }
  239. OSDArray capsRequested = (OSDArray)OSDParser.DeserializeLLSDXml(request);
  240. List<string> validCaps = new List<string>();
  241. foreach (OSD c in capsRequested)
  242. validCaps.Add(c.AsString());
  243. string result = LLSDHelpers.SerialiseLLSDReply(m_HostCapsObj.GetCapsDetails(true, validCaps));
  244. //m_log.DebugFormat("[CAPS] CapsRequest {0}", result);
  245. return result;
  246. }
  247. /// <summary>
  248. /// Called by the script task update handler. Provides a URL to which the client can upload a new asset.
  249. /// </summary>
  250. /// <param name="request"></param>
  251. /// <param name="path"></param>
  252. /// <param name="param"></param>
  253. /// <param name="httpRequest">HTTP request header object</param>
  254. /// <param name="httpResponse">HTTP response header object</param>
  255. /// <returns></returns>
  256. public string ScriptTaskInventory(string request, string path, string param,
  257. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  258. {
  259. try
  260. {
  261. // m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName);
  262. //m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param);
  263. Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
  264. LLSDTaskScriptUpdate llsdUpdateRequest = new LLSDTaskScriptUpdate();
  265. LLSDHelpers.DeserialiseOSDMap(hash, llsdUpdateRequest);
  266. string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
  267. string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
  268. TaskInventoryScriptUpdater uploader =
  269. new TaskInventoryScriptUpdater(
  270. llsdUpdateRequest.item_id,
  271. llsdUpdateRequest.task_id,
  272. llsdUpdateRequest.is_script_running,
  273. capsBase + uploaderPath,
  274. m_HostCapsObj.HttpListener,
  275. m_dumpAssetsToFile);
  276. uploader.OnUpLoad += TaskScriptUpdated;
  277. m_HostCapsObj.HttpListener.AddStreamHandler(
  278. new BinaryStreamHandler(
  279. "POST", capsBase + uploaderPath, uploader.uploaderCaps, "TaskInventoryScriptUpdater", null));
  280. string protocol = "http://";
  281. if (m_HostCapsObj.SSLCaps)
  282. protocol = "https://";
  283. string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
  284. uploaderPath;
  285. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  286. uploadResponse.uploader = uploaderURL;
  287. uploadResponse.state = "upload";
  288. // m_log.InfoFormat("[CAPS]: " +
  289. // "ScriptTaskInventory response: {0}",
  290. // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
  291. return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
  292. }
  293. catch (Exception e)
  294. {
  295. m_log.Error("[CAPS]: " + e.ToString());
  296. }
  297. return null;
  298. }
  299. /// <summary>
  300. /// Called when new asset data for an agent inventory item update has been uploaded.
  301. /// </summary>
  302. /// <param name="itemID">Item to update</param>
  303. /// <param name="primID">Prim containing item to update</param>
  304. /// <param name="isScriptRunning">Signals whether the script to update is currently running</param>
  305. /// <param name="data">New asset data</param>
  306. public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors)
  307. {
  308. if (TaskScriptUpdatedCall != null)
  309. {
  310. ArrayList e = TaskScriptUpdatedCall(m_HostCapsObj.AgentID, itemID, primID, isScriptRunning, data);
  311. foreach (Object item in e)
  312. errors.Add(item);
  313. }
  314. }
  315. /// <summary>
  316. /// Called when new asset data for an agent inventory item update has been uploaded.
  317. /// </summary>
  318. /// <param name="itemID">Item to update</param>
  319. /// <param name="data">New asset data</param>
  320. /// <returns></returns>
  321. public UUID ItemUpdated(UUID itemID, byte[] data)
  322. {
  323. if (ItemUpdatedCall != null)
  324. {
  325. return ItemUpdatedCall(m_HostCapsObj.AgentID, itemID, data);
  326. }
  327. return UUID.Zero;
  328. }
  329. /// <summary>
  330. ///
  331. /// </summary>
  332. /// <param name="llsdRequest"></param>
  333. /// <returns></returns>
  334. public LLSDAssetUploadResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest)
  335. {
  336. //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
  337. //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
  338. if (llsdRequest.asset_type == "texture" ||
  339. llsdRequest.asset_type == "animation" ||
  340. llsdRequest.asset_type == "sound")
  341. {
  342. ScenePresence avatar = null;
  343. IClientAPI client = null;
  344. m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
  345. // check user level
  346. if (avatar != null)
  347. {
  348. client = avatar.ControllingClient;
  349. if (avatar.UserLevel < m_levelUpload)
  350. {
  351. if (client != null)
  352. client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
  353. LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
  354. errorResponse.uploader = "";
  355. errorResponse.state = "error";
  356. return errorResponse;
  357. }
  358. }
  359. // check funds
  360. if (client != null)
  361. {
  362. IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
  363. if (mm != null)
  364. {
  365. if (!mm.UploadCovered(client.AgentId, mm.UploadCharge))
  366. {
  367. client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
  368. LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
  369. errorResponse.uploader = "";
  370. errorResponse.state = "error";
  371. return errorResponse;
  372. }
  373. }
  374. }
  375. }
  376. string assetName = llsdRequest.name;
  377. string assetDes = llsdRequest.description;
  378. string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
  379. UUID newAsset = UUID.Random();
  380. UUID newInvItem = UUID.Random();
  381. UUID parentFolder = llsdRequest.folder_id;
  382. string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
  383. AssetUploader uploader =
  384. new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
  385. llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile);
  386. m_HostCapsObj.HttpListener.AddStreamHandler(
  387. new BinaryStreamHandler(
  388. "POST",
  389. capsBase + uploaderPath,
  390. uploader.uploaderCaps,
  391. "NewAgentInventoryRequest",
  392. m_HostCapsObj.AgentID.ToString()));
  393. string protocol = "http://";
  394. if (m_HostCapsObj.SSLCaps)
  395. protocol = "https://";
  396. string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
  397. uploaderPath;
  398. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  399. uploadResponse.uploader = uploaderURL;
  400. uploadResponse.state = "upload";
  401. uploader.OnUpLoad += UploadCompleteHandler;
  402. return uploadResponse;
  403. }
  404. /// <summary>
  405. /// Convert raw uploaded data into the appropriate asset and item.
  406. /// </summary>
  407. /// <param name="assetID"></param>
  408. /// <param name="inventoryItem"></param>
  409. /// <param name="data"></param>
  410. public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
  411. UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
  412. string assetType)
  413. {
  414. m_log.DebugFormat(
  415. "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
  416. assetID, inventoryItem, inventoryType, assetType);
  417. sbyte assType = 0;
  418. sbyte inType = 0;
  419. if (inventoryType == "sound")
  420. {
  421. inType = 1;
  422. assType = 1;
  423. }
  424. else if (inventoryType == "animation")
  425. {
  426. inType = 19;
  427. assType = 20;
  428. }
  429. else if (inventoryType == "wearable")
  430. {
  431. inType = 18;
  432. switch (assetType)
  433. {
  434. case "bodypart":
  435. assType = 13;
  436. break;
  437. case "clothing":
  438. assType = 5;
  439. break;
  440. }
  441. }
  442. else if (inventoryType == "object")
  443. {
  444. inType = (sbyte)InventoryType.Object;
  445. assType = (sbyte)AssetType.Object;
  446. List<Vector3> positions = new List<Vector3>();
  447. List<Quaternion> rotations = new List<Quaternion>();
  448. OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
  449. OSDArray instance_list = (OSDArray)request["instance_list"];
  450. OSDArray mesh_list = (OSDArray)request["mesh_list"];
  451. OSDArray texture_list = (OSDArray)request["texture_list"];
  452. SceneObjectGroup grp = null;
  453. List<UUID> textures = new List<UUID>();
  454. for (int i = 0; i < texture_list.Count; i++)
  455. {
  456. AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, "");
  457. textureAsset.Data = texture_list[i].AsBinary();
  458. m_assetService.Store(textureAsset);
  459. textures.Add(textureAsset.FullID);
  460. }
  461. for (int i = 0; i < mesh_list.Count; i++)
  462. {
  463. PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
  464. Primitive.TextureEntry textureEntry
  465. = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
  466. OSDMap inner_instance_list = (OSDMap)instance_list[i];
  467. OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
  468. for (uint face = 0; face < face_list.Count; face++)
  469. {
  470. OSDMap faceMap = (OSDMap)face_list[(int)face];
  471. Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
  472. if(faceMap.ContainsKey("fullbright"))
  473. f.Fullbright = faceMap["fullbright"].AsBoolean();
  474. if (faceMap.ContainsKey ("diffuse_color"))
  475. f.RGBA = faceMap["diffuse_color"].AsColor4();
  476. int textureNum = faceMap["image"].AsInteger();
  477. float imagerot = faceMap["imagerot"].AsInteger();
  478. float offsets = (float)faceMap["offsets"].AsReal();
  479. float offsett = (float)faceMap["offsett"].AsReal();
  480. float scales = (float)faceMap["scales"].AsReal();
  481. float scalet = (float)faceMap["scalet"].AsReal();
  482. if(imagerot != 0)
  483. f.Rotation = imagerot;
  484. if(offsets != 0)
  485. f.OffsetU = offsets;
  486. if (offsett != 0)
  487. f.OffsetV = offsett;
  488. if (scales != 0)
  489. f.RepeatU = scales;
  490. if (scalet != 0)
  491. f.RepeatV = scalet;
  492. if (textures.Count > textureNum)
  493. f.TextureID = textures[textureNum];
  494. else
  495. f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
  496. textureEntry.FaceTextures[face] = f;
  497. }
  498. pbs.TextureEntry = textureEntry.GetBytes();
  499. AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, "");
  500. meshAsset.Data = mesh_list[i].AsBinary();
  501. m_assetService.Store(meshAsset);
  502. pbs.SculptEntry = true;
  503. pbs.SculptTexture = meshAsset.FullID;
  504. pbs.SculptType = (byte)SculptType.Mesh;
  505. pbs.SculptData = meshAsset.Data;
  506. Vector3 position = inner_instance_list["position"].AsVector3();
  507. Vector3 scale = inner_instance_list["scale"].AsVector3();
  508. Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
  509. // no longer used - begin ------------------------
  510. // int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
  511. // int material = inner_instance_list["material"].AsInteger();
  512. // int mesh = inner_instance_list["mesh"].AsInteger();
  513. // OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
  514. // int base_mask = permissions["base_mask"].AsInteger();
  515. // int everyone_mask = permissions["everyone_mask"].AsInteger();
  516. // UUID creator_id = permissions["creator_id"].AsUUID();
  517. // UUID group_id = permissions["group_id"].AsUUID();
  518. // int group_mask = permissions["group_mask"].AsInteger();
  519. // bool is_owner_group = permissions["is_owner_group"].AsBoolean();
  520. // UUID last_owner_id = permissions["last_owner_id"].AsUUID();
  521. // int next_owner_mask = permissions["next_owner_mask"].AsInteger();
  522. // UUID owner_id = permissions["owner_id"].AsUUID();
  523. // int owner_mask = permissions["owner_mask"].AsInteger();
  524. // no longer used - end ------------------------
  525. UUID owner_id = m_HostCapsObj.AgentID;
  526. SceneObjectPart prim
  527. = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
  528. prim.Scale = scale;
  529. //prim.OffsetPosition = position;
  530. rotations.Add(rotation);
  531. positions.Add(position);
  532. prim.UUID = UUID.Random();
  533. prim.CreatorID = owner_id;
  534. prim.OwnerID = owner_id;
  535. prim.GroupID = UUID.Zero;
  536. prim.LastOwnerID = prim.OwnerID;
  537. prim.CreationDate = Util.UnixTimeSinceEpoch();
  538. prim.Name = assetName;
  539. prim.Description = "";
  540. // prim.BaseMask = (uint)base_mask;
  541. // prim.EveryoneMask = (uint)everyone_mask;
  542. // prim.GroupMask = (uint)group_mask;
  543. // prim.NextOwnerMask = (uint)next_owner_mask;
  544. // prim.OwnerMask = (uint)owner_mask;
  545. if (grp == null)
  546. grp = new SceneObjectGroup(prim);
  547. else
  548. grp.AddPart(prim);
  549. }
  550. Vector3 rootPos = positions[0];
  551. if (grp.Parts.Length > 1)
  552. {
  553. // Fix first link number
  554. grp.RootPart.LinkNum++;
  555. Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
  556. Quaternion tmprot;
  557. Vector3 offset;
  558. // fix children rotations and positions
  559. for (int i = 1; i < rotations.Count; i++)
  560. {
  561. tmprot = rotations[i];
  562. tmprot = rootRotConj * tmprot;
  563. grp.Parts[i].RotationOffset = tmprot;
  564. offset = positions[i] - rootPos;
  565. offset *= rootRotConj;
  566. grp.Parts[i].OffsetPosition = offset;
  567. }
  568. grp.AbsolutePosition = rootPos;
  569. grp.UpdateGroupRotationR(rotations[0]);
  570. }
  571. else
  572. {
  573. grp.AbsolutePosition = rootPos;
  574. grp.UpdateGroupRotationR(rotations[0]);
  575. }
  576. data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
  577. }
  578. AssetBase asset;
  579. asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString());
  580. asset.Data = data;
  581. if (AddNewAsset != null)
  582. AddNewAsset(asset);
  583. else if (m_assetService != null)
  584. m_assetService.Store(asset);
  585. InventoryItemBase item = new InventoryItemBase();
  586. item.Owner = m_HostCapsObj.AgentID;
  587. item.CreatorId = m_HostCapsObj.AgentID.ToString();
  588. item.CreatorData = String.Empty;
  589. item.ID = inventoryItem;
  590. item.AssetID = asset.FullID;
  591. item.Description = assetDescription;
  592. item.Name = assetName;
  593. item.AssetType = assType;
  594. item.InvType = inType;
  595. item.Folder = parentFolder;
  596. // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
  597. // (owner) permissions. This becomes a problem if next permissions are changed.
  598. item.CurrentPermissions
  599. = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
  600. item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
  601. item.EveryOnePermissions = 0;
  602. item.NextPermissions = (uint)PermissionMask.All;
  603. item.CreationDate = Util.UnixTimeSinceEpoch();
  604. if (AddNewInventoryItem != null)
  605. {
  606. AddNewInventoryItem(m_HostCapsObj.AgentID, item);
  607. }
  608. }
  609. /// <summary>
  610. ///
  611. /// </summary>
  612. /// <param name="mapReq"></param>
  613. /// <returns></returns>
  614. public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq)
  615. {
  616. m_log.Debug("[CAPS]: MapLayer Request in region: " + m_regionName);
  617. LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
  618. mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
  619. return mapResponse;
  620. }
  621. /// <summary>
  622. ///
  623. /// </summary>
  624. /// <returns></returns>
  625. protected static OSDMapLayer GetOSDMapLayerResponse()
  626. {
  627. OSDMapLayer mapLayer = new OSDMapLayer();
  628. mapLayer.Right = 5000;
  629. mapLayer.Top = 5000;
  630. mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
  631. return mapLayer;
  632. }
  633. /// <summary>
  634. ///
  635. /// </summary>
  636. /// <param name="request"></param>
  637. /// <param name="path"></param>
  638. /// <param name="param"></param>
  639. /// <returns></returns>
  640. public string RequestTexture(string request, string path, string param)
  641. {
  642. m_log.Debug("texture request " + request);
  643. // Needs implementing (added to remove compiler warning)
  644. return String.Empty;
  645. }
  646. /// <summary>
  647. /// Called by the notecard update handler. Provides a URL to which the client can upload a new asset.
  648. /// </summary>
  649. /// <param name="request"></param>
  650. /// <param name="path"></param>
  651. /// <param name="param"></param>
  652. /// <returns></returns>
  653. public string NoteCardAgentInventory(string request, string path, string param,
  654. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  655. {
  656. //m_log.Debug("[CAPS]: NoteCardAgentInventory Request in region: " + m_regionName + "\n" + request);
  657. //m_log.Debug("[CAPS]: NoteCardAgentInventory Request is: " + request);
  658. //OpenMetaverse.StructuredData.OSDMap hash = (OpenMetaverse.StructuredData.OSDMap)OpenMetaverse.StructuredData.LLSDParser.DeserializeBinary(Utils.StringToBytes(request));
  659. Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
  660. LLSDItemUpdate llsdRequest = new LLSDItemUpdate();
  661. LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest);
  662. string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
  663. string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
  664. ItemUpdater uploader =
  665. new ItemUpdater(llsdRequest.item_id, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile);
  666. uploader.OnUpLoad += ItemUpdated;
  667. m_HostCapsObj.HttpListener.AddStreamHandler(
  668. new BinaryStreamHandler(
  669. "POST", capsBase + uploaderPath, uploader.uploaderCaps, "NoteCardAgentInventory", null));
  670. string protocol = "http://";
  671. if (m_HostCapsObj.SSLCaps)
  672. protocol = "https://";
  673. string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
  674. uploaderPath;
  675. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  676. uploadResponse.uploader = uploaderURL;
  677. uploadResponse.state = "upload";
  678. // m_log.InfoFormat("[CAPS]: " +
  679. // "NoteCardAgentInventory response: {0}",
  680. // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
  681. return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
  682. }
  683. /// <summary>
  684. /// Called by the CopyInventoryFromNotecard caps handler.
  685. /// </summary>
  686. /// <param name="request"></param>
  687. /// <param name="path"></param>
  688. /// <param name="param"></param>
  689. public string CopyInventoryFromNotecard(string request, string path, string param,
  690. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  691. {
  692. Hashtable response = new Hashtable();
  693. response["int_response_code"] = 404;
  694. response["content_type"] = "text/plain";
  695. response["keepalive"] = false;
  696. response["str_response_string"] = "";
  697. try
  698. {
  699. OSDMap content = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  700. UUID objectID = content["object-id"].AsUUID();
  701. UUID notecardID = content["notecard-id"].AsUUID();
  702. UUID folderID = content["folder-id"].AsUUID();
  703. UUID itemID = content["item-id"].AsUUID();
  704. // m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, FolderID:{0}, ItemID:{1}, NotecardID:{2}, ObjectID:{3}", folderID, itemID, notecardID, objectID);
  705. if (objectID != UUID.Zero)
  706. {
  707. SceneObjectPart part = m_Scene.GetSceneObjectPart(objectID);
  708. if (part != null)
  709. {
  710. // TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(notecardID);
  711. if (!m_Scene.Permissions.CanCopyObjectInventory(notecardID, objectID, m_HostCapsObj.AgentID))
  712. {
  713. return LLSDHelpers.SerialiseLLSDReply(response);
  714. }
  715. }
  716. }
  717. InventoryItemBase item = null;
  718. InventoryItemBase copyItem = null;
  719. IClientAPI client = null;
  720. m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
  721. item = m_Scene.InventoryService.GetItem(new InventoryItemBase(itemID));
  722. if (item != null)
  723. {
  724. copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID);
  725. if (copyItem != null && client != null)
  726. {
  727. m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder);
  728. client.SendBulkUpdateInventory(copyItem);
  729. }
  730. }
  731. else
  732. {
  733. m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID);
  734. if (client != null)
  735. client.SendAlertMessage("Failed to retrieve item");
  736. }
  737. }
  738. catch (Exception e)
  739. {
  740. m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard : {0}", e.ToString());
  741. }
  742. response["int_response_code"] = 200;
  743. return LLSDHelpers.SerialiseLLSDReply(response);
  744. }
  745. public string GetObjectPhysicsData(string request, string path,
  746. string param, IOSHttpRequest httpRequest,
  747. IOSHttpResponse httpResponse)
  748. {
  749. OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  750. OSDMap resp = new OSDMap();
  751. OSDArray object_ids = (OSDArray)req["object_ids"];
  752. for (int i = 0 ; i < object_ids.Count ; i++)
  753. {
  754. UUID uuid = object_ids[i].AsUUID();
  755. SceneObjectPart obj = m_Scene.GetSceneObjectPart(uuid);
  756. if (obj != null)
  757. {
  758. OSDMap object_data = new OSDMap();
  759. object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
  760. object_data["Density"] = obj.Density;
  761. object_data["Friction"] = obj.Friction;
  762. object_data["Restitution"] = obj.Restitution;
  763. object_data["GravityMultiplier"] = obj.GravityModifier;
  764. resp[uuid.ToString()] = object_data;
  765. }
  766. }
  767. string response = OSDParser.SerializeLLSDXmlString(resp);
  768. return response;
  769. }
  770. public string UpdateAgentInformation(string request, string path,
  771. string param, IOSHttpRequest httpRequest,
  772. IOSHttpResponse httpResponse)
  773. {
  774. // OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  775. OSDMap resp = new OSDMap();
  776. OSDMap accessPrefs = new OSDMap();
  777. accessPrefs["max"] = "A";
  778. resp["access_prefs"] = accessPrefs;
  779. string response = OSDParser.SerializeLLSDXmlString(resp);
  780. return response;
  781. }
  782. }
  783. public class AssetUploader
  784. {
  785. public event UpLoadedAsset OnUpLoad;
  786. private UpLoadedAsset handlerUpLoad = null;
  787. private string uploaderPath = String.Empty;
  788. private UUID newAssetID;
  789. private UUID inventoryItemID;
  790. private UUID parentFolder;
  791. private IHttpServer httpListener;
  792. private bool m_dumpAssetsToFile;
  793. private string m_assetName = String.Empty;
  794. private string m_assetDes = String.Empty;
  795. private string m_invType = String.Empty;
  796. private string m_assetType = String.Empty;
  797. public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
  798. UUID parentFolderID, string invType, string assetType, string path,
  799. IHttpServer httpServer, bool dumpAssetsToFile)
  800. {
  801. m_assetName = assetName;
  802. m_assetDes = description;
  803. newAssetID = assetID;
  804. inventoryItemID = inventoryItem;
  805. uploaderPath = path;
  806. httpListener = httpServer;
  807. parentFolder = parentFolderID;
  808. m_assetType = assetType;
  809. m_invType = invType;
  810. m_dumpAssetsToFile = dumpAssetsToFile;
  811. }
  812. /// <summary>
  813. /// Handle raw asset upload data via the capability.
  814. /// </summary>
  815. /// <param name="data"></param>
  816. /// <param name="path"></param>
  817. /// <param name="param"></param>
  818. /// <returns></returns>
  819. public string uploaderCaps(byte[] data, string path, string param)
  820. {
  821. UUID inv = inventoryItemID;
  822. string res = String.Empty;
  823. LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
  824. uploadComplete.new_asset = newAssetID.ToString();
  825. uploadComplete.new_inventory_item = inv;
  826. uploadComplete.state = "complete";
  827. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  828. httpListener.RemoveStreamHandler("POST", uploaderPath);
  829. // TODO: probably make this a better set of extensions here
  830. string extension = ".jp2";
  831. if (m_invType != "image")
  832. {
  833. extension = ".dat";
  834. }
  835. if (m_dumpAssetsToFile)
  836. {
  837. SaveAssetToFile(m_assetName + extension, data);
  838. }
  839. handlerUpLoad = OnUpLoad;
  840. if (handlerUpLoad != null)
  841. {
  842. handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType);
  843. }
  844. return res;
  845. }
  846. ///Left this in and commented in case there are unforseen issues
  847. //private void SaveAssetToFile(string filename, byte[] data)
  848. //{
  849. // FileStream fs = File.Create(filename);
  850. // BinaryWriter bw = new BinaryWriter(fs);
  851. // bw.Write(data);
  852. // bw.Close();
  853. // fs.Close();
  854. //}
  855. private static void SaveAssetToFile(string filename, byte[] data)
  856. {
  857. string assetPath = "UserAssets";
  858. if (!Directory.Exists(assetPath))
  859. {
  860. Directory.CreateDirectory(assetPath);
  861. }
  862. FileStream fs = File.Create(Path.Combine(assetPath, Util.safeFileName(filename)));
  863. BinaryWriter bw = new BinaryWriter(fs);
  864. bw.Write(data);
  865. bw.Close();
  866. fs.Close();
  867. }
  868. }
  869. /// <summary>
  870. /// This class is a callback invoked when a client sends asset data to
  871. /// an agent inventory notecard update url
  872. /// </summary>
  873. public class ItemUpdater
  874. {
  875. public event UpdateItem OnUpLoad;
  876. private UpdateItem handlerUpdateItem = null;
  877. private string uploaderPath = String.Empty;
  878. private UUID inventoryItemID;
  879. private IHttpServer httpListener;
  880. private bool m_dumpAssetToFile;
  881. public ItemUpdater(UUID inventoryItem, string path, IHttpServer httpServer, bool dumpAssetToFile)
  882. {
  883. m_dumpAssetToFile = dumpAssetToFile;
  884. inventoryItemID = inventoryItem;
  885. uploaderPath = path;
  886. httpListener = httpServer;
  887. }
  888. /// <summary>
  889. /// Handle raw uploaded asset data.
  890. /// </summary>
  891. /// <param name="data"></param>
  892. /// <param name="path"></param>
  893. /// <param name="param"></param>
  894. /// <returns></returns>
  895. public string uploaderCaps(byte[] data, string path, string param)
  896. {
  897. UUID inv = inventoryItemID;
  898. string res = String.Empty;
  899. LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
  900. UUID assetID = UUID.Zero;
  901. handlerUpdateItem = OnUpLoad;
  902. if (handlerUpdateItem != null)
  903. {
  904. assetID = handlerUpdateItem(inv, data);
  905. }
  906. uploadComplete.new_asset = assetID.ToString();
  907. uploadComplete.new_inventory_item = inv;
  908. uploadComplete.state = "complete";
  909. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  910. httpListener.RemoveStreamHandler("POST", uploaderPath);
  911. if (m_dumpAssetToFile)
  912. {
  913. SaveAssetToFile("updateditem" + Util.RandomClass.Next(1, 1000) + ".dat", data);
  914. }
  915. return res;
  916. }
  917. ///Left this in and commented in case there are unforseen issues
  918. //private void SaveAssetToFile(string filename, byte[] data)
  919. //{
  920. // FileStream fs = File.Create(filename);
  921. // BinaryWriter bw = new BinaryWriter(fs);
  922. // bw.Write(data);
  923. // bw.Close();
  924. // fs.Close();
  925. //}
  926. private static void SaveAssetToFile(string filename, byte[] data)
  927. {
  928. string assetPath = "UserAssets";
  929. if (!Directory.Exists(assetPath))
  930. {
  931. Directory.CreateDirectory(assetPath);
  932. }
  933. FileStream fs = File.Create(Path.Combine(assetPath, filename));
  934. BinaryWriter bw = new BinaryWriter(fs);
  935. bw.Write(data);
  936. bw.Close();
  937. fs.Close();
  938. }
  939. }
  940. /// <summary>
  941. /// This class is a callback invoked when a client sends asset data to
  942. /// a task inventory script update url
  943. /// </summary>
  944. public class TaskInventoryScriptUpdater
  945. {
  946. private static readonly ILog m_log =
  947. LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  948. public event UpdateTaskScript OnUpLoad;
  949. private UpdateTaskScript handlerUpdateTaskScript = null;
  950. private string uploaderPath = String.Empty;
  951. private UUID inventoryItemID;
  952. private UUID primID;
  953. private bool isScriptRunning;
  954. private IHttpServer httpListener;
  955. private bool m_dumpAssetToFile;
  956. public TaskInventoryScriptUpdater(UUID inventoryItemID, UUID primID, int isScriptRunning,
  957. string path, IHttpServer httpServer, bool dumpAssetToFile)
  958. {
  959. m_dumpAssetToFile = dumpAssetToFile;
  960. this.inventoryItemID = inventoryItemID;
  961. this.primID = primID;
  962. // This comes in over the packet as an integer, but actually appears to be treated as a bool
  963. this.isScriptRunning = (0 == isScriptRunning ? false : true);
  964. uploaderPath = path;
  965. httpListener = httpServer;
  966. }
  967. /// <summary>
  968. ///
  969. /// </summary>
  970. /// <param name="data"></param>
  971. /// <param name="path"></param>
  972. /// <param name="param"></param>
  973. /// <returns></returns>
  974. public string uploaderCaps(byte[] data, string path, string param)
  975. {
  976. try
  977. {
  978. // m_log.InfoFormat("[CAPS]: " +
  979. // "TaskInventoryScriptUpdater received data: {0}, path: {1}, param: {2}",
  980. // data, path, param));
  981. string res = String.Empty;
  982. LLSDTaskScriptUploadComplete uploadComplete = new LLSDTaskScriptUploadComplete();
  983. ArrayList errors = new ArrayList();
  984. handlerUpdateTaskScript = OnUpLoad;
  985. if (handlerUpdateTaskScript != null)
  986. {
  987. handlerUpdateTaskScript(inventoryItemID, primID, isScriptRunning, data, ref errors);
  988. }
  989. uploadComplete.new_asset = inventoryItemID;
  990. uploadComplete.compiled = errors.Count > 0 ? false : true;
  991. uploadComplete.state = "complete";
  992. uploadComplete.errors = new OpenSim.Framework.Capabilities.OSDArray();
  993. uploadComplete.errors.Array = errors;
  994. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  995. httpListener.RemoveStreamHandler("POST", uploaderPath);
  996. if (m_dumpAssetToFile)
  997. {
  998. SaveAssetToFile("updatedtaskscript" + Util.RandomClass.Next(1, 1000) + ".dat", data);
  999. }
  1000. // m_log.InfoFormat("[CAPS]: TaskInventoryScriptUpdater.uploaderCaps res: {0}", res);
  1001. return res;
  1002. }
  1003. catch (Exception e)
  1004. {
  1005. m_log.Error("[CAPS]: " + e.ToString());
  1006. }
  1007. // XXX Maybe this should be some meaningful error packet
  1008. return null;
  1009. }
  1010. ///Left this in and commented in case there are unforseen issues
  1011. //private void SaveAssetToFile(string filename, byte[] data)
  1012. //{
  1013. // FileStream fs = File.Create(filename);
  1014. // BinaryWriter bw = new BinaryWriter(fs);
  1015. // bw.Write(data);
  1016. // bw.Close();
  1017. // fs.Close();
  1018. //}
  1019. private static void SaveAssetToFile(string filename, byte[] data)
  1020. {
  1021. string assetPath = "UserAssets";
  1022. if (!Directory.Exists(assetPath))
  1023. {
  1024. Directory.CreateDirectory(assetPath);
  1025. }
  1026. FileStream fs = File.Create(Path.Combine(assetPath, filename));
  1027. BinaryWriter bw = new BinaryWriter(fs);
  1028. bw.Write(data);
  1029. bw.Close();
  1030. fs.Close();
  1031. }
  1032. }
  1033. }