Caps.cs 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  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 log4net;
  33. using OpenMetaverse;
  34. using OpenSim.Framework.Servers;
  35. using OpenSim.Framework.Servers.HttpServer;
  36. using OpenSim.Services.Interfaces;
  37. // using OpenSim.Region.Framework.Interfaces;
  38. namespace OpenSim.Framework.Capabilities
  39. {
  40. public delegate void UpLoadedAsset(
  41. string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
  42. byte[] data, string inventoryType, string assetType);
  43. public delegate UUID UpdateItem(UUID itemID, byte[] data);
  44. public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data);
  45. public delegate void NewInventoryItem(UUID userID, InventoryItemBase item);
  46. public delegate void NewAsset(AssetBase asset);
  47. public delegate UUID ItemUpdatedCallback(UUID userID, UUID itemID, byte[] data);
  48. public delegate void TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID,
  49. bool isScriptRunning, byte[] data);
  50. public delegate List<InventoryItemBase> FetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID,
  51. bool fetchFolders, bool fetchItems, int sortOrder);
  52. /// <summary>
  53. /// XXX Probably not a particularly nice way of allow us to get the scene presence from the scene (chiefly so that
  54. /// we can popup a message on the user's client if the inventory service has permanently failed). But I didn't want
  55. /// to just pass the whole Scene into CAPS.
  56. /// </summary>
  57. public delegate IClientAPI GetClientDelegate(UUID agentID);
  58. public class Caps
  59. {
  60. private static readonly ILog m_log =
  61. LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  62. private string m_httpListenerHostName;
  63. private uint m_httpListenPort;
  64. /// <summary>
  65. /// This is the uuid portion of every CAPS path. It is used to make capability urls private to the requester.
  66. /// </summary>
  67. private string m_capsObjectPath;
  68. public string CapsObjectPath { get { return m_capsObjectPath; } }
  69. private CapsHandlers m_capsHandlers;
  70. private static readonly string m_requestPath = "0000/";
  71. // private static readonly string m_mapLayerPath = "0001/";
  72. private static readonly string m_newInventory = "0002/";
  73. //private static readonly string m_requestTexture = "0003/";
  74. private static readonly string m_notecardUpdatePath = "0004/";
  75. private static readonly string m_notecardTaskUpdatePath = "0005/";
  76. // private static readonly string m_fetchInventoryPath = "0006/";
  77. // The following entries are in a module, however, they are also here so that we don't re-assign
  78. // the path to another cap by mistake.
  79. // private static readonly string m_parcelVoiceInfoRequestPath = "0007/"; // This is in a module.
  80. // private static readonly string m_provisionVoiceAccountRequestPath = "0008/";// This is in a module.
  81. // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
  82. //private string eventQueue = "0100/";
  83. private IHttpServer m_httpListener;
  84. private UUID m_agentID;
  85. private IAssetService m_assetCache;
  86. private int m_eventQueueCount = 1;
  87. private Queue<string> m_capsEventQueue = new Queue<string>();
  88. private bool m_dumpAssetsToFile;
  89. private string m_regionName;
  90. public bool SSLCaps
  91. {
  92. get { return m_httpListener.UseSSL; }
  93. }
  94. public string SSLCommonName
  95. {
  96. get { return m_httpListener.SSLCommonName; }
  97. }
  98. public CapsHandlers CapsHandlers
  99. {
  100. get { return m_capsHandlers; }
  101. }
  102. // These are callbacks which will be setup by the scene so that we can update scene data when we
  103. // receive capability calls
  104. public NewInventoryItem AddNewInventoryItem = null;
  105. public NewAsset AddNewAsset = null;
  106. public ItemUpdatedCallback ItemUpdatedCall = null;
  107. public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null;
  108. public FetchInventoryDescendentsCAPS CAPSFetchInventoryDescendents = null;
  109. public GetClientDelegate GetClient = null;
  110. public Caps(IAssetService assetCache, IHttpServer httpServer, string httpListen, uint httpPort, string capsPath,
  111. UUID agent, bool dumpAssetsToFile, string regionName)
  112. {
  113. m_assetCache = assetCache;
  114. m_capsObjectPath = capsPath;
  115. m_httpListener = httpServer;
  116. m_httpListenerHostName = httpListen;
  117. m_httpListenPort = httpPort;
  118. if (httpServer.UseSSL)
  119. {
  120. m_httpListenPort = httpServer.SSLPort;
  121. httpListen = httpServer.SSLCommonName;
  122. httpPort = httpServer.SSLPort;
  123. }
  124. m_agentID = agent;
  125. m_dumpAssetsToFile = dumpAssetsToFile;
  126. m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, httpServer.UseSSL);
  127. m_regionName = regionName;
  128. }
  129. /// <summary>
  130. /// Register all CAPS http service handlers
  131. /// </summary>
  132. public void RegisterHandlers()
  133. {
  134. DeregisterHandlers();
  135. string capsBase = "/CAPS/" + m_capsObjectPath;
  136. RegisterRegionServiceHandlers(capsBase);
  137. RegisterInventoryServiceHandlers(capsBase);
  138. }
  139. public void RegisterRegionServiceHandlers(string capsBase)
  140. {
  141. try
  142. {
  143. // the root of all evil
  144. m_capsHandlers["SEED"] = new RestStreamHandler("POST", capsBase + m_requestPath, CapsRequest);
  145. m_log.DebugFormat(
  146. "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_agentID);
  147. //m_capsHandlers["MapLayer"] =
  148. // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
  149. // capsBase + m_mapLayerPath,
  150. // GetMapLayer);
  151. m_capsHandlers["UpdateScriptTaskInventory"] =
  152. new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory);
  153. m_capsHandlers["UpdateScriptTask"] = m_capsHandlers["UpdateScriptTaskInventory"];
  154. }
  155. catch (Exception e)
  156. {
  157. m_log.Error("[CAPS]: " + e.ToString());
  158. }
  159. }
  160. public void RegisterInventoryServiceHandlers(string capsBase)
  161. {
  162. try
  163. {
  164. // I don't think this one works...
  165. m_capsHandlers["NewFileAgentInventory"] =
  166. new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>("POST",
  167. capsBase + m_newInventory,
  168. NewAgentInventoryRequest);
  169. m_capsHandlers["UpdateNotecardAgentInventory"] =
  170. new RestStreamHandler("POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory);
  171. m_capsHandlers["UpdateScriptAgentInventory"] = m_capsHandlers["UpdateNotecardAgentInventory"];
  172. m_capsHandlers["UpdateScriptAgent"] = m_capsHandlers["UpdateScriptAgentInventory"];
  173. // As of RC 1.22.9 of the Linden client this is
  174. // supported
  175. // m_capsHandlers["WebFetchInventoryDescendents"] =new RestStreamHandler("POST", capsBase + m_fetchInventoryPath, FetchInventoryDescendentsRequest);
  176. // justincc: I've disabled the CAPS service for now to fix problems with selecting textures, and
  177. // subsequent inventory breakage, in the edit object pane (such as mantis 1085). This requires
  178. // enhancements (probably filling out the folder part of the LLSD reply) to our CAPS service,
  179. // but when I went on the Linden grid, the
  180. // simulators I visited (version 1.21) were, surprisingly, no longer supplying this capability. Instead,
  181. // the 1.19.1.4 client appeared to be happily flowing inventory data over UDP
  182. //
  183. // This is very probably just a temporary measure - once the CAPS service appears again on the Linden grid
  184. // we will be
  185. // able to get the data we need to implement the necessary part of the protocol to fix the issue above.
  186. // m_capsHandlers["FetchInventoryDescendents"] =
  187. // new RestStreamHandler("POST", capsBase + m_fetchInventoryPath, FetchInventoryRequest);
  188. // m_capsHandlers["FetchInventoryDescendents"] =
  189. // new LLSDStreamhandler<LLSDFetchInventoryDescendents, LLSDInventoryDescendents>("POST",
  190. // capsBase + m_fetchInventory,
  191. // FetchInventory));
  192. // m_capsHandlers["RequestTextureDownload"] = new RestStreamHandler("POST",
  193. // capsBase + m_requestTexture,
  194. // RequestTexture);
  195. }
  196. catch (Exception e)
  197. {
  198. m_log.Error("[CAPS]: " + e.ToString());
  199. }
  200. }
  201. /// <summary>
  202. /// Register a handler. This allows modules to register handlers.
  203. /// </summary>
  204. /// <param name="capName"></param>
  205. /// <param name="handler"></param>
  206. public void RegisterHandler(string capName, IRequestHandler handler)
  207. {
  208. m_capsHandlers[capName] = handler;
  209. //m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path);
  210. }
  211. /// <summary>
  212. /// Remove all CAPS service handlers.
  213. ///
  214. /// </summary>
  215. /// <param name="httpListener"></param>
  216. /// <param name="path"></param>
  217. /// <param name="restMethod"></param>
  218. public void DeregisterHandlers()
  219. {
  220. if (m_capsHandlers != null)
  221. {
  222. foreach (string capsName in m_capsHandlers.Caps)
  223. {
  224. m_capsHandlers.Remove(capsName);
  225. }
  226. }
  227. }
  228. /// <summary>
  229. /// Construct a client response detailing all the capabilities this server can provide.
  230. /// </summary>
  231. /// <param name="request"></param>
  232. /// <param name="path"></param>
  233. /// <param name="param"></param>
  234. /// <param name="httpRequest">HTTP request header object</param>
  235. /// <param name="httpResponse">HTTP response header object</param>
  236. /// <returns></returns>
  237. public string CapsRequest(string request, string path, string param,
  238. OSHttpRequest httpRequest, OSHttpResponse httpResponse)
  239. {
  240. //m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName);
  241. string result = LLSDHelpers.SerialiseLLSDReply(m_capsHandlers.CapsDetails);
  242. //m_log.DebugFormat("[CAPS] CapsRequest {0}", result);
  243. return result;
  244. }
  245. // FIXME: these all should probably go into the respective region
  246. // modules
  247. /// <summary>
  248. /// Processes a fetch inventory request and sends the reply
  249. /// </summary>
  250. /// <param name="request"></param>
  251. /// <param name="path"></param>
  252. /// <param name="param"></param>
  253. /// <returns></returns>
  254. // Request is like:
  255. //<llsd>
  256. // <map><key>folders</key>
  257. // <array>
  258. // <map>
  259. // <key>fetch-folders</key><boolean>1</boolean><key>fetch-items</key><boolean>1</boolean><key>folder-id</key><uuid>8e1e3a30-b9bf-11dc-95ff-0800200c9a66</uuid><key>owner-id</key><uuid>11111111-1111-0000-0000-000100bba000</uuid><key>sort-order</key><integer>1</integer>
  260. // </map>
  261. // </array>
  262. // </map>
  263. //</llsd>
  264. //
  265. // multiple fetch-folder maps are allowed within the larger folders map.
  266. public string FetchInventoryRequest(string request, string path, string param)
  267. {
  268. // string unmodifiedRequest = request.ToString();
  269. //m_log.DebugFormat("[AGENT INVENTORY]: Received CAPS fetch inventory request {0}", unmodifiedRequest);
  270. m_log.Debug("[CAPS]: Inventory Request in region: " + m_regionName);
  271. Hashtable hash = new Hashtable();
  272. try
  273. {
  274. hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
  275. }
  276. catch (LLSD.LLSDParseException pe)
  277. {
  278. m_log.Error("[AGENT INVENTORY]: Fetch error: " + pe.Message);
  279. m_log.Error("Request: " + request.ToString());
  280. }
  281. ArrayList foldersrequested = (ArrayList)hash["folders"];
  282. string response = "";
  283. for (int i = 0; i < foldersrequested.Count; i++)
  284. {
  285. string inventoryitemstr = "";
  286. Hashtable inventoryhash = (Hashtable)foldersrequested[i];
  287. LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
  288. LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
  289. LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
  290. inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
  291. inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
  292. inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
  293. response += inventoryitemstr;
  294. }
  295. if (response.Length == 0)
  296. {
  297. // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants.
  298. // Therefore, I'm concluding that the client only has so many threads available to do requests
  299. // and when a thread stalls.. is stays stalled.
  300. // Therefore we need to return something valid
  301. response = "<llsd><map><key>folders</key><array /></map></llsd>";
  302. }
  303. else
  304. {
  305. response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
  306. }
  307. //m_log.DebugFormat("[AGENT INVENTORY]: Replying to CAPS fetch inventory request with following xml");
  308. //m_log.Debug(Util.GetFormattedXml(response));
  309. return response;
  310. }
  311. public string FetchInventoryDescendentsRequest(string request, string path, string param,OSHttpRequest httpRequest, OSHttpResponse httpResponse)
  312. {
  313. // m_log.Debug("[CAPS]: FetchInventoryDescendentsRequest in region: " + m_regionName + "request is "+request);
  314. // nasty temporary hack here, the linden client falsely identifies the uuid 00000000-0000-0000-0000-000000000000 as a string which breaks us
  315. // correctly mark it as a uuid
  316. request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
  317. // another hack <integer>1</integer> results in a System.ArgumentException: Object type System.Int32 cannot be converted to target type: System.Boolean
  318. request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
  319. request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
  320. Hashtable hash = new Hashtable();
  321. try
  322. {
  323. hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
  324. }
  325. catch (LLSD.LLSDParseException pe)
  326. {
  327. m_log.Error("[AGENT INVENTORY]: Fetch error: " + pe.Message);
  328. m_log.Error("Request: " + request.ToString());
  329. }
  330. ArrayList foldersrequested = (ArrayList)hash["folders"];
  331. string response = "";
  332. for (int i = 0; i < foldersrequested.Count; i++)
  333. {
  334. string inventoryitemstr = "";
  335. Hashtable inventoryhash = (Hashtable)foldersrequested[i];
  336. LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
  337. try{
  338. LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
  339. }
  340. catch(Exception e)
  341. {
  342. m_log.Debug("[CAPS]: caught exception doing OSD deserialize" + e);
  343. }
  344. LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
  345. inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
  346. inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
  347. inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
  348. response += inventoryitemstr;
  349. }
  350. if (response.Length == 0)
  351. {
  352. // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants.
  353. // Therefore, I'm concluding that the client only has so many threads available to do requests
  354. // and when a thread stalls.. is stays stalled.
  355. // Therefore we need to return something valid
  356. response = "<llsd><map><key>folders</key><array /></map></llsd>";
  357. }
  358. else
  359. {
  360. response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
  361. }
  362. //m_log.DebugFormat("[CAPS]: Replying to CAPS fetch inventory request with following xml");
  363. //m_log.Debug("[CAPS] "+response);
  364. return response;
  365. }
  366. /// <summary>
  367. /// Construct an LLSD reply packet to a CAPS inventory request
  368. /// </summary>
  369. /// <param name="invFetch"></param>
  370. /// <returns></returns>
  371. private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
  372. {
  373. LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
  374. LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
  375. contents.agent_id = m_agentID;
  376. contents.owner_id = invFetch.owner_id;
  377. contents.folder_id = invFetch.folder_id;
  378. // The version number being sent back was originally 1.
  379. // Unfortunately, on 1.19.1.4, this means that we see a problem where on subsequent logins
  380. // without clearing client cache, objects in the root folder disappear until the cache is cleared,
  381. // at which point they reappear.
  382. //
  383. // Seeing the version to something other than 0 may be the right thing to do, but there is
  384. // a greater subtlety of the second life protocol that needs to be understood first.
  385. contents.version = 0;
  386. contents.descendents = 0;
  387. reply.folders.Array.Add(contents);
  388. List<InventoryItemBase> itemList = null;
  389. if (CAPSFetchInventoryDescendents != null)
  390. {
  391. itemList = CAPSFetchInventoryDescendents(m_agentID, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order);
  392. }
  393. if (itemList != null)
  394. {
  395. foreach (InventoryItemBase invItem in itemList)
  396. {
  397. contents.items.Array.Add(ConvertInventoryItem(invItem));
  398. }
  399. }
  400. /* The following block is removed as it ALWAYS sends the error to the client because the RC 1.22.9 client tries to
  401. find items that have become dissasociated with a paret folder and have parent of 00000000-0000-00000....
  402. else
  403. {
  404. IClientAPI client = GetClient(m_agentID);
  405. // We're going to both notify the client of inventory service failure and send back a 'no folder contents' response.
  406. // If we don't send back the response,
  407. // the client becomes unhappy (see Teravus' comment in FetchInventoryRequest())
  408. if (client != null)
  409. {
  410. client.SendAgentAlertMessage(
  411. "AGIN0001E: The inventory service has either failed or is not responding. Your inventory will not function properly for the rest of this session. Please clear your cache and relog.",
  412. true);
  413. }
  414. else
  415. {
  416. m_log.ErrorFormat(
  417. "[AGENT INVENTORY]: Could not lookup controlling client for {0} in order to notify them of the inventory service failure",
  418. m_agentID);
  419. }
  420. }*/
  421. contents.descendents = contents.items.Array.Count;
  422. return reply;
  423. }
  424. /// <summary>
  425. /// Convert an internal inventory item object into an LLSD object.
  426. /// </summary>
  427. /// <param name="invItem"></param>
  428. /// <returns></returns>
  429. private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
  430. {
  431. LLSDInventoryItem llsdItem = new LLSDInventoryItem();
  432. llsdItem.asset_id = invItem.AssetID;
  433. llsdItem.created_at = invItem.CreationDate;
  434. llsdItem.desc = invItem.Description;
  435. llsdItem.flags = 0;
  436. llsdItem.item_id = invItem.ID;
  437. llsdItem.name = invItem.Name;
  438. llsdItem.parent_id = invItem.Folder;
  439. try
  440. {
  441. // TODO reevaluate after upgrade to libomv >= r2566. Probably should use UtilsConversions.
  442. llsdItem.type = TaskInventoryItem.Types[invItem.AssetType];
  443. llsdItem.inv_type = TaskInventoryItem.InvTypes[invItem.InvType];
  444. }
  445. catch (Exception e)
  446. {
  447. m_log.Error("[CAPS]: Problem setting asset/inventory type while converting inventory item " + invItem.Name + " to LLSD:", e);
  448. }
  449. llsdItem.permissions = new LLSDPermissions();
  450. llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
  451. llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
  452. llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
  453. llsdItem.permissions.group_id = UUID.Zero;
  454. llsdItem.permissions.group_mask = 0;
  455. llsdItem.permissions.is_owner_group = false;
  456. llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
  457. llsdItem.permissions.owner_id = m_agentID; // FixMe
  458. llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
  459. llsdItem.sale_info = new LLSDSaleInfo();
  460. llsdItem.sale_info.sale_price = 10;
  461. llsdItem.sale_info.sale_type = "not";
  462. return llsdItem;
  463. }
  464. /// <summary>
  465. ///
  466. /// </summary>
  467. /// <param name="mapReq"></param>
  468. /// <returns></returns>
  469. public LLSDMapLayerResponse GetMapLayer(LLSDMapRequest mapReq)
  470. {
  471. m_log.Debug("[CAPS]: MapLayer Request in region: " + m_regionName);
  472. LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
  473. mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
  474. return mapResponse;
  475. }
  476. /// <summary>
  477. ///
  478. /// </summary>
  479. /// <returns></returns>
  480. protected static OSDMapLayer GetOSDMapLayerResponse()
  481. {
  482. OSDMapLayer mapLayer = new OSDMapLayer();
  483. mapLayer.Right = 5000;
  484. mapLayer.Top = 5000;
  485. mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
  486. return mapLayer;
  487. }
  488. /// <summary>
  489. ///
  490. /// </summary>
  491. /// <param name="request"></param>
  492. /// <param name="path"></param>
  493. /// <param name="param"></param>
  494. /// <returns></returns>
  495. public string RequestTexture(string request, string path, string param)
  496. {
  497. m_log.Debug("texture request " + request);
  498. // Needs implementing (added to remove compiler warning)
  499. return String.Empty;
  500. }
  501. #region EventQueue (Currently not enabled)
  502. /// <summary>
  503. ///
  504. /// </summary>
  505. /// <param name="request"></param>
  506. /// <param name="path"></param>
  507. /// <param name="param"></param>
  508. /// <returns></returns>
  509. public string ProcessEventQueue(string request, string path, string param)
  510. {
  511. string res = String.Empty;
  512. if (m_capsEventQueue.Count > 0)
  513. {
  514. lock (m_capsEventQueue)
  515. {
  516. string item = m_capsEventQueue.Dequeue();
  517. res = item;
  518. }
  519. }
  520. else
  521. {
  522. res = CreateEmptyEventResponse();
  523. }
  524. return res;
  525. }
  526. /// <summary>
  527. ///
  528. /// </summary>
  529. /// <param name="caps"></param>
  530. /// <param name="ipAddressPort"></param>
  531. /// <returns></returns>
  532. public string CreateEstablishAgentComms(string caps, string ipAddressPort)
  533. {
  534. LLSDCapEvent eventItem = new LLSDCapEvent();
  535. eventItem.id = m_eventQueueCount;
  536. //should be creating a EstablishAgentComms item, but there isn't a class for it yet
  537. eventItem.events.Array.Add(new LLSDEmpty());
  538. string res = LLSDHelpers.SerialiseLLSDReply(eventItem);
  539. m_eventQueueCount++;
  540. m_capsEventQueue.Enqueue(res);
  541. return res;
  542. }
  543. /// <summary>
  544. ///
  545. /// </summary>
  546. /// <returns></returns>
  547. public string CreateEmptyEventResponse()
  548. {
  549. LLSDCapEvent eventItem = new LLSDCapEvent();
  550. eventItem.id = m_eventQueueCount;
  551. eventItem.events.Array.Add(new LLSDEmpty());
  552. string res = LLSDHelpers.SerialiseLLSDReply(eventItem);
  553. m_eventQueueCount++;
  554. return res;
  555. }
  556. #endregion
  557. /// <summary>
  558. /// Called by the script task update handler. Provides a URL to which the client can upload a new asset.
  559. /// </summary>
  560. /// <param name="request"></param>
  561. /// <param name="path"></param>
  562. /// <param name="param"></param>
  563. /// <param name="httpRequest">HTTP request header object</param>
  564. /// <param name="httpResponse">HTTP response header object</param>
  565. /// <returns></returns>
  566. public string ScriptTaskInventory(string request, string path, string param,
  567. OSHttpRequest httpRequest, OSHttpResponse httpResponse)
  568. {
  569. try
  570. {
  571. m_log.Debug("[CAPS]: ScriptTaskInventory Request in region: " + m_regionName);
  572. //m_log.DebugFormat("[CAPS]: request: {0}, path: {1}, param: {2}", request, path, param);
  573. Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(Utils.StringToBytes(request));
  574. LLSDTaskScriptUpdate llsdUpdateRequest = new LLSDTaskScriptUpdate();
  575. LLSDHelpers.DeserialiseOSDMap(hash, llsdUpdateRequest);
  576. string capsBase = "/CAPS/" + m_capsObjectPath;
  577. string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
  578. TaskInventoryScriptUpdater uploader =
  579. new TaskInventoryScriptUpdater(
  580. llsdUpdateRequest.item_id,
  581. llsdUpdateRequest.task_id,
  582. llsdUpdateRequest.is_script_running,
  583. capsBase + uploaderPath,
  584. m_httpListener,
  585. m_dumpAssetsToFile);
  586. uploader.OnUpLoad += TaskScriptUpdated;
  587. m_httpListener.AddStreamHandler(
  588. new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
  589. string protocol = "http://";
  590. if (m_httpListener.UseSSL)
  591. protocol = "https://";
  592. string uploaderURL = protocol + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase +
  593. uploaderPath;
  594. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  595. uploadResponse.uploader = uploaderURL;
  596. uploadResponse.state = "upload";
  597. // m_log.InfoFormat("[CAPS]: " +
  598. // "ScriptTaskInventory response: {0}",
  599. // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
  600. return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
  601. }
  602. catch (Exception e)
  603. {
  604. m_log.Error("[CAPS]: " + e.ToString());
  605. }
  606. return null;
  607. }
  608. /// <summary>
  609. /// Called by the notecard update handler. Provides a URL to which the client can upload a new asset.
  610. /// </summary>
  611. /// <param name="request"></param>
  612. /// <param name="path"></param>
  613. /// <param name="param"></param>
  614. /// <returns></returns>
  615. public string NoteCardAgentInventory(string request, string path, string param,
  616. OSHttpRequest httpRequest, OSHttpResponse httpResponse)
  617. {
  618. //m_log.Debug("[CAPS]: NoteCardAgentInventory Request in region: " + m_regionName + "\n" + request);
  619. //m_log.Debug("[CAPS]: NoteCardAgentInventory Request is: " + request);
  620. //OpenMetaverse.StructuredData.OSDMap hash = (OpenMetaverse.StructuredData.OSDMap)OpenMetaverse.StructuredData.LLSDParser.DeserializeBinary(Utils.StringToBytes(request));
  621. Hashtable hash = (Hashtable) LLSD.LLSDDeserialize(Utils.StringToBytes(request));
  622. LLSDItemUpdate llsdRequest = new LLSDItemUpdate();
  623. LLSDHelpers.DeserialiseOSDMap(hash, llsdRequest);
  624. string capsBase = "/CAPS/" + m_capsObjectPath;
  625. string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
  626. ItemUpdater uploader =
  627. new ItemUpdater(llsdRequest.item_id, capsBase + uploaderPath, m_httpListener, m_dumpAssetsToFile);
  628. uploader.OnUpLoad += ItemUpdated;
  629. m_httpListener.AddStreamHandler(
  630. new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
  631. string protocol = "http://";
  632. if (m_httpListener.UseSSL)
  633. protocol = "https://";
  634. string uploaderURL = protocol + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase +
  635. uploaderPath;
  636. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  637. uploadResponse.uploader = uploaderURL;
  638. uploadResponse.state = "upload";
  639. // m_log.InfoFormat("[CAPS]: " +
  640. // "NoteCardAgentInventory response: {0}",
  641. // LLSDHelpers.SerialiseLLSDReply(uploadResponse)));
  642. return LLSDHelpers.SerialiseLLSDReply(uploadResponse);
  643. }
  644. /// <summary>
  645. ///
  646. /// </summary>
  647. /// <param name="llsdRequest"></param>
  648. /// <returns></returns>
  649. public LLSDAssetUploadResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest)
  650. {
  651. //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
  652. //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
  653. if (llsdRequest.asset_type == "texture" ||
  654. llsdRequest.asset_type == "animation" ||
  655. llsdRequest.asset_type == "sound")
  656. {
  657. IClientAPI client = null;
  658. IScene scene = null;
  659. if (GetClient != null)
  660. {
  661. client = GetClient(m_agentID);
  662. scene = client.Scene;
  663. IMoneyModule mm = scene.RequestModuleInterface<IMoneyModule>();
  664. if (mm != null)
  665. {
  666. if (!mm.UploadCovered(client))
  667. {
  668. if (client != null)
  669. client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
  670. LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
  671. errorResponse.uploader = "";
  672. errorResponse.state = "error";
  673. return errorResponse;
  674. }
  675. }
  676. }
  677. }
  678. string assetName = llsdRequest.name;
  679. string assetDes = llsdRequest.description;
  680. string capsBase = "/CAPS/" + m_capsObjectPath;
  681. UUID newAsset = UUID.Random();
  682. UUID newInvItem = UUID.Random();
  683. UUID parentFolder = llsdRequest.folder_id;
  684. string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
  685. AssetUploader uploader =
  686. new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
  687. llsdRequest.asset_type, capsBase + uploaderPath, m_httpListener, m_dumpAssetsToFile);
  688. m_httpListener.AddStreamHandler(
  689. new BinaryStreamHandler("POST", capsBase + uploaderPath, uploader.uploaderCaps));
  690. string protocol = "http://";
  691. if (m_httpListener.UseSSL)
  692. protocol = "https://";
  693. string uploaderURL = protocol + m_httpListenerHostName + ":" + m_httpListenPort.ToString() + capsBase +
  694. uploaderPath;
  695. LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
  696. uploadResponse.uploader = uploaderURL;
  697. uploadResponse.state = "upload";
  698. uploader.OnUpLoad += UploadCompleteHandler;
  699. return uploadResponse;
  700. }
  701. /// <summary>
  702. ///
  703. /// </summary>
  704. /// <param name="assetID"></param>
  705. /// <param name="inventoryItem"></param>
  706. /// <param name="data"></param>
  707. public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
  708. UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
  709. string assetType)
  710. {
  711. sbyte assType = 0;
  712. sbyte inType = 0;
  713. if (inventoryType == "sound")
  714. {
  715. inType = 1;
  716. assType = 1;
  717. }
  718. else if (inventoryType == "animation")
  719. {
  720. inType = 19;
  721. assType = 20;
  722. }
  723. else if (inventoryType == "wearable")
  724. {
  725. inType = 18;
  726. switch (assetType)
  727. {
  728. case "bodypart":
  729. assType = 13;
  730. break;
  731. case "clothing":
  732. assType = 5;
  733. break;
  734. }
  735. }
  736. AssetBase asset;
  737. asset = new AssetBase();
  738. asset.FullID = assetID;
  739. asset.Type = assType;
  740. asset.Name = assetName;
  741. asset.Data = data;
  742. if (AddNewAsset != null)
  743. AddNewAsset(asset);
  744. else if (m_assetCache != null)
  745. m_assetCache.Store(asset);
  746. InventoryItemBase item = new InventoryItemBase();
  747. item.Owner = m_agentID;
  748. item.CreatorId = m_agentID.ToString();
  749. item.ID = inventoryItem;
  750. item.AssetID = asset.FullID;
  751. item.Description = assetDescription;
  752. item.Name = assetName;
  753. item.AssetType = assType;
  754. item.InvType = inType;
  755. item.Folder = parentFolder;
  756. item.CurrentPermissions = 2147483647;
  757. item.BasePermissions = 2147483647;
  758. item.EveryOnePermissions = 0;
  759. item.NextPermissions = 2147483647;
  760. item.CreationDate = Util.UnixTimeSinceEpoch();
  761. if (AddNewInventoryItem != null)
  762. {
  763. AddNewInventoryItem(m_agentID, item);
  764. }
  765. }
  766. /// <summary>
  767. /// Called when new asset data for an agent inventory item update has been uploaded.
  768. /// </summary>
  769. /// <param name="itemID">Item to update</param>
  770. /// <param name="data">New asset data</param>
  771. /// <returns></returns>
  772. public UUID ItemUpdated(UUID itemID, byte[] data)
  773. {
  774. if (ItemUpdatedCall != null)
  775. {
  776. return ItemUpdatedCall(m_agentID, itemID, data);
  777. }
  778. return UUID.Zero;
  779. }
  780. /// <summary>
  781. /// Called when new asset data for an agent inventory item update has been uploaded.
  782. /// </summary>
  783. /// <param name="itemID">Item to update</param>
  784. /// <param name="primID">Prim containing item to update</param>
  785. /// <param name="isScriptRunning">Signals whether the script to update is currently running</param>
  786. /// <param name="data">New asset data</param>
  787. public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data)
  788. {
  789. if (TaskScriptUpdatedCall != null)
  790. {
  791. TaskScriptUpdatedCall(m_agentID, itemID, primID, isScriptRunning, data);
  792. }
  793. }
  794. public class AssetUploader
  795. {
  796. public event UpLoadedAsset OnUpLoad;
  797. private UpLoadedAsset handlerUpLoad = null;
  798. private string uploaderPath = String.Empty;
  799. private UUID newAssetID;
  800. private UUID inventoryItemID;
  801. private UUID parentFolder;
  802. private IHttpServer httpListener;
  803. private bool m_dumpAssetsToFile;
  804. private string m_assetName = String.Empty;
  805. private string m_assetDes = String.Empty;
  806. private string m_invType = String.Empty;
  807. private string m_assetType = String.Empty;
  808. public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
  809. UUID parentFolderID, string invType, string assetType, string path,
  810. IHttpServer httpServer, bool dumpAssetsToFile)
  811. {
  812. m_assetName = assetName;
  813. m_assetDes = description;
  814. newAssetID = assetID;
  815. inventoryItemID = inventoryItem;
  816. uploaderPath = path;
  817. httpListener = httpServer;
  818. parentFolder = parentFolderID;
  819. m_assetType = assetType;
  820. m_invType = invType;
  821. m_dumpAssetsToFile = dumpAssetsToFile;
  822. }
  823. /// <summary>
  824. ///
  825. /// </summary>
  826. /// <param name="data"></param>
  827. /// <param name="path"></param>
  828. /// <param name="param"></param>
  829. /// <returns></returns>
  830. public string uploaderCaps(byte[] data, string path, string param)
  831. {
  832. UUID inv = inventoryItemID;
  833. string res = String.Empty;
  834. LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
  835. uploadComplete.new_asset = newAssetID.ToString();
  836. uploadComplete.new_inventory_item = inv;
  837. uploadComplete.state = "complete";
  838. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  839. httpListener.RemoveStreamHandler("POST", uploaderPath);
  840. // TODO: probably make this a better set of extensions here
  841. string extension = ".jp2";
  842. if (m_invType != "image")
  843. {
  844. extension = ".dat";
  845. }
  846. if (m_dumpAssetsToFile)
  847. {
  848. SaveAssetToFile(m_assetName + extension, data);
  849. }
  850. handlerUpLoad = OnUpLoad;
  851. if (handlerUpLoad != null)
  852. {
  853. handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType);
  854. }
  855. return res;
  856. }
  857. ///Left this in and commented in case there are unforseen issues
  858. //private void SaveAssetToFile(string filename, byte[] data)
  859. //{
  860. // FileStream fs = File.Create(filename);
  861. // BinaryWriter bw = new BinaryWriter(fs);
  862. // bw.Write(data);
  863. // bw.Close();
  864. // fs.Close();
  865. //}
  866. private static void SaveAssetToFile(string filename, byte[] data)
  867. {
  868. string assetPath = "UserAssets";
  869. if (!Directory.Exists(assetPath))
  870. {
  871. Directory.CreateDirectory(assetPath);
  872. }
  873. FileStream fs = File.Create(Path.Combine(assetPath, Util.safeFileName(filename)));
  874. BinaryWriter bw = new BinaryWriter(fs);
  875. bw.Write(data);
  876. bw.Close();
  877. fs.Close();
  878. }
  879. }
  880. /// <summary>
  881. /// This class is a callback invoked when a client sends asset data to
  882. /// an agent inventory notecard update url
  883. /// </summary>
  884. public class ItemUpdater
  885. {
  886. public event UpdateItem OnUpLoad;
  887. private UpdateItem handlerUpdateItem = null;
  888. private string uploaderPath = String.Empty;
  889. private UUID inventoryItemID;
  890. private IHttpServer httpListener;
  891. private bool m_dumpAssetToFile;
  892. public ItemUpdater(UUID inventoryItem, string path, IHttpServer httpServer, bool dumpAssetToFile)
  893. {
  894. m_dumpAssetToFile = dumpAssetToFile;
  895. inventoryItemID = inventoryItem;
  896. uploaderPath = path;
  897. httpListener = httpServer;
  898. }
  899. /// <summary>
  900. ///
  901. /// </summary>
  902. /// <param name="data"></param>
  903. /// <param name="path"></param>
  904. /// <param name="param"></param>
  905. /// <returns></returns>
  906. public string uploaderCaps(byte[] data, string path, string param)
  907. {
  908. UUID inv = inventoryItemID;
  909. string res = String.Empty;
  910. LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
  911. UUID assetID = UUID.Zero;
  912. handlerUpdateItem = OnUpLoad;
  913. if (handlerUpdateItem != null)
  914. {
  915. assetID = handlerUpdateItem(inv, data);
  916. }
  917. uploadComplete.new_asset = assetID.ToString();
  918. uploadComplete.new_inventory_item = inv;
  919. uploadComplete.state = "complete";
  920. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  921. httpListener.RemoveStreamHandler("POST", uploaderPath);
  922. if (m_dumpAssetToFile)
  923. {
  924. SaveAssetToFile("updateditem" + Util.RandomClass.Next(1, 1000) + ".dat", data);
  925. }
  926. return res;
  927. }
  928. ///Left this in and commented in case there are unforseen issues
  929. //private void SaveAssetToFile(string filename, byte[] data)
  930. //{
  931. // FileStream fs = File.Create(filename);
  932. // BinaryWriter bw = new BinaryWriter(fs);
  933. // bw.Write(data);
  934. // bw.Close();
  935. // fs.Close();
  936. //}
  937. private static void SaveAssetToFile(string filename, byte[] data)
  938. {
  939. string assetPath = "UserAssets";
  940. if (!Directory.Exists(assetPath))
  941. {
  942. Directory.CreateDirectory(assetPath);
  943. }
  944. FileStream fs = File.Create(Path.Combine(assetPath, filename));
  945. BinaryWriter bw = new BinaryWriter(fs);
  946. bw.Write(data);
  947. bw.Close();
  948. fs.Close();
  949. }
  950. }
  951. /// <summary>
  952. /// This class is a callback invoked when a client sends asset data to
  953. /// a task inventory script update url
  954. /// </summary>
  955. public class TaskInventoryScriptUpdater
  956. {
  957. public event UpdateTaskScript OnUpLoad;
  958. private UpdateTaskScript handlerUpdateTaskScript = null;
  959. private string uploaderPath = String.Empty;
  960. private UUID inventoryItemID;
  961. private UUID primID;
  962. private bool isScriptRunning;
  963. private IHttpServer httpListener;
  964. private bool m_dumpAssetToFile;
  965. public TaskInventoryScriptUpdater(UUID inventoryItemID, UUID primID, int isScriptRunning,
  966. string path, IHttpServer httpServer, bool dumpAssetToFile)
  967. {
  968. m_dumpAssetToFile = dumpAssetToFile;
  969. this.inventoryItemID = inventoryItemID;
  970. this.primID = primID;
  971. // This comes in over the packet as an integer, but actually appears to be treated as a bool
  972. this.isScriptRunning = (0 == isScriptRunning ? false : true);
  973. uploaderPath = path;
  974. httpListener = httpServer;
  975. }
  976. /// <summary>
  977. ///
  978. /// </summary>
  979. /// <param name="data"></param>
  980. /// <param name="path"></param>
  981. /// <param name="param"></param>
  982. /// <returns></returns>
  983. public string uploaderCaps(byte[] data, string path, string param)
  984. {
  985. try
  986. {
  987. // m_log.InfoFormat("[CAPS]: " +
  988. // "TaskInventoryScriptUpdater received data: {0}, path: {1}, param: {2}",
  989. // data, path, param));
  990. string res = String.Empty;
  991. LLSDTaskInventoryUploadComplete uploadComplete = new LLSDTaskInventoryUploadComplete();
  992. handlerUpdateTaskScript = OnUpLoad;
  993. if (handlerUpdateTaskScript != null)
  994. {
  995. handlerUpdateTaskScript(inventoryItemID, primID, isScriptRunning, data);
  996. }
  997. uploadComplete.item_id = inventoryItemID;
  998. uploadComplete.task_id = primID;
  999. uploadComplete.state = "complete";
  1000. res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
  1001. httpListener.RemoveStreamHandler("POST", uploaderPath);
  1002. if (m_dumpAssetToFile)
  1003. {
  1004. SaveAssetToFile("updatedtaskscript" + Util.RandomClass.Next(1, 1000) + ".dat", data);
  1005. }
  1006. // m_log.InfoFormat("[CAPS]: TaskInventoryScriptUpdater.uploaderCaps res: {0}", res);
  1007. return res;
  1008. }
  1009. catch (Exception e)
  1010. {
  1011. m_log.Error("[CAPS]: " + e.ToString());
  1012. }
  1013. // XXX Maybe this should be some meaningful error packet
  1014. return null;
  1015. }
  1016. ///Left this in and commented in case there are unforseen issues
  1017. //private void SaveAssetToFile(string filename, byte[] data)
  1018. //{
  1019. // FileStream fs = File.Create(filename);
  1020. // BinaryWriter bw = new BinaryWriter(fs);
  1021. // bw.Write(data);
  1022. // bw.Close();
  1023. // fs.Close();
  1024. //}
  1025. private static void SaveAssetToFile(string filename, byte[] data)
  1026. {
  1027. string assetPath = "UserAssets";
  1028. if (!Directory.Exists(assetPath))
  1029. {
  1030. Directory.CreateDirectory(assetPath);
  1031. }
  1032. FileStream fs = File.Create(Path.Combine(assetPath, filename));
  1033. BinaryWriter bw = new BinaryWriter(fs);
  1034. bw.Write(data);
  1035. bw.Close();
  1036. fs.Close();
  1037. }
  1038. }
  1039. }
  1040. }