aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Capabilities/Handlers
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Capabilities/Handlers')
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs143
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs79
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs357
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs69
-rw-r--r--OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs299
-rw-r--r--OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs76
6 files changed, 1023 insertions, 0 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
new file mode 100644
index 0000000..c60abb1
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -0,0 +1,143 @@
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
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Services.Interfaces;
42using Caps = OpenSim.Framework.Capabilities.Caps;
43
44namespace OpenSim.Capabilities.Handlers
45{
46 public class GetMeshHandler
47 {
48// private static readonly ILog m_log =
49// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private IAssetService m_assetService;
52
53 public GetMeshHandler(IAssetService assService)
54 {
55 m_assetService = assService;
56 }
57
58 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
59 {
60
61 Hashtable responsedata = new Hashtable();
62 responsedata["int_response_code"] = 400; //501; //410; //404;
63 responsedata["content_type"] = "text/plain";
64 responsedata["keepalive"] = false;
65 responsedata["str_response_string"] = "Request wasn't what was expected";
66
67 string meshStr = string.Empty;
68
69 if (request.ContainsKey("mesh_id"))
70 meshStr = request["mesh_id"].ToString();
71
72
73 UUID meshID = UUID.Zero;
74 if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID))
75 {
76 if (m_assetService == null)
77 {
78 responsedata["int_response_code"] = 404; //501; //410; //404;
79 responsedata["content_type"] = "text/plain";
80 responsedata["keepalive"] = false;
81 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
82 return responsedata;
83 }
84
85 AssetBase mesh;
86 // Only try to fetch locally cached textures. Misses are redirected
87 mesh = m_assetService.GetCached(meshID.ToString());
88 if (mesh != null)
89 {
90 if (mesh.Type == (SByte)AssetType.Mesh)
91 {
92 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
93 responsedata["content_type"] = "application/vnd.ll.mesh";
94 responsedata["int_response_code"] = 200;
95 }
96 // Optionally add additional mesh types here
97 else
98 {
99 responsedata["int_response_code"] = 404; //501; //410; //404;
100 responsedata["content_type"] = "text/plain";
101 responsedata["keepalive"] = false;
102 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
103 return responsedata;
104 }
105 }
106 else
107 {
108 mesh = m_assetService.Get(meshID.ToString());
109 if (mesh != null)
110 {
111 if (mesh.Type == (SByte)AssetType.Mesh)
112 {
113 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
114 responsedata["content_type"] = "application/vnd.ll.mesh";
115 responsedata["int_response_code"] = 200;
116 }
117 // Optionally add additional mesh types here
118 else
119 {
120 responsedata["int_response_code"] = 404; //501; //410; //404;
121 responsedata["content_type"] = "text/plain";
122 responsedata["keepalive"] = false;
123 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
124 return responsedata;
125 }
126 }
127
128 else
129 {
130 responsedata["int_response_code"] = 404; //501; //410; //404;
131 responsedata["content_type"] = "text/plain";
132 responsedata["keepalive"] = false;
133 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
134 return responsedata;
135 }
136 }
137
138 }
139
140 return responsedata;
141 }
142 }
143}
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
new file mode 100644
index 0000000..fa5f755
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
@@ -0,0 +1,79 @@
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
28using System;
29using System.Collections;
30using Nini.Config;
31using OpenSim.Server.Base;
32using OpenSim.Services.Interfaces;
33using OpenSim.Framework.Servers.HttpServer;
34using OpenSim.Server.Handlers.Base;
35using OpenSim.Framework.Servers;
36using OpenSim.Framework.Servers.HttpServer;
37
38using OpenMetaverse;
39
40namespace OpenSim.Capabilities.Handlers
41{
42 public class GetMeshServerConnector : ServiceConnector
43 {
44 private IAssetService m_AssetService;
45 private string m_ConfigName = "CapsService";
46
47 public GetMeshServerConnector(IConfigSource config, IHttpServer server, string configName) :
48 base(config, server, configName)
49 {
50 if (configName != String.Empty)
51 m_ConfigName = configName;
52
53 IConfig serverConfig = config.Configs[m_ConfigName];
54 if (serverConfig == null)
55 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
56
57 string assetService = serverConfig.GetString("AssetService", String.Empty);
58
59 if (assetService == String.Empty)
60 throw new Exception("No AssetService in config file");
61
62 Object[] args = new Object[] { config };
63 m_AssetService =
64 ServerUtils.LoadPlugin<IAssetService>(assetService, args);
65
66 if (m_AssetService == null)
67 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
68
69 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
70 IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(),
71 delegate(Hashtable m_dhttpMethod)
72 {
73 return gmeshHandler.ProcessGetMesh(m_dhttpMethod, UUID.Zero, null);
74 });
75 server.AddStreamHandler(reqHandler);
76 }
77
78 }
79}
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
new file mode 100644
index 0000000..00ff3d0
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -0,0 +1,357 @@
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
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.Reflection;
34using System.IO;
35using System.Web;
36using log4net;
37using Nini.Config;
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using OpenMetaverse.Imaging;
41using OpenSim.Framework;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Services.Interfaces;
46using Caps = OpenSim.Framework.Capabilities.Caps;
47
48namespace OpenSim.Capabilities.Handlers
49{
50
51 public class GetTextureHandler : BaseStreamHandler
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private IAssetService m_assetService;
56
57 public const string DefaultFormat = "x-j2c";
58
59 // TODO: Change this to a config option
60 const string REDIRECT_URL = null;
61
62 public GetTextureHandler(string path, IAssetService assService) :
63 base("GET", path)
64 {
65 m_assetService = assService;
66 }
67
68 public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
69 {
70
71 // Try to parse the texture ID from the request URL
72 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
73 string textureStr = query.GetOne("texture_id");
74 string format = query.GetOne("format");
75
76 m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr);
77
78 if (m_assetService == null)
79 {
80 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
81 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
82 return null;
83 }
84
85 UUID textureID;
86 if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
87 {
88 string[] formats;
89 if (format != null && format != string.Empty)
90 {
91 formats = new string[1] { format.ToLower() };
92 }
93 else
94 {
95 formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept"));
96 if (formats.Length == 0)
97 formats = new string[1] { DefaultFormat }; // default
98
99 }
100 // OK, we have an array with preferred formats, possibly with only one entry
101
102 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
103 foreach (string f in formats)
104 {
105 if (FetchTexture(httpRequest, httpResponse, textureID, f))
106 break;
107 }
108
109 }
110 else
111 {
112 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
113 }
114
115 httpResponse.Send();
116 return null;
117 }
118
119 /// <summary>
120 ///
121 /// </summary>
122 /// <param name="httpRequest"></param>
123 /// <param name="httpResponse"></param>
124 /// <param name="textureID"></param>
125 /// <param name="format"></param>
126 /// <returns>False for "caller try another codec"; true otherwise</returns>
127 private bool FetchTexture(OSHttpRequest httpRequest, OSHttpResponse httpResponse, UUID textureID, string format)
128 {
129// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
130 AssetBase texture;
131
132 string fullID = textureID.ToString();
133 if (format != DefaultFormat)
134 fullID = fullID + "-" + format;
135
136 if (!String.IsNullOrEmpty(REDIRECT_URL))
137 {
138 // Only try to fetch locally cached textures. Misses are redirected
139 texture = m_assetService.GetCached(fullID);
140
141 if (texture != null)
142 {
143 if (texture.Type != (sbyte)AssetType.Texture)
144 {
145 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
146 return true;
147 }
148 WriteTextureData(httpRequest, httpResponse, texture, format);
149 }
150 else
151 {
152 string textureUrl = REDIRECT_URL + textureID.ToString();
153 m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
154 httpResponse.RedirectLocation = textureUrl;
155 return true;
156 }
157 }
158 else // no redirect
159 {
160 // try the cache
161 texture = m_assetService.GetCached(fullID);
162
163 if (texture == null)
164 {
165 //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
166
167 // Fetch locally or remotely. Misses return a 404
168 texture = m_assetService.Get(textureID.ToString());
169
170 if (texture != null)
171 {
172 if (texture.Type != (sbyte)AssetType.Texture)
173 {
174 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
175 return true;
176 }
177 if (format == DefaultFormat)
178 {
179 WriteTextureData(httpRequest, httpResponse, texture, format);
180 return true;
181 }
182 else
183 {
184 AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
185 newTexture.Data = ConvertTextureData(texture, format);
186 if (newTexture.Data.Length == 0)
187 return false; // !!! Caller try another codec, please!
188
189 newTexture.Flags = AssetFlags.Collectable;
190 newTexture.Temporary = true;
191 m_assetService.Store(newTexture);
192 WriteTextureData(httpRequest, httpResponse, newTexture, format);
193 return true;
194 }
195 }
196 }
197 else // it was on the cache
198 {
199 //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
200 WriteTextureData(httpRequest, httpResponse, texture, format);
201 return true;
202 }
203 }
204
205 // not found
206// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
207 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
208 return true;
209 }
210
211 private void WriteTextureData(OSHttpRequest request, OSHttpResponse response, AssetBase texture, string format)
212 {
213 string range = request.Headers.GetOne("Range");
214 //m_log.DebugFormat("[GETTEXTURE]: Range {0}", range);
215 if (!String.IsNullOrEmpty(range)) // JP2's only
216 {
217 // Range request
218 int start, end;
219 if (TryParseRange(range, out start, out end))
220 {
221 // Before clamping start make sure we can satisfy it in order to avoid
222 // sending back the last byte instead of an error status
223 if (start >= texture.Data.Length)
224 {
225 response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
226 return;
227 }
228
229 end = Utils.Clamp(end, 0, texture.Data.Length - 1);
230 start = Utils.Clamp(start, 0, end);
231 int len = end - start + 1;
232
233 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
234
235 if (len < texture.Data.Length)
236 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
237
238 response.ContentLength = len;
239 response.ContentType = texture.Metadata.ContentType;
240 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
241
242 response.Body.Write(texture.Data, start, len);
243 }
244 else
245 {
246 m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
247 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
248 }
249 }
250 else // JP2's or other formats
251 {
252 // Full content request
253 response.StatusCode = (int)System.Net.HttpStatusCode.OK;
254 response.ContentLength = texture.Data.Length;
255 if (format == DefaultFormat)
256 response.ContentType = texture.Metadata.ContentType;
257 else
258 response.ContentType = "image/" + format;
259 response.Body.Write(texture.Data, 0, texture.Data.Length);
260 }
261 }
262
263 private bool TryParseRange(string header, out int start, out int end)
264 {
265 if (header.StartsWith("bytes="))
266 {
267 string[] rangeValues = header.Substring(6).Split('-');
268 if (rangeValues.Length == 2)
269 {
270 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
271 return true;
272 }
273 }
274
275 start = end = 0;
276 return false;
277 }
278
279
280 private byte[] ConvertTextureData(AssetBase texture, string format)
281 {
282 m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format);
283 byte[] data = new byte[0];
284
285 MemoryStream imgstream = new MemoryStream();
286 Bitmap mTexture = new Bitmap(1, 1);
287 ManagedImage managedImage;
288 Image image = (Image)mTexture;
289
290 try
291 {
292 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data
293
294 imgstream = new MemoryStream();
295
296 // Decode image to System.Drawing.Image
297 if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image))
298 {
299 // Save to bitmap
300 mTexture = new Bitmap(image);
301
302 EncoderParameters myEncoderParameters = new EncoderParameters();
303 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
304
305 // Save bitmap to stream
306 ImageCodecInfo codec = GetEncoderInfo("image/" + format);
307 if (codec != null)
308 {
309 mTexture.Save(imgstream, codec, myEncoderParameters);
310 // Write the stream to a byte array for output
311 data = imgstream.ToArray();
312 }
313 else
314 m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format);
315
316 }
317 }
318 catch (Exception e)
319 {
320 m_log.WarnFormat("[GETTEXTURE]: Unable to convert texture {0} to {1}: {2}", texture.ID, format, e.Message);
321 }
322 finally
323 {
324 // Reclaim memory, these are unmanaged resources
325 // If we encountered an exception, one or more of these will be null
326 if (mTexture != null)
327 mTexture.Dispose();
328
329 if (image != null)
330 image.Dispose();
331
332 if (imgstream != null)
333 {
334 imgstream.Close();
335 imgstream.Dispose();
336 }
337 }
338
339 return data;
340 }
341
342 // From msdn
343 private static ImageCodecInfo GetEncoderInfo(String mimeType)
344 {
345 ImageCodecInfo[] encoders;
346 encoders = ImageCodecInfo.GetImageEncoders();
347 for (int j = 0; j < encoders.Length; ++j)
348 {
349 if (encoders[j].MimeType == mimeType)
350 return encoders[j];
351 }
352 return null;
353 }
354
355
356 }
357}
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
new file mode 100644
index 0000000..0d072f7
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
@@ -0,0 +1,69 @@
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
28using System;
29using Nini.Config;
30using OpenSim.Server.Base;
31using OpenSim.Services.Interfaces;
32using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base;
34using OpenMetaverse;
35
36namespace OpenSim.Capabilities.Handlers
37{
38 public class GetTextureServerConnector : ServiceConnector
39 {
40 private IAssetService m_AssetService;
41 private string m_ConfigName = "CapsService";
42
43 public GetTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
44 base(config, server, configName)
45 {
46 if (configName != String.Empty)
47 m_ConfigName = configName;
48
49 IConfig serverConfig = config.Configs[m_ConfigName];
50 if (serverConfig == null)
51 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
52
53 string assetService = serverConfig.GetString("AssetService", String.Empty);
54
55 if (assetService == String.Empty)
56 throw new Exception("No AssetService in config file");
57
58 Object[] args = new Object[] { config };
59 m_AssetService =
60 ServerUtils.LoadPlugin<IAssetService>(assetService, args);
61
62 if (m_AssetService == null)
63 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
64
65 server.AddStreamHandler(new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService));
66 }
67
68 }
69}
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
new file mode 100644
index 0000000..6fd7946
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
@@ -0,0 +1,299 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Framework.Capabilities;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Services.Interfaces;
41using Caps = OpenSim.Framework.Capabilities.Caps;
42
43namespace OpenSim.Capabilities.Handlers
44{
45
46 public class WebFetchInvDescHandler
47 {
48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private IInventoryService m_InventoryService;
52 private ILibraryService m_LibraryService;
53 private object m_fetchLock = new Object();
54
55 public WebFetchInvDescHandler(IInventoryService invService, ILibraryService libService)
56 {
57 m_InventoryService = invService;
58 m_LibraryService = libService;
59 }
60
61 public string FetchInventoryDescendentsRequest(string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
62 {
63 // nasty temporary hack here, the linden client falsely
64 // identifies the uuid 00000000-0000-0000-0000-000000000000
65 // as a string which breaks us
66 //
67 // correctly mark it as a uuid
68 //
69 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
70
71 // another hack <integer>1</integer> results in a
72 // System.ArgumentException: Object type System.Int32 cannot
73 // be converted to target type: System.Boolean
74 //
75 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
76 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
77
78 Hashtable hash = new Hashtable();
79 try
80 {
81 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
82 }
83 catch (LLSD.LLSDParseException pe)
84 {
85 m_log.Error("[AGENT INVENTORY]: Fetch error: " + pe.Message);
86 m_log.Error("Request: " + request.ToString());
87 }
88
89 ArrayList foldersrequested = (ArrayList)hash["folders"];
90
91 string response = "";
92 lock (m_fetchLock)
93 {
94 for (int i = 0; i < foldersrequested.Count; i++)
95 {
96 string inventoryitemstr = "";
97 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
98
99 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
100
101 try
102 {
103 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
104 }
105 catch (Exception e)
106 {
107 m_log.Debug("[CAPS]: caught exception doing OSD deserialize" + e);
108 }
109 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
110
111 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
112 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
113 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
114
115 response += inventoryitemstr;
116 }
117
118
119 if (response.Length == 0)
120 {
121 // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants.
122 // Therefore, I'm concluding that the client only has so many threads available to do requests
123 // and when a thread stalls.. is stays stalled.
124 // Therefore we need to return something valid
125 response = "<llsd><map><key>folders</key><array /></map></llsd>";
126 }
127 else
128 {
129 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
130 }
131
132 //m_log.DebugFormat("[CAPS]: Replying to CAPS fetch inventory request with following xml");
133 //m_log.Debug("[CAPS] "+response);
134
135 }
136 return response;
137 }
138
139 /// <summary>
140 /// Construct an LLSD reply packet to a CAPS inventory request
141 /// </summary>
142 /// <param name="invFetch"></param>
143 /// <returns></returns>
144 private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
145 {
146 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
147 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
148 contents.agent_id = invFetch.owner_id;
149 contents.owner_id = invFetch.owner_id;
150 contents.folder_id = invFetch.folder_id;
151
152 reply.folders.Array.Add(contents);
153 InventoryCollection inv = new InventoryCollection();
154 inv.Folders = new List<InventoryFolderBase>();
155 inv.Items = new List<InventoryItemBase>();
156 int version = 0;
157
158 inv = Fetch(invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version);
159
160 if (inv.Folders != null)
161 {
162 foreach (InventoryFolderBase invFolder in inv.Folders)
163 {
164 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
165 }
166 }
167
168 if (inv.Items != null)
169 {
170 foreach (InventoryItemBase invItem in inv.Items)
171 {
172 contents.items.Array.Add(ConvertInventoryItem(invItem));
173 }
174 }
175
176 contents.descendents = contents.items.Array.Count + contents.categories.Array.Count;
177 contents.version = version;
178
179 return reply;
180 }
181
182 public InventoryCollection Fetch(UUID agentID, UUID folderID, UUID ownerID,
183 bool fetchFolders, bool fetchItems, int sortOrder, out int version)
184 {
185 m_log.DebugFormat(
186 "[WEBFETCHINVENTORYDESCENDANTS]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
187 fetchFolders, fetchItems, folderID, agentID);
188
189 version = 0;
190 InventoryFolderImpl fold;
191 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
192 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
193 {
194 InventoryCollection ret = new InventoryCollection();
195 ret.Folders = new List<InventoryFolderBase>();
196 ret.Items = fold.RequestListOfItems();
197
198 return ret;
199 }
200
201 InventoryCollection contents = new InventoryCollection();
202
203 if (folderID != UUID.Zero)
204 {
205 contents = m_InventoryService.GetFolderContent(agentID, folderID);
206 InventoryFolderBase containingFolder = new InventoryFolderBase();
207 containingFolder.ID = folderID;
208 containingFolder.Owner = agentID;
209 containingFolder = m_InventoryService.GetFolder(containingFolder);
210 if (containingFolder != null)
211 version = containingFolder.Version;
212 }
213 else
214 {
215 // Lost itemsm don't really need a version
216 version = 1;
217 }
218
219 return contents;
220
221 }
222 /// <summary>
223 /// Convert an internal inventory folder object into an LLSD object.
224 /// </summary>
225 /// <param name="invFolder"></param>
226 /// <returns></returns>
227 private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
228 {
229 LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
230 llsdFolder.folder_id = invFolder.ID;
231 llsdFolder.parent_id = invFolder.ParentID;
232 llsdFolder.name = invFolder.Name;
233 if (invFolder.Type < 0 || invFolder.Type >= TaskInventoryItem.Types.Length)
234 llsdFolder.type = "-1";
235 else
236 llsdFolder.type = TaskInventoryItem.Types[invFolder.Type];
237 llsdFolder.preferred_type = "-1";
238
239 return llsdFolder;
240 }
241
242 /// <summary>
243 /// Convert an internal inventory item object into an LLSD object.
244 /// </summary>
245 /// <param name="invItem"></param>
246 /// <returns></returns>
247 private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
248 {
249 LLSDInventoryItem llsdItem = new LLSDInventoryItem();
250 llsdItem.asset_id = invItem.AssetID;
251 llsdItem.created_at = invItem.CreationDate;
252 llsdItem.desc = invItem.Description;
253 llsdItem.flags = (int)invItem.Flags;
254 llsdItem.item_id = invItem.ID;
255 llsdItem.name = invItem.Name;
256 llsdItem.parent_id = invItem.Folder;
257 try
258 {
259 // TODO reevaluate after upgrade to libomv >= r2566. Probably should use UtilsConversions.
260 llsdItem.type = TaskInventoryItem.Types[invItem.AssetType];
261 llsdItem.inv_type = TaskInventoryItem.InvTypes[invItem.InvType];
262 }
263 catch (Exception e)
264 {
265 m_log.ErrorFormat("[CAPS]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}", invItem.AssetType, invItem.InvType, invItem.Name, e.Message);
266 }
267 llsdItem.permissions = new LLSDPermissions();
268 llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
269 llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
270 llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
271 llsdItem.permissions.group_id = invItem.GroupID;
272 llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
273 llsdItem.permissions.is_owner_group = invItem.GroupOwned;
274 llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
275 llsdItem.permissions.owner_id = invItem.Owner;
276 llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
277 llsdItem.sale_info = new LLSDSaleInfo();
278 llsdItem.sale_info.sale_price = invItem.SalePrice;
279 switch (invItem.SaleType)
280 {
281 default:
282 llsdItem.sale_info.sale_type = "not";
283 break;
284 case 1:
285 llsdItem.sale_info.sale_type = "original";
286 break;
287 case 2:
288 llsdItem.sale_info.sale_type = "copy";
289 break;
290 case 3:
291 llsdItem.sale_info.sale_type = "contents";
292 break;
293 }
294
295 return llsdItem;
296 }
297
298 }
299}
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
new file mode 100644
index 0000000..92eeb14
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescServerConnector.cs
@@ -0,0 +1,76 @@
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
28using System;
29using Nini.Config;
30using OpenSim.Server.Base;
31using OpenSim.Services.Interfaces;
32using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base;
34using OpenMetaverse;
35
36namespace OpenSim.Capabilities.Handlers
37{
38 public class WebFetchInvDescServerConnector : ServiceConnector
39 {
40 private IInventoryService m_InventoryService;
41 private ILibraryService m_LibraryService;
42 private string m_ConfigName = "CapsService";
43
44 public WebFetchInvDescServerConnector(IConfigSource config, IHttpServer server, string configName) :
45 base(config, server, configName)
46 {
47 if (configName != String.Empty)
48 m_ConfigName = configName;
49
50 IConfig serverConfig = config.Configs[m_ConfigName];
51 if (serverConfig == null)
52 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
53
54 string invService = serverConfig.GetString("InventoryService", String.Empty);
55
56 if (invService == String.Empty)
57 throw new Exception("No InventoryService in config file");
58
59 Object[] args = new Object[] { config };
60 m_InventoryService =
61 ServerUtils.LoadPlugin<IInventoryService>(invService, args);
62
63 if (m_InventoryService == null)
64 throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName));
65
66 string libService = serverConfig.GetString("LibraryService", String.Empty);
67 m_LibraryService =
68 ServerUtils.LoadPlugin<ILibraryService>(libService, args);
69
70 WebFetchInvDescHandler webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
71 IRequestHandler reqHandler = new RestStreamHandler("POST", "/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/, webFetchHandler.FetchInventoryDescendentsRequest);
72 server.AddStreamHandler(reqHandler);
73 }
74
75 }
76}