/// <summary> /// Get a json of stats about the image. It is used to populate a tooltip when you hover over an image container /// </summary> private void HandleImageInfo(ApiRequest request) { try { var fileName = request.RequiredFileNameOrPath("image"); Guard.AgainstNull(_bookSelection.CurrentSelection, "CurrentBook"); var plainfilename = fileName.NotEncoded; // The fileName might be URL encoded. See https://silbloom.myjetbrains.com/youtrack/issue/BL-3901. var path = UrlPathString.GetFullyDecodedPath(_bookSelection.CurrentSelection.FolderPath, ref plainfilename); RequireThat.File(path).Exists(); var fileInfo = new FileInfo(path); dynamic result = new ExpandoObject(); result.name = plainfilename; result.bytes = fileInfo.Length; // Using a stream this way, according to one source, // http://stackoverflow.com/questions/552467/how-do-i-reliably-get-an-image-dimensions-in-net-without-loading-the-image, // supposedly avoids loading the image into memory when we only want its dimensions using (var stream = RobustFile.OpenRead(path)) using (var img = Image.FromStream(stream, false, false)) { result.width = img.Width; result.height = img.Height; switch (img.PixelFormat) { case PixelFormat.Format32bppArgb: case PixelFormat.Format32bppRgb: case PixelFormat.Format32bppPArgb: result.bitDepth = "32"; break; case PixelFormat.Format24bppRgb: result.bitDepth = "24"; break; case PixelFormat.Format16bppArgb1555: case PixelFormat.Format16bppGrayScale: result.bitDepth = "16"; break; case PixelFormat.Format8bppIndexed: result.bitDepth = "8"; break; case PixelFormat.Format1bppIndexed: result.bitDepth = "1"; break; default: result.bitDepth = "unknown"; break; } } request.ReplyWithJson((object)result); } catch (Exception e) { Logger.WriteEvent("Error in server imageInfo/: url was " + request.LocalPath()); Logger.WriteEvent("Error in server imageInfo/: exception is " + e.Message); request.Failed(e.Message); NonFatalProblem.Report(ModalIf.None, PassiveIf.Alpha, "Request Error", request.LocalPath(), e); } }
/// <summary> /// Get a json of stats about the image. It is used to populate a tooltip when you hover over an image container /// </summary> private void HandleImageInfo(ApiRequest request) { try { var fileName = request.RequiredParam("image"); Guard.AgainstNull(_bookSelection.CurrentSelection, "CurrentBook"); var path = Path.Combine(_bookSelection.CurrentSelection.FolderPath, fileName); while (!RobustFile.Exists(path) && fileName.Contains('%')) { var fileName1 = fileName; // We can be fed doubly-encoded filenames. So try to decode a second time and see if that works. // See https://silbloom.myjetbrains.com/youtrack/issue/BL-3749. // Effectively triple-encoded filenames have cropped up for particular books. Such files are // already handled okay by EnhancedImageServer.ProcessAnyFileContent(). This code can handle // any depth of url-encoding. // See https://silbloom.myjetbrains.com/youtrack/issue/BL-5757. fileName = System.Web.HttpUtility.UrlDecode(fileName); if (fileName == fileName1) { break; } path = Path.Combine(_bookSelection.CurrentSelection.FolderPath, fileName); } RequireThat.File(path).Exists(); var fileInfo = new FileInfo(path); dynamic result = new ExpandoObject(); result.name = fileName; result.bytes = fileInfo.Length; // Using a stream this way, according to one source, // http://stackoverflow.com/questions/552467/how-do-i-reliably-get-an-image-dimensions-in-net-without-loading-the-image, // supposedly avoids loading the image into memory when we only want its dimensions using (var stream = RobustFile.OpenRead(path)) using (var img = Image.FromStream(stream, false, false)) { result.width = img.Width; result.height = img.Height; switch (img.PixelFormat) { case PixelFormat.Format32bppArgb: case PixelFormat.Format32bppRgb: case PixelFormat.Format32bppPArgb: result.bitDepth = "32"; break; case PixelFormat.Format24bppRgb: result.bitDepth = "24"; break; case PixelFormat.Format16bppArgb1555: case PixelFormat.Format16bppGrayScale: result.bitDepth = "16"; break; case PixelFormat.Format8bppIndexed: result.bitDepth = "8"; break; case PixelFormat.Format1bppIndexed: result.bitDepth = "1"; break; default: result.bitDepth = "unknown"; break; } } request.ReplyWithJson((object)result); } catch (Exception e) { Logger.WriteError("Error in server imageInfo/: url was " + request.LocalPath(), e); request.Failed(e.Message); } }