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