29 using System.Collections;
30 using System.Collections.Specialized;
32 using System.Drawing.Imaging;
33 using System.Reflection;
39 using OpenMetaverse.StructuredData;
40 using OpenMetaverse.Imaging;
41 using OpenSim.Framework;
42 using OpenSim.Framework.Servers;
43 using OpenSim.Framework.Servers.HttpServer;
44 using OpenSim.Region.Framework.Interfaces;
45 using OpenSim.Services.Interfaces;
48 namespace OpenSim.Capabilities.Handlers
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56 public const string DefaultFormat =
"x-j2c";
59 private string m_RedirectURL = null;
62 : base(
"GET", path, name, description)
64 m_assetService = assService;
65 m_RedirectURL = redirectURL;
66 if (m_RedirectURL != null && !m_RedirectURL.EndsWith(
"/"))
73 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
74 string textureStr = query.GetOne(
"texture_id");
75 string format = query.GetOne(
"format");
79 if (m_assetService == null)
81 m_log.Error(
"[GETTEXTURE]: Cannot fetch texture " + textureStr +
" without an asset service");
82 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
86 if (!
String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
91 if (!
string.IsNullOrEmpty(format))
93 formats =
new string[1] { format.ToLower() };
97 formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get(
"Accept"));
98 if (formats.Length == 0)
99 formats =
new string[1] { DefaultFormat };
104 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
105 foreach (
string f in formats)
107 if (FetchTexture(httpRequest, httpResponse, textureID, f))
113 m_log.Warn(
"[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
136 string fullID = textureID.ToString();
137 if (format != DefaultFormat)
138 fullID = fullID +
"-" +
format;
140 if (!
String.IsNullOrEmpty(m_RedirectURL))
143 texture = m_assetService.GetCached(fullID);
147 if (texture.
Type != (sbyte)AssetType.Texture)
149 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
152 WriteTextureData(httpRequest, httpResponse, texture, format);
156 string textureUrl = m_RedirectURL +
"?texture_id="+ textureID.ToString();
157 m_log.Debug(
"[GETTEXTURE]: Redirecting texture request to " + textureUrl);
166 texture = m_assetService.GetCached(fullID);
173 texture = m_assetService.Get(textureID.ToString());
177 if (texture.
Type != (sbyte)AssetType.Texture)
179 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
182 if (format == DefaultFormat)
184 WriteTextureData(httpRequest, httpResponse, texture, format);
190 newTexture.Data = ConvertTextureData(texture, format);
191 if (newTexture.
Data.Length == 0)
194 newTexture.Flags = AssetFlags.Collectable;
195 newTexture.Temporary =
true;
196 newTexture.Local =
true;
197 m_assetService.Store(newTexture);
198 WriteTextureData(httpRequest, httpResponse, newTexture, format);
206 WriteTextureData(httpRequest, httpResponse, texture, format);
213 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
219 string range = request.Headers.GetOne(
"Range");
221 if (!
String.IsNullOrEmpty(range))
225 if (TryParseRange(range, out start, out end))
229 if (start >= texture.
Data.Length)
249 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
259 end = Utils.Clamp(end, 0, texture.Data.Length - 1);
260 start = Utils.Clamp(start, 0, end);
261 int len = end - start + 1;
275 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
279 response.
AddHeader(
"Content-Range",
String.Format(
"bytes {0}-{1}/{2}", start, end, texture.
Data.Length));
281 response.Body.Write(texture.Data, start, len);
286 m_log.Warn(
"[GETTEXTURE]: Malformed Range header: " + range);
287 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
293 response.StatusCode = (int)System.Net.HttpStatusCode.OK;
295 if (format == DefaultFormat)
296 response.ContentType = texture.Metadata.ContentType;
298 response.ContentType =
"image/" +
format;
299 response.Body.Write(texture.Data, 0, texture.Data.Length);
325 private bool TryParseRange(
string header, out
int start, out
int end)
329 if (header.StartsWith(
"bytes="))
331 string[] rangeValues = header.Substring(6).Split(
'-');
333 if (rangeValues.Length == 2)
335 if (!Int32.TryParse(rangeValues[0], out start))
338 string rawEnd = rangeValues[1];
345 else if (Int32.TryParse(rawEnd, out end))
356 private byte[] ConvertTextureData(
AssetBase texture,
string format)
358 m_log.DebugFormat(
"[GETTEXTURE]: Converting texture {0} to {1}", texture.ID,
format);
359 byte[] data =
new byte[0];
361 MemoryStream imgstream =
new MemoryStream();
362 Bitmap mTexture =
new Bitmap(1, 1);
363 ManagedImage managedImage;
364 Image image = (Image)mTexture;
370 imgstream =
new MemoryStream();
373 if (OpenJPEG.DecodeToImage(texture.
Data, out managedImage, out image))
376 mTexture =
new Bitmap(image);
378 EncoderParameters myEncoderParameters =
new EncoderParameters();
379 myEncoderParameters.Param[0] =
new EncoderParameter(Encoder.Quality, 95L);
382 ImageCodecInfo codec = GetEncoderInfo(
"image/" + format);
385 mTexture.Save(imgstream, codec, myEncoderParameters);
387 data = imgstream.ToArray();
390 m_log.WarnFormat(
"[GETTEXTURE]: No such codec {0}",
format);
396 m_log.WarnFormat(
"[GETTEXTURE]: Unable to convert texture {0} to {1}: {2}", texture.ID,
format, e.Message);
402 if (mTexture != null)
408 if (imgstream != null)
419 private static ImageCodecInfo GetEncoderInfo(
String mimeType)
421 ImageCodecInfo[] encoders;
422 encoders = ImageCodecInfo.GetImageEncoders();
423 for (
int j = 0; j < encoders.Length; ++j)
425 if (encoders[j].MimeType == mimeType)
long ContentLength
Boolean property indicating whether the content type property actively has been set.
string ContentType
Content type property.
Base streamed request handler.
override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
OpenSim.Framework.Capabilities.Caps Caps
sbyte Type
(sbyte) AssetType enum
string RedirectLocation
Set a redirct location.
OpenSim.Framework.Capabilities.Caps Caps
Asset class. All Assets are reference by this class or a class derived from this class ...
GetTextureRobustHandler(string path, IAssetService assService, string name, string description, string redirectURL)
void AddHeader(string key, string value)
Add a header field and content to the response.
string ID
Asset MetaData ID (transferring from UUID to string ID)
OSHttpStatusCode
HTTP status codes (almost) as defined by W3C in http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html and IETF in http://tools.ietf.org/html/rfc6585