aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Capabilities
diff options
context:
space:
mode:
authorUbitUmarov2015-09-01 14:54:35 +0100
committerUbitUmarov2015-09-01 14:54:35 +0100
commit371c9dd2af01a2e7422ec901ee1f80757284a78c (patch)
tree058d2a513cacb12efcce0c0df0ae14ad135dbfe2 /OpenSim/Capabilities
parentremove lixo (diff)
parentdont change camera on crossings (diff)
downloadopensim-SC-371c9dd2af01a2e7422ec901ee1f80757284a78c.zip
opensim-SC-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.gz
opensim-SC-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.bz2
opensim-SC-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.xz
bad merge?
Diffstat (limited to '')
-rw-r--r--OpenSim/Capabilities/Caps.cs14
-rw-r--r--OpenSim/Capabilities/CapsHandlers.cs1
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs2
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs194
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs224
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs4
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs4
-rw-r--r--OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs15
-rw-r--r--OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs438
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadComplete.cs3
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadRequest.cs15
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadResponse.cs33
12 files changed, 797 insertions, 150 deletions
diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs
index 049afab..3efab8e 100644
--- a/OpenSim/Capabilities/Caps.cs
+++ b/OpenSim/Capabilities/Caps.cs
@@ -30,6 +30,7 @@ using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection; 32using System.Reflection;
33using System.Threading;
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -71,6 +72,7 @@ namespace OpenSim.Framework.Capabilities
71 private IHttpServer m_httpListener; 72 private IHttpServer m_httpListener;
72 private UUID m_agentID; 73 private UUID m_agentID;
73 private string m_regionName; 74 private string m_regionName;
75 private ManualResetEvent m_capsActive = new ManualResetEvent(false);
74 76
75 public UUID AgentID 77 public UUID AgentID
76 { 78 {
@@ -136,6 +138,7 @@ namespace OpenSim.Framework.Capabilities
136 m_agentID = agent; 138 m_agentID = agent;
137 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL); 139 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL);
138 m_regionName = regionName; 140 m_regionName = regionName;
141 m_capsActive.Reset();
139 } 142 }
140 143
141 /// <summary> 144 /// <summary>
@@ -255,5 +258,16 @@ namespace OpenSim.Framework.Capabilities
255 258
256 return caps; 259 return caps;
257 } 260 }
261
262 public void Activate()
263 {
264 m_capsActive.Set();
265 }
266
267 public bool WaitForActivation()
268 {
269 // Wait for 30s. If that elapses, return false and run without caps
270 return m_capsActive.WaitOne(120000);
271 }
258 } 272 }
259} \ No newline at end of file 273} \ No newline at end of file
diff --git a/OpenSim/Capabilities/CapsHandlers.cs b/OpenSim/Capabilities/CapsHandlers.cs
index 890df90..04cede1 100644
--- a/OpenSim/Capabilities/CapsHandlers.cs
+++ b/OpenSim/Capabilities/CapsHandlers.cs
@@ -90,6 +90,7 @@ namespace OpenSim.Framework.Capabilities
90 lock (m_capsHandlers) 90 lock (m_capsHandlers)
91 { 91 {
92 m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path); 92 m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
93 m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[capsName].Path);
93 m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path); 94 m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
94 m_capsHandlers.Remove(capsName); 95 m_capsHandlers.Remove(capsName);
95 } 96 }
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
index c904392..638e8bc 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
@@ -114,7 +114,7 @@ namespace OpenSim.Capabilities.Handlers
114 llsdItem.asset_id = invItem.AssetID; 114 llsdItem.asset_id = invItem.AssetID;
115 llsdItem.created_at = invItem.CreationDate; 115 llsdItem.created_at = invItem.CreationDate;
116 llsdItem.desc = invItem.Description; 116 llsdItem.desc = invItem.Description;
117 llsdItem.flags = (int)invItem.Flags; 117 llsdItem.flags = ((int)invItem.Flags) & 0xff;
118 llsdItem.item_id = invItem.ID; 118 llsdItem.item_id = invItem.ID;
119 llsdItem.name = invItem.Name; 119 llsdItem.name = invItem.Name;
120 llsdItem.parent_id = invItem.Folder; 120 llsdItem.parent_id = invItem.Folder;
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index 6b67da1..7fcc798 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -44,26 +44,64 @@ namespace OpenSim.Capabilities.Handlers
44 public class GetMeshHandler : BaseStreamHandler 44 public class GetMeshHandler : BaseStreamHandler
45 { 45 {
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
48 private IAssetService m_assetService; 49 private IAssetService m_assetService;
49 50
50 // TODO: Change this to a config option 51 public const string DefaultFormat = "vnd.ll.mesh";
51 private string m_RedirectURL = null; 52
52 53 public GetMeshHandler(IAssetService assService)
53 public GetMeshHandler(string path, IAssetService assService, string name, string description, string redirectURL)
54 : base("GET", path, name, description)
55 { 54 {
56 m_assetService = assService; 55 m_assetService = assService;
57 m_RedirectURL = redirectURL; 56 m_RedirectURL = redirectURL;
58 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/")) 57 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
59 m_RedirectURL += "/"; 58 m_RedirectURL += "/";
60 } 59 }
60 public Hashtable Handle(Hashtable request)
61 {
62 Hashtable ret = new Hashtable();
63 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
64 ret["content_type"] = "text/plain";
65 ret["keepalive"] = false;
66 ret["reusecontext"] = false;
67 ret["int_bytes"] = 0;
68 ret["int_lod"] = 0;
69 string MeshStr = (string)request["mesh_id"];
70
71
72 //m_log.DebugFormat("[GETMESH]: called {0}", MeshStr);
73
74 if (m_assetService == null)
75 {
76 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service");
77 }
78
79 UUID meshID;
80 if (!String.IsNullOrEmpty(MeshStr) && UUID.TryParse(MeshStr, out meshID))
81 {
82 // m_log.DebugFormat("[GETMESH]: Received request for mesh id {0}", meshID);
83
84
85 ret = ProcessGetMesh(request, UUID.Zero, null);
86
87
88 }
89 else
90 {
91 m_log.Warn("[GETMESH]: Failed to parse a mesh_id from GetMesh request: " + (string)request["uri"]);
92 }
61 93
62 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 94
95 return ret;
96 }
97 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
63 { 98 {
64 // Try to parse the texture ID from the request URL 99 // Try to parse the texture ID from the request URL
65 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); 100 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
66 string textureStr = query.GetOne("mesh_id"); 101 string textureStr = query.GetOne("mesh_id");
102 responsedata["reusecontext"] = false;
103 responsedata["int_lod"] = 0;
104 responsedata["int_bytes"] = 0;
67 105
68 if (m_assetService == null) 106 if (m_assetService == null)
69 { 107 {
@@ -160,40 +198,121 @@ namespace OpenSim.Capabilities.Handlers
160 // sending back the last byte instead of an error status 198 // sending back the last byte instead of an error status
161 if (start >= texture.Data.Length) 199 if (start >= texture.Data.Length)
162 { 200 {
163 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
164 response.ContentType = texture.Metadata.ContentType;
165 }
166 else
167 {
168 // Handle the case where no second range value was given. This is equivalent to requesting
169 // the rest of the entity.
170 if (end == -1)
171 end = int.MaxValue;
172 201
173 end = Utils.Clamp(end, 0, texture.Data.Length - 1); 202 Hashtable headers = new Hashtable();
174 start = Utils.Clamp(start, 0, end); 203 responsedata["headers"] = headers;
175 int len = end - start + 1; 204
205 string range = String.Empty;
206
207 if (((Hashtable)request["headers"])["range"] != null)
208 range = (string)((Hashtable)request["headers"])["range"];
176 209
177 if (0 == start && len == texture.Data.Length) 210 else if (((Hashtable)request["headers"])["Range"] != null)
211 range = (string)((Hashtable)request["headers"])["Range"];
212
213 if (!String.IsNullOrEmpty(range)) // Mesh Asset LOD // Physics
178 { 214 {
179 response.StatusCode = (int)System.Net.HttpStatusCode.OK; 215 // Range request
216 int start, end;
217 if (TryParseRange(range, out start, out end))
218 {
219 // Before clamping start make sure we can satisfy it in order to avoid
220 // sending back the last byte instead of an error status
221 if (start >= mesh.Data.Length)
222 {
223 responsedata["int_response_code"] = 404; //501; //410; //404;
224 responsedata["content_type"] = "text/plain";
225 responsedata["keepalive"] = false;
226 responsedata["str_response_string"] = "This range doesnt exist.";
227 responsedata["reusecontext"] = false;
228 responsedata["int_lod"] = 3;
229 return responsedata;
230 }
231 else
232 {
233 end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
234 start = Utils.Clamp(start, 0, end);
235 int len = end - start + 1;
236
237 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
238
239 if (start > 20000)
240 {
241 responsedata["int_lod"] = 3;
242 }
243 else if (start < 4097)
244 {
245 responsedata["int_lod"] = 1;
246 }
247 else
248 {
249 responsedata["int_lod"] = 2;
250 }
251
252
253 if (start == 0 && len == mesh.Data.Length) // well redudante maybe
254 {
255 responsedata["int_response_code"] = (int) System.Net.HttpStatusCode.OK;
256 responsedata["bin_response_data"] = mesh.Data;
257 responsedata["int_bytes"] = mesh.Data.Length;
258 responsedata["reusecontext"] = false;
259 responsedata["int_lod"] = 3;
260
261 }
262 else
263 {
264 responsedata["int_response_code"] =
265 (int) System.Net.HttpStatusCode.PartialContent;
266 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end,
267 mesh.Data.Length);
268
269 byte[] d = new byte[len];
270 Array.Copy(mesh.Data, start, d, 0, len);
271 responsedata["bin_response_data"] = d;
272 responsedata["int_bytes"] = len;
273 responsedata["reusecontext"] = false;
274 }
275 }
276 }
277 else
278 {
279 m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
280 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
281 responsedata["content_type"] = "application/vnd.ll.mesh";
282 responsedata["int_response_code"] = 200;
283 responsedata["reusecontext"] = false;
284 responsedata["int_lod"] = 3;
285 }
180 } 286 }
181 else 287 else
182 { 288 {
183 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; 289 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
184 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); 290 responsedata["content_type"] = "application/vnd.ll.mesh";
291 responsedata["int_response_code"] = 200;
292 responsedata["reusecontext"] = false;
293 responsedata["int_lod"] = 3;
185 } 294 }
186 295 }
187 response.ContentLength = len; 296 else
188 response.ContentType = "application/vnd.ll.mesh"; 297 {
189 298 responsedata["int_response_code"] = 404; //501; //410; //404;
190 response.Body.Write(texture.Data, start, len); 299 responsedata["content_type"] = "text/plain";
300 responsedata["keepalive"] = false;
301 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
302 responsedata["reusecontext"] = false;
303 responsedata["int_lod"] = 1;
304 return responsedata;
191 } 305 }
192 } 306 }
193 else 307 else
194 { 308 {
195 m_log.Warn("[GETMESH]: Malformed Range header: " + range); 309 responsedata["int_response_code"] = 404; //501; //410; //404;
196 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; 310 responsedata["content_type"] = "text/plain";
311 responsedata["keepalive"] = false;
312 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
313 responsedata["reusecontext"] = false;
314 responsedata["int_lod"] = 0;
315 return responsedata;
197 } 316 }
198 } 317 }
199 else 318 else
@@ -249,5 +368,20 @@ namespace OpenSim.Capabilities.Handlers
249 start = end = 0; 368 start = end = 0;
250 return false; 369 return false;
251 } 370 }
371 private bool TryParseRange(string header, out int start, out int end)
372 {
373 if (header.StartsWith("bytes="))
374 {
375 string[] rangeValues = header.Substring(6).Split('-');
376 if (rangeValues.Length == 2)
377 {
378 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
379 return true;
380 }
381 }
382
383 start = end = 0;
384 return false;
385 }
252 } 386 }
253} \ No newline at end of file 387} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index 828e943..a8e0fb5 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -47,10 +47,11 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
47 47
48namespace OpenSim.Capabilities.Handlers 48namespace OpenSim.Capabilities.Handlers
49{ 49{
50 public class GetTextureHandler : BaseStreamHandler 50 public class GetTextureHandler
51 { 51 {
52 private static readonly ILog m_log = 52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
54 private IAssetService m_assetService; 55 private IAssetService m_assetService;
55 56
56 public const string DefaultFormat = "x-j2c"; 57 public const string DefaultFormat = "x-j2c";
@@ -58,8 +59,8 @@ namespace OpenSim.Capabilities.Handlers
58 // TODO: Change this to a config option 59 // TODO: Change this to a config option
59 private string m_RedirectURL = null; 60 private string m_RedirectURL = null;
60 61
61 public GetTextureHandler(string path, IAssetService assService, string name, string description, string redirectURL) 62
62 : base("GET", path, name, description) 63 public GetTextureHandler(IAssetService assService)
63 { 64 {
64 m_assetService = assService; 65 m_assetService = assService;
65 m_RedirectURL = redirectURL; 66 m_RedirectURL = redirectURL;
@@ -67,19 +68,22 @@ namespace OpenSim.Capabilities.Handlers
67 m_RedirectURL += "/"; 68 m_RedirectURL += "/";
68 } 69 }
69 70
70 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 71 public Hashtable Handle(Hashtable request)
71 { 72 {
72 // Try to parse the texture ID from the request URL 73 Hashtable ret = new Hashtable();
73 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); 74 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
74 string textureStr = query.GetOne("texture_id"); 75 ret["content_type"] = "text/plain";
75 string format = query.GetOne("format"); 76 ret["keepalive"] = false;
77 ret["reusecontext"] = false;
78 ret["int_bytes"] = 0;
79 string textureStr = (string)request["texture_id"];
80 string format = (string)request["format"];
76 81
77 //m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr); 82 //m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr);
78 83
79 if (m_assetService == null) 84 if (m_assetService == null)
80 { 85 {
81 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); 86 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
82 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
83 } 87 }
84 88
85 UUID textureID; 89 UUID textureID;
@@ -94,30 +98,41 @@ namespace OpenSim.Capabilities.Handlers
94 } 98 }
95 else 99 else
96 { 100 {
97 formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept")); 101 formats = new string[1] { DefaultFormat }; // default
102 if (((Hashtable)request["headers"])["Accept"] != null)
103 formats = WebUtil.GetPreferredImageTypes((string)((Hashtable)request["headers"])["Accept"]);
98 if (formats.Length == 0) 104 if (formats.Length == 0)
99 formats = new string[1] { DefaultFormat }; // default 105 formats = new string[1] { DefaultFormat }; // default
100 106
101 } 107 }
102 // OK, we have an array with preferred formats, possibly with only one entry 108 // OK, we have an array with preferred formats, possibly with only one entry
103 109 bool foundtexture = false;
104 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
105 foreach (string f in formats) 110 foreach (string f in formats)
106 { 111 {
107 if (FetchTexture(httpRequest, httpResponse, textureID, f)) 112 foundtexture = FetchTexture(request, ret, textureID, f);
113 if (foundtexture)
108 break; 114 break;
109 } 115 }
116 if (!foundtexture)
117 {
118 ret["int_response_code"] = 404;
119 ret["error_status_text"] = "not found";
120 ret["str_response_string"] = "not found";
121 ret["content_type"] = "text/plain";
122 ret["keepalive"] = false;
123 ret["reusecontext"] = false;
124 ret["int_bytes"] = 0;
125 }
110 } 126 }
111 else 127 else
112 { 128 {
113 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); 129 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + (string)request["uri"]);
114 } 130 }
115 131
116// m_log.DebugFormat( 132// m_log.DebugFormat(
117// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}", 133// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
118// textureID, httpResponse.StatusCode, httpResponse.ContentLength); 134// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
119 135 return ret;
120 return null;
121 } 136 }
122 137
123 /// <summary> 138 /// <summary>
@@ -128,7 +143,7 @@ namespace OpenSim.Capabilities.Handlers
128 /// <param name="textureID"></param> 143 /// <param name="textureID"></param>
129 /// <param name="format"></param> 144 /// <param name="format"></param>
130 /// <returns>False for "caller try another codec"; true otherwise</returns> 145 /// <returns>False for "caller try another codec"; true otherwise</returns>
131 private bool FetchTexture(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID textureID, string format) 146 private bool FetchTexture(Hashtable request, Hashtable response, UUID textureID, string format)
132 { 147 {
133// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format); 148// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
134 AssetBase texture; 149 AssetBase texture;
@@ -137,86 +152,70 @@ namespace OpenSim.Capabilities.Handlers
137 if (format != DefaultFormat) 152 if (format != DefaultFormat)
138 fullID = fullID + "-" + format; 153 fullID = fullID + "-" + format;
139 154
140 if (!String.IsNullOrEmpty(m_RedirectURL)) 155 // try the cache
156 texture = m_assetService.GetCached(fullID);
157
158 if (texture == null)
141 { 159 {
142 // Only try to fetch locally cached textures. Misses are redirected 160 //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
143 texture = m_assetService.GetCached(fullID); 161
162 // Fetch locally or remotely. Misses return a 404
163 texture = m_assetService.Get(textureID.ToString());
144 164
145 if (texture != null) 165 if (texture != null)
146 { 166 {
147 if (texture.Type != (sbyte)AssetType.Texture) 167 if (texture.Type != (sbyte)AssetType.Texture)
168 return true;
169
170 if (format == DefaultFormat)
148 { 171 {
149 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; 172 WriteTextureData(request, response, texture, format);
150 return true; 173 return true;
151 } 174 }
152 WriteTextureData(httpRequest, httpResponse, texture, format); 175 else
153 }
154 else
155 {
156 string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString();
157 m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
158 httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
159 httpResponse.RedirectLocation = textureUrl;
160 return true;
161 }
162 }
163 else // no redirect
164 {
165 // try the cache
166 texture = m_assetService.GetCached(fullID);
167
168 if (texture == null)
169 {
170// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
171
172 // Fetch locally or remotely. Misses return a 404
173 texture = m_assetService.Get(textureID.ToString());
174
175 if (texture != null)
176 { 176 {
177 if (texture.Type != (sbyte)AssetType.Texture) 177 AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
178 { 178 newTexture.Data = ConvertTextureData(texture, format);
179 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; 179 if (newTexture.Data.Length == 0)
180 return true; 180 return false; // !!! Caller try another codec, please!
181 } 181
182 if (format == DefaultFormat) 182 newTexture.Flags = AssetFlags.Collectable;
183 { 183 newTexture.Temporary = true;
184 WriteTextureData(httpRequest, httpResponse, texture, format); 184 newTexture.Local = true;
185 return true; 185 m_assetService.Store(newTexture);
186 } 186 WriteTextureData(request, response, newTexture, format);
187 else 187 return true;
188 {
189 AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
190 newTexture.Data = ConvertTextureData(texture, format);
191 if (newTexture.Data.Length == 0)
192 return false; // !!! Caller try another codec, please!
193
194 newTexture.Flags = AssetFlags.Collectable;
195 newTexture.Temporary = true;
196 newTexture.Local = true;
197 m_assetService.Store(newTexture);
198 WriteTextureData(httpRequest, httpResponse, newTexture, format);
199 return true;
200 }
201 } 188 }
202 } 189 }
203 else // it was on the cache 190 }
204 { 191 else // it was on the cache
205// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); 192 {
206 WriteTextureData(httpRequest, httpResponse, texture, format); 193 //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
207 return true; 194 WriteTextureData(request, response, texture, format);
208 } 195 return true;
209 } 196 }
210 197
198 //response = new Hashtable();
199
200
201 //WriteTextureData(request,response,null,format);
211 // not found 202 // not found
212// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); 203 //m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
213 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; 204 return false;
214 return true;
215 } 205 }
216 206
217 private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format) 207 private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format)
218 { 208 {
219 string range = request.Headers.GetOne("Range"); 209 Hashtable headers = new Hashtable();
210 response["headers"] = headers;
211
212 string range = String.Empty;
213
214 if (((Hashtable)request["headers"])["range"] != null)
215 range = (string)((Hashtable)request["headers"])["range"];
216
217 else if (((Hashtable)request["headers"])["Range"] != null)
218 range = (string)((Hashtable)request["headers"])["Range"];
220 219
221 if (!String.IsNullOrEmpty(range)) // JP2's only 220 if (!String.IsNullOrEmpty(range)) // JP2's only
222 { 221 {
@@ -244,10 +243,8 @@ namespace OpenSim.Capabilities.Handlers
244 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution. 243 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
245 244
246// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; 245// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
247// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length)); 246 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
248// response.StatusCode = (int)System.Net.HttpStatusCode.OK; 247 response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
249 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
250 response.ContentType = texture.Metadata.ContentType;
251 } 248 }
252 else 249 else
253 { 250 {
@@ -262,41 +259,46 @@ namespace OpenSim.Capabilities.Handlers
262 259
263// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 260// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
264 261
265 // Always return PartialContent, even if the range covered the entire data length 262 response["content-type"] = texture.Metadata.ContentType;
266 // We were accidentally sending back 404 before in this situation 263
267 // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the 264 if (start == 0 && len == texture.Data.Length) // well redudante maybe
268 // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this. 265 {
269 // 266 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
270 // We also do not want to send back OK even if the whole range was satisfiable since this causes 267 response["bin_response_data"] = texture.Data;
271 // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality. 268 response["int_bytes"] = texture.Data.Length;
272// if (end > maxEnd) 269 }
273// response.StatusCode = (int)System.Net.HttpStatusCode.OK; 270 else
274// else 271 {
275 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; 272 response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
276 273 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
277 response.ContentLength = len; 274
278 response.ContentType = texture.Metadata.ContentType; 275 byte[] d = new byte[len];
279 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); 276 Array.Copy(texture.Data, start, d, 0, len);
280 277 response["bin_response_data"] = d;
281 response.Body.Write(texture.Data, start, len); 278 response["int_bytes"] = len;
279 }
280// response.Body.Write(texture.Data, start, len);
282 } 281 }
283 } 282 }
284 else 283 else
285 { 284 {
286 m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); 285 m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
287 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; 286 response["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest;
288 } 287 }
289 } 288 }
290 else // JP2's or other formats 289 else // JP2's or other formats
291 { 290 {
292 // Full content request 291 // Full content request
293 response.StatusCode = (int)System.Net.HttpStatusCode.OK; 292 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
294 response.ContentLength = texture.Data.Length;
295 if (format == DefaultFormat) 293 if (format == DefaultFormat)
296 response.ContentType = texture.Metadata.ContentType; 294 response["content_type"] = texture.Metadata.ContentType;
297 else 295 else
298 response.ContentType = "image/" + format; 296 response["content_type"] = "image/" + format;
299 response.Body.Write(texture.Data, 0, texture.Data.Length); 297
298 response["bin_response_data"] = texture.Data;
299 response["int_bytes"] = texture.Data.Length;
300
301// response.Body.Write(texture.Data, 0, texture.Data.Length);
300 } 302 }
301 303
302// if (response.StatusCode < 200 || response.StatusCode > 299) 304// if (response.StatusCode < 200 || response.StatusCode > 299)
@@ -428,4 +430,4 @@ namespace OpenSim.Capabilities.Handlers
428 return null; 430 return null;
429 } 431 }
430 } 432 }
431} \ No newline at end of file 433}
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
index fa0b228..d55e0ff 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base; 33using OpenSim.Server.Handlers.Base;
34using OpenMetaverse; 34using OpenMetaverse;
35 35
36/*
36namespace OpenSim.Capabilities.Handlers 37namespace OpenSim.Capabilities.Handlers
37{ 38{
38 public class GetTextureServerConnector : ServiceConnector 39 public class GetTextureServerConnector : ServiceConnector
@@ -68,4 +69,5 @@ namespace OpenSim.Capabilities.Handlers
68 new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl)); 69 new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl));
69 } 70 }
70 } 71 }
71} \ No newline at end of file 72}
73*/
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
index e5d9618..61aa689 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
@@ -38,6 +38,7 @@ using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Tests.Common; 39using OpenSim.Tests.Common;
40 40
41/*
41namespace OpenSim.Capabilities.Handlers.GetTexture.Tests 42namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
42{ 43{
43 [TestFixture] 44 [TestFixture]
@@ -59,4 +60,5 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
59 Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound)); 60 Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound));
60 } 61 }
61 } 62 }
62} \ No newline at end of file 63}
64*/
diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs
index 8849a59..5536564 100644
--- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Collections.Specialized; 31using System.Collections.Specialized;
31using System.Drawing; 32using System.Drawing;
32using System.Drawing.Imaging; 33using System.Drawing.Imaging;
@@ -50,6 +51,7 @@ namespace OpenSim.Capabilities.Handlers
50{ 51{
51 public class UploadBakedTextureHandler 52 public class UploadBakedTextureHandler
52 { 53 {
54
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 56
55 private Caps m_HostCapsObj; 57 private Caps m_HostCapsObj;
@@ -79,9 +81,9 @@ namespace OpenSim.Capabilities.Handlers
79 { 81 {
80 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 82 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
81 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 83 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
82 84
83 BakedTextureUploader uploader = 85 BakedTextureUploader uploader =
84 new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener); 86 new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_HostCapsObj.AgentID);
85 uploader.OnUpLoad += BakedTextureUploaded; 87 uploader.OnUpLoad += BakedTextureUploaded;
86 88
87 m_HostCapsObj.HttpListener.AddStreamHandler( 89 m_HostCapsObj.HttpListener.AddStreamHandler(
@@ -117,7 +119,7 @@ namespace OpenSim.Capabilities.Handlers
117 /// <param name="data"></param> 119 /// <param name="data"></param>
118 private void BakedTextureUploaded(UUID assetID, byte[] data) 120 private void BakedTextureUploaded(UUID assetID, byte[] data)
119 { 121 {
120// m_log.DebugFormat("[UPLOAD BAKED TEXTURE HANDLER]: Received baked texture {0}", assetID.ToString()); 122 m_log.DebugFormat("[UPLOAD BAKED TEXTURE HANDLER]: Received baked texture {0}", assetID.ToString());
121 123
122 AssetBase asset; 124 AssetBase asset;
123 asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString()); 125 asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());
@@ -125,6 +127,7 @@ namespace OpenSim.Capabilities.Handlers
125 asset.Temporary = true; 127 asset.Temporary = true;
126 asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are 128 asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
127 m_assetService.Store(asset); 129 m_assetService.Store(asset);
130
128 } 131 }
129 } 132 }
130 133
@@ -137,15 +140,19 @@ namespace OpenSim.Capabilities.Handlers
137 private string uploaderPath = String.Empty; 140 private string uploaderPath = String.Empty;
138 private UUID newAssetID; 141 private UUID newAssetID;
139 private IHttpServer httpListener; 142 private IHttpServer httpListener;
143 private UUID AgentId = UUID.Zero;
140 144
141 public BakedTextureUploader(string path, IHttpServer httpServer) 145 public BakedTextureUploader(string path, IHttpServer httpServer, UUID uUID)
142 { 146 {
143 newAssetID = UUID.Random(); 147 newAssetID = UUID.Random();
144 uploaderPath = path; 148 uploaderPath = path;
145 httpListener = httpServer; 149 httpListener = httpServer;
150 AgentId = uUID;
146 // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID); 151 // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
147 } 152 }
148 153
154
155
149 /// <summary> 156 /// <summary>
150 /// Handle raw uploaded baked texture data. 157 /// Handle raw uploaded baked texture data.
151 /// </summary> 158 /// </summary>
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
new file mode 100644
index 0000000..16e2f2d
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
@@ -0,0 +1,438 @@
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 public class WebFetchInvDescHandler
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private IInventoryService m_InventoryService;
51 private ILibraryService m_LibraryService;
52// private object m_fetchLock = new Object();
53
54 public WebFetchInvDescHandler(IInventoryService invService, ILibraryService libService)
55 {
56 m_InventoryService = invService;
57 m_LibraryService = libService;
58 }
59
60 public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
61 {
62// lock (m_fetchLock)
63// {
64// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Received request {0}", request);
65
66 // nasty temporary hack here, the linden client falsely
67 // identifies the uuid 00000000-0000-0000-0000-000000000000
68 // as a string which breaks us
69 //
70 // correctly mark it as a uuid
71 //
72 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
73
74 // another hack <integer>1</integer> results in a
75 // System.ArgumentException: Object type System.Int32 cannot
76 // be converted to target type: System.Boolean
77 //
78 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
79 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
80
81 Hashtable hash = new Hashtable();
82 try
83 {
84 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
85 }
86 catch (LLSD.LLSDParseException e)
87 {
88 m_log.ErrorFormat("[WEB FETCH INV DESC HANDLER]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
89 m_log.Error("Request: " + request);
90 }
91
92 ArrayList foldersrequested = (ArrayList)hash["folders"];
93
94 string response = "";
95
96 for (int i = 0; i < foldersrequested.Count; i++)
97 {
98 string inventoryitemstr = "";
99 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
100
101 LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
102
103 try
104 {
105 LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest);
106 }
107 catch (Exception e)
108 {
109 m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e);
110 }
111 LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
112
113 inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
114 inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
115 inventoryitemstr = inventoryitemstr.Replace("</array></map></llsd>", "");
116
117 response += inventoryitemstr;
118 }
119
120 if (response.Length == 0)
121 {
122 // Ter-guess: If requests fail a lot, the client seems to stop requesting descendants.
123 // Therefore, I'm concluding that the client only has so many threads available to do requests
124 // and when a thread stalls.. is stays stalled.
125 // Therefore we need to return something valid
126 response = "<llsd><map><key>folders</key><array /></map></llsd>";
127 }
128 else
129 {
130 response = "<llsd><map><key>folders</key><array>" + response + "</array></map></llsd>";
131 }
132
133// m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Replying to CAPS fetch inventory request");
134 //m_log.Debug("[WEB FETCH INV DESC HANDLER] "+response);
135
136 return response;
137
138// }
139 }
140
141 /// <summary>
142 /// Construct an LLSD reply packet to a CAPS inventory request
143 /// </summary>
144 /// <param name="invFetch"></param>
145 /// <returns></returns>
146 private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
147 {
148 LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
149 LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
150 contents.agent_id = invFetch.owner_id;
151 contents.owner_id = invFetch.owner_id;
152 contents.folder_id = invFetch.folder_id;
153
154 reply.folders.Array.Add(contents);
155 InventoryCollection inv = new InventoryCollection();
156 inv.Folders = new List<InventoryFolderBase>();
157 inv.Items = new List<InventoryItemBase>();
158 int version = 0;
159 int descendents = 0;
160
161 inv
162 = Fetch(
163 invFetch.owner_id, invFetch.folder_id, invFetch.owner_id,
164 invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version, out descendents);
165
166 if (inv != null && inv.Folders != null)
167 {
168 foreach (InventoryFolderBase invFolder in inv.Folders)
169 {
170 contents.categories.Array.Add(ConvertInventoryFolder(invFolder));
171 }
172
173 descendents += inv.Folders.Count;
174 }
175
176 if (inv != null && inv.Items != null)
177 {
178 foreach (InventoryItemBase invItem in inv.Items)
179 {
180 contents.items.Array.Add(ConvertInventoryItem(invItem));
181 }
182 }
183
184 contents.descendents = descendents;
185 contents.version = version;
186
187// m_log.DebugFormat(
188// "[WEB FETCH INV DESC HANDLER]: Replying to request for folder {0} (fetch items {1}, fetch folders {2}) with {3} items and {4} folders for agent {5}",
189// invFetch.folder_id,
190// invFetch.fetch_items,
191// invFetch.fetch_folders,
192// contents.items.Array.Count,
193// contents.categories.Array.Count,
194// invFetch.owner_id);
195
196 return reply;
197 }
198
199 /// <summary>
200 /// Handle the caps inventory descendents fetch.
201 /// </summary>
202 /// <param name="agentID"></param>
203 /// <param name="folderID"></param>
204 /// <param name="ownerID"></param>
205 /// <param name="fetchFolders"></param>
206 /// <param name="fetchItems"></param>
207 /// <param name="sortOrder"></param>
208 /// <param name="version"></param>
209 /// <returns>An empty InventoryCollection if the inventory look up failed</returns>
210 private InventoryCollection Fetch(
211 UUID agentID, UUID folderID, UUID ownerID,
212 bool fetchFolders, bool fetchItems, int sortOrder, out int version, out int descendents)
213 {
214// m_log.DebugFormat(
215// "[WEB FETCH INV DESC HANDLER]: Fetching folders ({0}), items ({1}) from {2} for agent {3}",
216// fetchFolders, fetchItems, folderID, agentID);
217
218 // FIXME MAYBE: We're not handling sortOrder!
219
220 version = 0;
221 descendents = 0;
222
223 InventoryFolderImpl fold;
224 if (m_LibraryService != null && m_LibraryService.LibraryRootFolder != null && agentID == m_LibraryService.LibraryRootFolder.Owner)
225 {
226 if ((fold = m_LibraryService.LibraryRootFolder.FindFolder(folderID)) != null)
227 {
228 InventoryCollection ret = new InventoryCollection();
229 ret.Folders = new List<InventoryFolderBase>();
230 ret.Items = fold.RequestListOfItems();
231 descendents = ret.Folders.Count + ret.Items.Count;
232
233 return ret;
234 }
235 }
236
237 InventoryCollection contents = new InventoryCollection();
238
239 if (folderID != UUID.Zero)
240 {
241 contents = m_InventoryService.GetFolderContent(agentID, folderID);
242 InventoryFolderBase containingFolder = new InventoryFolderBase();
243 containingFolder.ID = folderID;
244 containingFolder.Owner = agentID;
245 containingFolder = m_InventoryService.GetFolder(containingFolder);
246
247 if (containingFolder != null)
248 {
249// m_log.DebugFormat(
250// "[WEB FETCH INV DESC HANDLER]: Retrieved folder {0} {1} for agent id {2}",
251// containingFolder.Name, containingFolder.ID, agentID);
252
253 version = containingFolder.Version;
254
255 if (fetchItems)
256 {
257 List<InventoryItemBase> itemsToReturn = contents.Items;
258 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
259
260 // descendents must only include the links, not the linked items we add
261 descendents = originalItems.Count;
262
263 // Add target items for links in this folder before the links themselves.
264 foreach (InventoryItemBase item in originalItems)
265 {
266 if (item.AssetType == (int)AssetType.Link)
267 {
268 InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
269
270 // Take care of genuinely broken links where the target doesn't exist
271 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
272 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
273 // rather than having to keep track of every folder requested in the recursion.
274 if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
275 itemsToReturn.Insert(0, linkedItem);
276 }
277 }
278
279 // Now scan for folder links and insert the items they target and those links at the head of the return data
280 foreach (InventoryItemBase item in originalItems)
281 {
282 if (item.AssetType == (int)AssetType.LinkFolder)
283 {
284 InventoryCollection linkedFolderContents = m_InventoryService.GetFolderContent(ownerID, item.AssetID);
285 List<InventoryItemBase> links = linkedFolderContents.Items;
286
287 itemsToReturn.InsertRange(0, links);
288
289 foreach (InventoryItemBase link in linkedFolderContents.Items)
290 {
291 // Take care of genuinely broken links where the target doesn't exist
292 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
293 // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
294 // rather than having to keep track of every folder requested in the recursion.
295 if (link != null)
296 {
297// m_log.DebugFormat(
298// "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3}",
299// link.Name, (AssetType)link.AssetType, item.AssetID, containingFolder.Name);
300
301 InventoryItemBase linkedItem
302 = m_InventoryService.GetItem(new InventoryItemBase(link.AssetID));
303
304 if (linkedItem != null)
305 itemsToReturn.Insert(0, linkedItem);
306 }
307 }
308 }
309 }
310 }
311
312// foreach (InventoryItemBase item in contents.Items)
313// {
314// m_log.DebugFormat(
315// "[WEB FETCH INV DESC HANDLER]: Returning item {0}, type {1}, parent {2} in {3} {4}",
316// item.Name, (AssetType)item.AssetType, item.Folder, containingFolder.Name, containingFolder.ID);
317// }
318
319 // =====
320
321//
322// foreach (InventoryItemBase linkedItem in linkedItemsToAdd)
323// {
324// m_log.DebugFormat(
325// "[WEB FETCH INV DESC HANDLER]: Inserted linked item {0} for link in folder {1} for agent {2}",
326// linkedItem.Name, folderID, agentID);
327//
328// contents.Items.Add(linkedItem);
329// }
330//
331// // If the folder requested contains links, then we need to send those folders first, otherwise the links
332// // will be broken in the viewer.
333// HashSet<UUID> linkedItemFolderIdsToSend = new HashSet<UUID>();
334// foreach (InventoryItemBase item in contents.Items)
335// {
336// if (item.AssetType == (int)AssetType.Link)
337// {
338// InventoryItemBase linkedItem = m_InventoryService.GetItem(new InventoryItemBase(item.AssetID));
339//
340// // Take care of genuinely broken links where the target doesn't exist
341// // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
342// // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles
343// // rather than having to keep track of every folder requested in the recursion.
344// if (linkedItem != null && linkedItem.AssetType != (int)AssetType.Link)
345// {
346// // We don't need to send the folder if source and destination of the link are in the same
347// // folder.
348// if (linkedItem.Folder != containingFolder.ID)
349// linkedItemFolderIdsToSend.Add(linkedItem.Folder);
350// }
351// }
352// }
353//
354// foreach (UUID linkedItemFolderId in linkedItemFolderIdsToSend)
355// {
356// m_log.DebugFormat(
357// "[WEB FETCH INV DESC HANDLER]: Recursively fetching folder {0} linked by item in folder {1} for agent {2}",
358// linkedItemFolderId, folderID, agentID);
359//
360// int dummyVersion;
361// InventoryCollection linkedCollection
362// = Fetch(
363// agentID, linkedItemFolderId, ownerID, fetchFolders, fetchItems, sortOrder, out dummyVersion);
364//
365// InventoryFolderBase linkedFolder = new InventoryFolderBase(linkedItemFolderId);
366// linkedFolder.Owner = agentID;
367// linkedFolder = m_InventoryService.GetFolder(linkedFolder);
368//
369//// contents.Folders.AddRange(linkedCollection.Folders);
370//
371// contents.Folders.Add(linkedFolder);
372// contents.Items.AddRange(linkedCollection.Items);
373// }
374// }
375 }
376 }
377 else
378 {
379 // Lost items don't really need a version
380 version = 1;
381 }
382
383 return contents;
384
385 }
386 /// <summary>
387 /// Convert an internal inventory folder object into an LLSD object.
388 /// </summary>
389 /// <param name="invFolder"></param>
390 /// <returns></returns>
391 private LLSDInventoryFolder ConvertInventoryFolder(InventoryFolderBase invFolder)
392 {
393 LLSDInventoryFolder llsdFolder = new LLSDInventoryFolder();
394 llsdFolder.folder_id = invFolder.ID;
395 llsdFolder.parent_id = invFolder.ParentID;
396 llsdFolder.name = invFolder.Name;
397 llsdFolder.type = invFolder.Type;
398 llsdFolder.preferred_type = -1;
399
400 return llsdFolder;
401 }
402
403 /// <summary>
404 /// Convert an internal inventory item object into an LLSD object.
405 /// </summary>
406 /// <param name="invItem"></param>
407 /// <returns></returns>
408 private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem)
409 {
410 LLSDInventoryItem llsdItem = new LLSDInventoryItem();
411 llsdItem.asset_id = invItem.AssetID;
412 llsdItem.created_at = invItem.CreationDate;
413 llsdItem.desc = invItem.Description;
414 llsdItem.flags = ((int)invItem.Flags) & 0xff;
415 llsdItem.item_id = invItem.ID;
416 llsdItem.name = invItem.Name;
417 llsdItem.parent_id = invItem.Folder;
418 llsdItem.type = invItem.AssetType;
419 llsdItem.inv_type = invItem.InvType;
420
421 llsdItem.permissions = new LLSDPermissions();
422 llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid;
423 llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions;
424 llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions;
425 llsdItem.permissions.group_id = invItem.GroupID;
426 llsdItem.permissions.group_mask = (int)invItem.GroupPermissions;
427 llsdItem.permissions.is_owner_group = invItem.GroupOwned;
428 llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions;
429 llsdItem.permissions.owner_id = invItem.Owner;
430 llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions;
431 llsdItem.sale_info = new LLSDSaleInfo();
432 llsdItem.sale_info.sale_price = invItem.SalePrice;
433 llsdItem.sale_info.sale_type = invItem.SaleType;
434
435 return llsdItem;
436 }
437 }
438}
diff --git a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
index ab6cee5..ae8eb09 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
@@ -30,12 +30,15 @@ using OpenMetaverse;
30 30
31namespace OpenSim.Framework.Capabilities 31namespace OpenSim.Framework.Capabilities
32{ 32{
33
33 [LLSDType("MAP")] 34 [LLSDType("MAP")]
34 public class LLSDAssetUploadComplete 35 public class LLSDAssetUploadComplete
35 { 36 {
36 public string new_asset = String.Empty; 37 public string new_asset = String.Empty;
37 public UUID new_inventory_item = UUID.Zero; 38 public UUID new_inventory_item = UUID.Zero;
39// public UUID new_texture_folder_id = UUID.Zero;
38 public string state = String.Empty; 40 public string state = String.Empty;
41 public LLSDAssetUploadError error = null;
39 //public bool success = false; 42 //public bool success = false;
40 43
41 public LLSDAssetUploadComplete() 44 public LLSDAssetUploadComplete()
diff --git a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
index 6e66f0a..6779cc1 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
@@ -31,14 +31,27 @@ using OpenMetaverse;
31namespace OpenSim.Framework.Capabilities 31namespace OpenSim.Framework.Capabilities
32{ 32{
33 [OSDMap] 33 [OSDMap]
34 public class LLSDAssetResource
35 {
36 public OSDArray instance_list = new OSDArray();
37 public OSDArray texture_list = new OSDArray();
38 public OSDArray mesh_list = new OSDArray();
39 public string metric = String.Empty;
40 }
41
42 [OSDMap]
34 public class LLSDAssetUploadRequest 43 public class LLSDAssetUploadRequest
35 { 44 {
36 public string asset_type = String.Empty; 45 public string asset_type = String.Empty;
37 public string description = String.Empty; 46 public string description = String.Empty;
38 public UUID folder_id = UUID.Zero; 47 public UUID folder_id = UUID.Zero;
48 public UUID texture_folder_id = UUID.Zero;
49 public int next_owner_mask = 0;
50 public int group_mask = 0;
51 public int everyone_mask = 0;
39 public string inventory_type = String.Empty; 52 public string inventory_type = String.Empty;
40 public string name = String.Empty; 53 public string name = String.Empty;
41 54 public LLSDAssetResource asset_resources = new LLSDAssetResource();
42 public LLSDAssetUploadRequest() 55 public LLSDAssetUploadRequest()
43 { 56 {
44 } 57 }
diff --git a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
index 0d6f7f9..7c4bc97 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
@@ -26,20 +26,51 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse;
29 30
30namespace OpenSim.Framework.Capabilities 31namespace OpenSim.Framework.Capabilities
31{ 32{
32 [OSDMap] 33 [OSDMap]
34 public class LLSDAssetUploadError
35 {
36 public string message = String.Empty;
37 public UUID identifier = UUID.Zero;
38 }
39
40 [OSDMap]
41 public class LLSDAssetUploadResponsePricebrkDown
42 {
43 public int mesh_streaming;
44 public int mesh_physics;
45 public int mesh_instance;
46 public int texture;
47 public int model;
48 }
49
50 [OSDMap]
51 public class LLSDAssetUploadResponseData
52 {
53 public double resource_cost;
54 public double model_streaming_cost;
55 public double simulation_cost;
56 public double physics_cost;
57 public LLSDAssetUploadResponsePricebrkDown upload_price_breakdown = new LLSDAssetUploadResponsePricebrkDown();
58 }
59
60 [OSDMap]
33 public class LLSDAssetUploadResponse 61 public class LLSDAssetUploadResponse
34 { 62 {
35 public string uploader = String.Empty; 63 public string uploader = String.Empty;
36 public string state = String.Empty; 64 public string state = String.Empty;
37 65 public int upload_price = 0;
66 public LLSDAssetUploadResponseData data = null;
67 public LLSDAssetUploadError error = null;
38 public LLSDAssetUploadResponse() 68 public LLSDAssetUploadResponse()
39 { 69 {
40 } 70 }
41 } 71 }
42 72
73
43 [OSDMap] 74 [OSDMap]
44 public class LLSDNewFileAngentInventoryVariablePriceReplyResponse 75 public class LLSDNewFileAngentInventoryVariablePriceReplyResponse
45 { 76 {