1
0

BunchOfCaps.cs 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
  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 = (sbyte)InventoryType.Sound;
  422. assType = (sbyte)AssetType.Sound;
  423. }
  424. else if (inventoryType == "snapshot")
  425. {
  426. inType = (sbyte)InventoryType.Snapshot;
  427. }
  428. else if (inventoryType == "animation")
  429. {
  430. inType = (sbyte)InventoryType.Animation;
  431. assType = (sbyte)AssetType.Animation;
  432. }
  433. else if (inventoryType == "wearable")
  434. {
  435. inType = (sbyte)InventoryType.Wearable;
  436. switch (assetType)
  437. {
  438. case "bodypart":
  439. assType = (sbyte)AssetType.Bodypart;
  440. break;
  441. case "clothing":
  442. assType = (sbyte)AssetType.Clothing;
  443. break;
  444. }
  445. }
  446. else if (inventoryType == "object")
  447. {
  448. inType = (sbyte)InventoryType.Object;
  449. assType = (sbyte)AssetType.Object;
  450. List<Vector3> positions = new List<Vector3>();
  451. List<Quaternion> rotations = new List<Quaternion>();
  452. OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
  453. OSDArray instance_list = (OSDArray)request["instance_list"];
  454. OSDArray mesh_list = (OSDArray)request["mesh_list"];
  455. OSDArray texture_list = (OSDArray)request["texture_list"];
  456. SceneObjectGroup grp = null;
  457. List<UUID> textures = new List<UUID>();
  458. for (int i = 0; i < texture_list.Count; i++)
  459. {
  460. AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, "");
  461. textureAsset.Data = texture_list[i].AsBinary();
  462. m_assetService.Store(textureAsset);
  463. textures.Add(textureAsset.FullID);
  464. }
  465. for (int i = 0; i < mesh_list.Count; i++)
  466. {
  467. PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
  468. Primitive.TextureEntry textureEntry
  469. = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
  470. OSDMap inner_instance_list = (OSDMap)instance_list[i];
  471. OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
  472. for (uint face = 0; face < face_list.Count; face++)
  473. {
  474. OSDMap faceMap = (OSDMap)face_list[(int)face];
  475. Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
  476. if(faceMap.ContainsKey("fullbright"))
  477. f.Fullbright = faceMap["fullbright"].AsBoolean();
  478. if (faceMap.ContainsKey ("diffuse_color"))
  479. f.RGBA = faceMap["diffuse_color"].AsColor4();
  480. int textureNum = faceMap["image"].AsInteger();
  481. float imagerot = faceMap["imagerot"].AsInteger();
  482. float offsets = (float)faceMap["offsets"].AsReal();
  483. float offsett = (float)faceMap["offsett"].AsReal();
  484. float scales = (float)faceMap["scales"].AsReal();
  485. float scalet = (float)faceMap["scalet"].AsReal();
  486. if(imagerot != 0)
  487. f.Rotation = imagerot;
  488. if(offsets != 0)
  489. f.OffsetU = offsets;
  490. if (offsett != 0)
  491. f.OffsetV = offsett;
  492. if (scales != 0)
  493. f.RepeatU = scales;
  494. if (scalet != 0)
  495. f.RepeatV = scalet;
  496. if (textures.Count > textureNum)
  497. f.TextureID = textures[textureNum];
  498. else
  499. f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
  500. textureEntry.FaceTextures[face] = f;
  501. }
  502. pbs.TextureEntry = textureEntry.GetBytes();
  503. AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, "");
  504. meshAsset.Data = mesh_list[i].AsBinary();
  505. m_assetService.Store(meshAsset);
  506. pbs.SculptEntry = true;
  507. pbs.SculptTexture = meshAsset.FullID;
  508. pbs.SculptType = (byte)SculptType.Mesh;
  509. pbs.SculptData = meshAsset.Data;
  510. Vector3 position = inner_instance_list["position"].AsVector3();
  511. Vector3 scale = inner_instance_list["scale"].AsVector3();
  512. Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
  513. // no longer used - begin ------------------------
  514. // int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
  515. // int material = inner_instance_list["material"].AsInteger();
  516. // int mesh = inner_instance_list["mesh"].AsInteger();
  517. // OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
  518. // int base_mask = permissions["base_mask"].AsInteger();
  519. // int everyone_mask = permissions["everyone_mask"].AsInteger();
  520. // UUID creator_id = permissions["creator_id"].AsUUID();
  521. // UUID group_id = permissions["group_id"].AsUUID();
  522. // int group_mask = permissions["group_mask"].AsInteger();
  523. // bool is_owner_group = permissions["is_owner_group"].AsBoolean();
  524. // UUID last_owner_id = permissions["last_owner_id"].AsUUID();
  525. // int next_owner_mask = permissions["next_owner_mask"].AsInteger();
  526. // UUID owner_id = permissions["owner_id"].AsUUID();
  527. // int owner_mask = permissions["owner_mask"].AsInteger();
  528. // no longer used - end ------------------------
  529. UUID owner_id = m_HostCapsObj.AgentID;
  530. SceneObjectPart prim
  531. = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
  532. prim.Scale = scale;
  533. //prim.OffsetPosition = position;
  534. rotations.Add(rotation);
  535. positions.Add(position);
  536. prim.UUID = UUID.Random();
  537. prim.CreatorID = owner_id;
  538. prim.OwnerID = owner_id;
  539. prim.GroupID = UUID.Zero;
  540. prim.LastOwnerID = prim.OwnerID;
  541. prim.CreationDate = Util.UnixTimeSinceEpoch();
  542. prim.Name = assetName;
  543. prim.Description = "";
  544. // prim.BaseMask = (uint)base_mask;
  545. // prim.EveryoneMask = (uint)everyone_mask;
  546. // prim.GroupMask = (uint)group_mask;
  547. // prim.NextOwnerMask = (uint)next_owner_mask;
  548. // prim.OwnerMask = (uint)owner_mask;
  549. if (grp == null)
  550. grp = new SceneObjectGroup(prim);
  551. else
  552. grp.AddPart(prim);
  553. }
  554. Vector3 rootPos = positions[0];
  555. if (grp.Parts.Length > 1)
  556. {
  557. // Fix first link number
  558. grp.RootPart.LinkNum++;
  559. Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
  560. Quaternion tmprot;
  561. Vector3 offset;
  562. // fix children rotations and positions
  563. for (int i = 1; i < rotations.Count; i++)
  564. {
  565. tmprot = rotations[i];
  566. tmprot = rootRotConj * tmprot;
  567. grp.Parts[i].RotationOffset = tmprot;
  568. offset = positions[i] - rootPos;
  569. offset *= rootRotConj;
  570. grp.Parts[i].OffsetPosition = offset;
  571. }
  572. grp.AbsolutePosition = rootPos;
  573. grp.UpdateGroupRotationR(rotations[0]);
  574. }
  575. else
  576. {
  577. grp.AbsolutePosition = rootPos;
  578. grp.UpdateGroupRotationR(rotations[0]);
  579. }
  580. data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
  581. }
  582. AssetBase asset;
  583. asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString());
  584. asset.Data = data;
  585. if (AddNewAsset != null)
  586. AddNewAsset(asset);
  587. else if (m_assetService != null)
  588. m_assetService.Store(asset);
  589. InventoryItemBase item = new InventoryItemBase();
  590. item.Owner = m_HostCapsObj.AgentID;
  591. item.CreatorId = m_HostCapsObj.AgentID.ToString();
  592. item.CreatorData = String.Empty;
  593. item.ID = inventoryItem;
  594. item.AssetID = asset.FullID;
  595. item.Description = assetDescription;
  596. item.Name = assetName;
  597. item.AssetType = assType;
  598. item.InvType = inType;
  599. item.Folder = parentFolder;
  600. // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
  601. // (owner) permissions. This becomes a problem if next permissions are changed.
  602. item.CurrentPermissions
  603. = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
  604. item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
  605. item.EveryOnePermissions = 0;
  606. item.NextPermissions = (uint)PermissionMask.All;
  607. item.CreationDate = Util.UnixTimeSinceEpoch();
  608. if (AddNewInventoryItem != null)
  609. {
  610. AddNewInventoryItem(m_HostCapsObj.AgentID, item);
  611. }
  612. }
  613. /// <summary>
  614. ///
  615. /// </summary>
  616. /// <param name="mapReq"></param>
  617. /// <returns></returns>
  618. public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq)
  619. {
  620. m_log.Debug("[CAPS]: MapLayer Request in region: " + m_regionName);
  621. LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
  622. mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
  623. return mapResponse;
  624. }
  625. /// <summary>
  626. ///
  627. /// </summary>
  628. /// <returns></returns>
  629. protected static OSDMapLayer GetOSDMapLayerResponse()
  630. {
  631. OSDMapLayer mapLayer = new OSDMapLayer();
  632. mapLayer.Right = 5000;
  633. mapLayer.Top = 5000;
  634. mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
  635. return mapLayer;
  636. }
  637. /// <summary>
  638. ///
  639. /// </summary>
  640. /// <param name="request"></param>
  641. /// <param name="path"></param>
  642. /// <param name="param"></param>
  643. /// <returns></returns>
  644. public string RequestTexture(string request, string path, string param)
  645. {
  646. m_log.Debug("texture request " + request);
  647. // Needs implementing (added to remove compiler warning)
  648. return String.Empty;
  649. }
  650. /// <summary>
  651. /// Called by the notecard update handler. Provides a URL to which the client can upload a new asset.
  652. /// </summary>
  653. /// <param name="request"></param>
  654. /// <param name="path"></param>
  655. /// <param name="param"></param>
  656. /// <returns></returns>
  657. public string NoteCardAgentInventory(string request, string path, string param,
  658. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  659. {
  660. //m_log.Debug("[CAPS]: NoteCardAgentInventory Request in region: " + m_regionName + "\n" + request);
  661. //m_log.Debug("[CAPS]: NoteCardAgentInventory Request is: " + request);
  662. //OpenMetaverse.StructuredData.OSDMap hash = (OpenMetaverse.StructuredData.OSDMap)OpenMetaverse.StructuredData.LLSDParser.DeserializeBinary(Utils.StringToBytes(request));
  663. Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
  664. LLSDItemUpdate llsdRequest = new LLSDItemUpdate();
  665. LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest);
  666. string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
  667. string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
  668. ItemUpdater uploader =
  669. new ItemUpdater(llsdRequest.item_id, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile);
  670. uploader.OnUpLoad += ItemUpdated;
  671. m_HostCapsObj.HttpListener.AddStreamHandler(
  672. new BinaryStreamHandler(
  673. "POST", capsBase + uploaderPath, uploader.uploaderCaps, "NoteCardAgentInventory", null));
  674. string protocol = "http://";
  675. if (m_HostCapsObj.SSLCaps)
  676. protocol = "https://";
  677. string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
  678. uploaderPath;
  679. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  680. uploadResponse.uploader = uploaderURL;
  681. uploadResponse.state = "upload";
  682. // m_log.InfoFormat("[CAPS]: " +
  683. // "NoteCardAgentInventory response: {0}",
  684. // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
  685. return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
  686. }
  687. /// <summary>
  688. /// Called by the CopyInventoryFromNotecard caps handler.
  689. /// </summary>
  690. /// <param name="request"></param>
  691. /// <param name="path"></param>
  692. /// <param name="param"></param>
  693. public string CopyInventoryFromNotecard(string request, string path, string param,
  694. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  695. {
  696. Hashtable response = new Hashtable();
  697. response["int_response_code"] = 404;
  698. response["content_type"] = "text/plain";
  699. response["keepalive"] = false;
  700. response["str_response_string"] = "";
  701. try
  702. {
  703. OSDMap content = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  704. UUID objectID = content["object-id"].AsUUID();
  705. UUID notecardID = content["notecard-id"].AsUUID();
  706. UUID folderID = content["folder-id"].AsUUID();
  707. UUID itemID = content["item-id"].AsUUID();
  708. // m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, FolderID:{0}, ItemID:{1}, NotecardID:{2}, ObjectID:{3}", folderID, itemID, notecardID, objectID);
  709. if (objectID != UUID.Zero)
  710. {
  711. SceneObjectPart part = m_Scene.GetSceneObjectPart(objectID);
  712. if (part != null)
  713. {
  714. // TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(notecardID);
  715. if (!m_Scene.Permissions.CanCopyObjectInventory(notecardID, objectID, m_HostCapsObj.AgentID))
  716. {
  717. return LLSDHelpers.SerialiseLLSDReply(response);
  718. }
  719. }
  720. }
  721. InventoryItemBase item = null;
  722. InventoryItemBase copyItem = null;
  723. IClientAPI client = null;
  724. m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
  725. item = m_Scene.InventoryService.GetItem(new InventoryItemBase(itemID));
  726. if (item != null)
  727. {
  728. copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID);
  729. if (copyItem != null && client != null)
  730. {
  731. m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder);
  732. client.SendBulkUpdateInventory(copyItem);
  733. }
  734. }
  735. else
  736. {
  737. m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID);
  738. if (client != null)
  739. client.SendAlertMessage("Failed to retrieve item");
  740. }
  741. }
  742. catch (Exception e)
  743. {
  744. m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard : {0}", e.ToString());
  745. }
  746. response["int_response_code"] = 200;
  747. return LLSDHelpers.SerialiseLLSDReply(response);
  748. }
  749. public string GetObjectPhysicsData(string request, string path,
  750. string param, IOSHttpRequest httpRequest,
  751. IOSHttpResponse httpResponse)
  752. {
  753. OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  754. OSDMap resp = new OSDMap();
  755. OSDArray object_ids = (OSDArray)req["object_ids"];
  756. for (int i = 0 ; i < object_ids.Count ; i++)
  757. {
  758. UUID uuid = object_ids[i].AsUUID();
  759. SceneObjectPart obj = m_Scene.GetSceneObjectPart(uuid);
  760. if (obj != null)
  761. {
  762. OSDMap object_data = new OSDMap();
  763. object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
  764. object_data["Density"] = obj.Density;
  765. object_data["Friction"] = obj.Friction;
  766. object_data["Restitution"] = obj.Restitution;
  767. object_data["GravityMultiplier"] = obj.GravityModifier;
  768. resp[uuid.ToString()] = object_data;
  769. }
  770. }
  771. string response = OSDParser.SerializeLLSDXmlString(resp);
  772. return response;
  773. }
  774. public string UpdateAgentInformation(string request, string path,
  775. string param, IOSHttpRequest httpRequest,
  776. IOSHttpResponse httpResponse)
  777. {
  778. // OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  779. OSDMap resp = new OSDMap();
  780. OSDMap accessPrefs = new OSDMap();
  781. accessPrefs["max"] = "A";
  782. resp["access_prefs"] = accessPrefs;
  783. string response = OSDParser.SerializeLLSDXmlString(resp);
  784. return response;
  785. }
  786. }
  787. public class AssetUploader
  788. {
  789. public event UpLoadedAsset OnUpLoad;
  790. private UpLoadedAsset handlerUpLoad = null;
  791. private string uploaderPath = String.Empty;
  792. private UUID newAssetID;
  793. private UUID inventoryItemID;
  794. private UUID parentFolder;
  795. private IHttpServer httpListener;
  796. private bool m_dumpAssetsToFile;
  797. private string m_assetName = String.Empty;
  798. private string m_assetDes = String.Empty;
  799. private string m_invType = String.Empty;
  800. private string m_assetType = String.Empty;
  801. public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
  802. UUID parentFolderID, string invType, string assetType, string path,
  803. IHttpServer httpServer, bool dumpAssetsToFile)
  804. {
  805. m_assetName = assetName;
  806. m_assetDes = description;
  807. newAssetID = assetID;
  808. inventoryItemID = inventoryItem;
  809. uploaderPath = path;
  810. httpListener = httpServer;
  811. parentFolder = parentFolderID;
  812. m_assetType = assetType;
  813. m_invType = invType;
  814. m_dumpAssetsToFile = dumpAssetsToFile;
  815. }
  816. /// <summary>
  817. /// Handle raw asset upload data via the capability.
  818. /// </summary>
  819. /// <param name="data"></param>
  820. /// <param name="path"></param>
  821. /// <param name="param"></param>
  822. /// <returns></returns>
  823. public string uploaderCaps(byte[] data, string path, string param)
  824. {
  825. UUID inv = inventoryItemID;
  826. string res = String.Empty;
  827. LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
  828. uploadComplete.new_asset = newAssetID.ToString();
  829. uploadComplete.new_inventory_item = inv;
  830. uploadComplete.state = "complete";
  831. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  832. httpListener.RemoveStreamHandler("POST", uploaderPath);
  833. // TODO: probably make this a better set of extensions here
  834. string extension = ".jp2";
  835. if (m_invType != "image")
  836. {
  837. extension = ".dat";
  838. }
  839. if (m_dumpAssetsToFile)
  840. {
  841. SaveAssetToFile(m_assetName + extension, data);
  842. }
  843. handlerUpLoad = OnUpLoad;
  844. if (handlerUpLoad != null)
  845. {
  846. handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType);
  847. }
  848. return res;
  849. }
  850. ///Left this in and commented in case there are unforseen issues
  851. //private void SaveAssetToFile(string filename, byte[] data)
  852. //{
  853. // FileStream fs = File.Create(filename);
  854. // BinaryWriter bw = new BinaryWriter(fs);
  855. // bw.Write(data);
  856. // bw.Close();
  857. // fs.Close();
  858. //}
  859. private static void SaveAssetToFile(string filename, byte[] data)
  860. {
  861. string assetPath = "UserAssets";
  862. if (!Directory.Exists(assetPath))
  863. {
  864. Directory.CreateDirectory(assetPath);
  865. }
  866. FileStream fs = File.Create(Path.Combine(assetPath, Util.safeFileName(filename)));
  867. BinaryWriter bw = new BinaryWriter(fs);
  868. bw.Write(data);
  869. bw.Close();
  870. fs.Close();
  871. }
  872. }
  873. /// <summary>
  874. /// This class is a callback invoked when a client sends asset data to
  875. /// an agent inventory notecard update url
  876. /// </summary>
  877. public class ItemUpdater
  878. {
  879. public event UpdateItem OnUpLoad;
  880. private UpdateItem handlerUpdateItem = null;
  881. private string uploaderPath = String.Empty;
  882. private UUID inventoryItemID;
  883. private IHttpServer httpListener;
  884. private bool m_dumpAssetToFile;
  885. public ItemUpdater(UUID inventoryItem, string path, IHttpServer httpServer, bool dumpAssetToFile)
  886. {
  887. m_dumpAssetToFile = dumpAssetToFile;
  888. inventoryItemID = inventoryItem;
  889. uploaderPath = path;
  890. httpListener = httpServer;
  891. }
  892. /// <summary>
  893. /// Handle raw uploaded asset data.
  894. /// </summary>
  895. /// <param name="data"></param>
  896. /// <param name="path"></param>
  897. /// <param name="param"></param>
  898. /// <returns></returns>
  899. public string uploaderCaps(byte[] data, string path, string param)
  900. {
  901. UUID inv = inventoryItemID;
  902. string res = String.Empty;
  903. LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
  904. UUID assetID = UUID.Zero;
  905. handlerUpdateItem = OnUpLoad;
  906. if (handlerUpdateItem != null)
  907. {
  908. assetID = handlerUpdateItem(inv, data);
  909. }
  910. uploadComplete.new_asset = assetID.ToString();
  911. uploadComplete.new_inventory_item = inv;
  912. uploadComplete.state = "complete";
  913. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  914. httpListener.RemoveStreamHandler("POST", uploaderPath);
  915. if (m_dumpAssetToFile)
  916. {
  917. SaveAssetToFile("updateditem" + Util.RandomClass.Next(1, 1000) + ".dat", data);
  918. }
  919. return res;
  920. }
  921. ///Left this in and commented in case there are unforseen issues
  922. //private void SaveAssetToFile(string filename, byte[] data)
  923. //{
  924. // FileStream fs = File.Create(filename);
  925. // BinaryWriter bw = new BinaryWriter(fs);
  926. // bw.Write(data);
  927. // bw.Close();
  928. // fs.Close();
  929. //}
  930. private static void SaveAssetToFile(string filename, byte[] data)
  931. {
  932. string assetPath = "UserAssets";
  933. if (!Directory.Exists(assetPath))
  934. {
  935. Directory.CreateDirectory(assetPath);
  936. }
  937. FileStream fs = File.Create(Path.Combine(assetPath, filename));
  938. BinaryWriter bw = new BinaryWriter(fs);
  939. bw.Write(data);
  940. bw.Close();
  941. fs.Close();
  942. }
  943. }
  944. /// <summary>
  945. /// This class is a callback invoked when a client sends asset data to
  946. /// a task inventory script update url
  947. /// </summary>
  948. public class TaskInventoryScriptUpdater
  949. {
  950. private static readonly ILog m_log =
  951. LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  952. public event UpdateTaskScript OnUpLoad;
  953. private UpdateTaskScript handlerUpdateTaskScript = null;
  954. private string uploaderPath = String.Empty;
  955. private UUID inventoryItemID;
  956. private UUID primID;
  957. private bool isScriptRunning;
  958. private IHttpServer httpListener;
  959. private bool m_dumpAssetToFile;
  960. public TaskInventoryScriptUpdater(UUID inventoryItemID, UUID primID, int isScriptRunning,
  961. string path, IHttpServer httpServer, bool dumpAssetToFile)
  962. {
  963. m_dumpAssetToFile = dumpAssetToFile;
  964. this.inventoryItemID = inventoryItemID;
  965. this.primID = primID;
  966. // This comes in over the packet as an integer, but actually appears to be treated as a bool
  967. this.isScriptRunning = (0 == isScriptRunning ? false : true);
  968. uploaderPath = path;
  969. httpListener = httpServer;
  970. }
  971. /// <summary>
  972. ///
  973. /// </summary>
  974. /// <param name="data"></param>
  975. /// <param name="path"></param>
  976. /// <param name="param"></param>
  977. /// <returns></returns>
  978. public string uploaderCaps(byte[] data, string path, string param)
  979. {
  980. try
  981. {
  982. // m_log.InfoFormat("[CAPS]: " +
  983. // "TaskInventoryScriptUpdater received data: {0}, path: {1}, param: {2}",
  984. // data, path, param));
  985. string res = String.Empty;
  986. LLSDTaskScriptUploadComplete uploadComplete = new LLSDTaskScriptUploadComplete();
  987. ArrayList errors = new ArrayList();
  988. handlerUpdateTaskScript = OnUpLoad;
  989. if (handlerUpdateTaskScript != null)
  990. {
  991. handlerUpdateTaskScript(inventoryItemID, primID, isScriptRunning, data, ref errors);
  992. }
  993. uploadComplete.new_asset = inventoryItemID;
  994. uploadComplete.compiled = errors.Count > 0 ? false : true;
  995. uploadComplete.state = "complete";
  996. uploadComplete.errors = new OpenSim.Framework.Capabilities.OSDArray();
  997. uploadComplete.errors.Array = errors;
  998. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  999. httpListener.RemoveStreamHandler("POST", uploaderPath);
  1000. if (m_dumpAssetToFile)
  1001. {
  1002. SaveAssetToFile("updatedtaskscript" + Util.RandomClass.Next(1, 1000) + ".dat", data);
  1003. }
  1004. // m_log.InfoFormat("[CAPS]: TaskInventoryScriptUpdater.uploaderCaps res: {0}", res);
  1005. return res;
  1006. }
  1007. catch (Exception e)
  1008. {
  1009. m_log.Error("[CAPS]: " + e.ToString());
  1010. }
  1011. // XXX Maybe this should be some meaningful error packet
  1012. return null;
  1013. }
  1014. ///Left this in and commented in case there are unforseen issues
  1015. //private void SaveAssetToFile(string filename, byte[] data)
  1016. //{
  1017. // FileStream fs = File.Create(filename);
  1018. // BinaryWriter bw = new BinaryWriter(fs);
  1019. // bw.Write(data);
  1020. // bw.Close();
  1021. // fs.Close();
  1022. //}
  1023. private static void SaveAssetToFile(string filename, byte[] data)
  1024. {
  1025. string assetPath = "UserAssets";
  1026. if (!Directory.Exists(assetPath))
  1027. {
  1028. Directory.CreateDirectory(assetPath);
  1029. }
  1030. FileStream fs = File.Create(Path.Combine(assetPath, filename));
  1031. BinaryWriter bw = new BinaryWriter(fs);
  1032. bw.Write(data);
  1033. bw.Close();
  1034. fs.Close();
  1035. }
  1036. }
  1037. }