Caps.cs 55 KB

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