/// <summary> /// This is designed to be easily unit testable by not taking actual HttpContext, but doing everything through this IRequestInfo object /// </summary> /// <param name="info"></param> public void MakeReply(IRequestInfo info) { var r = info.LocalPathWithoutQuery.Replace("/bloom/", ""); r = r.Replace("library/", ""); if (r.Contains("libraryContents")) { GetLibraryBooks(info); } else if (r == "libraryName") { info.WriteCompleteOutput(_collectionSettings.CollectionName + " Library"); } else if (r.Contains("SourceCollectionsList")) { GetStoreBooks(info); } else if (r.StartsWith("thumbnails/")) { r = r.Replace("thumbnails/", ""); r = r.Replace("%5C", "/"); r = r.Replace("%20", " "); if (File.Exists(r)) { info.ReplyWithImage(r); } } else if (r.EndsWith(".png")) { info.ContentType = "image/png"; r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(r); } else { var imgPath = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", "book.png"); info.ReplyWithImage(imgPath); //book.GetThumbNailOfBookCoverAsync(book.Type != Book.Book.BookType.Publication,image => RefreshOneThumbnail(book, image)); } } // else // { // var imgPath = FileLocator.GetFileDistributedWithApplication("root", "ui", "book.png"); // info.ReplyWithImage(imgPath); // } } else { string path = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", r); //request.QueryString.GetValues() info.WriteCompleteOutput(File.ReadAllText(path)); } }
protected override bool ProcessRequest(IRequestInfo info) { if (base.ProcessRequest(info)) { return(true); } if (!_useCache) { return(false); } var r = GetLocalPathWithoutQuery(info); if (r.EndsWith(".png") || r.EndsWith(".jpg")) { info.ContentType = r.EndsWith(".png") ? "image/png" : "image/jpeg"; r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(_cache.GetPathToResizedImage(r)); return(true); } } } return(false); }
/// <summary> /// This is designed to be easily unit testable by not taking actual HttpContext, but doing everything through this IRequestInfo object /// </summary> /// <param name="info"></param> public void MakeReply(IRequestInfo info) { if (info.LocalPathWithoutQuery.EndsWith("testconnection")) { info.WriteCompleteOutput("OK"); return; } var r = info.LocalPathWithoutQuery.Replace("/bloom/", ""); r = r.Replace("%3A", ":"); r = r.Replace("%20", " "); r = r.Replace("%27", "'"); if (r.EndsWith(".png") || r.EndsWith(".jpg")) { info.ContentType = r.EndsWith(".png") ? "image/png" : "image/jpeg"; r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(_cache.GetPathToResizedImage(r)); } else { Logger.WriteEvent("**ImageServer: File Missing: " + r); info.WriteError(404); } } } }
protected override bool ProcessRequest(IRequestInfo info) { if (base.ProcessRequest(info)) { return(true); } var r = CorrectedLocalPath(info); const string slashBloomSlash = "/bloom/"; if (r.StartsWith(slashBloomSlash)) { r = r.Substring(slashBloomSlash.Length); } r = r.Replace("library/", ""); if (r.Contains("libraryContents")) { GetLibraryBooks(info); } else if (r == "libraryName") { info.WriteCompleteOutput(_collectionSettings.CollectionName + " Library"); } else if (r.Contains("SourceCollectionsList")) { GetStoreBooks(info); } else if (r.StartsWith("thumbnails/")) { r = r.Replace("thumbnails/", ""); r = r.Replace("%5C", "/"); r = r.Replace("%20", " "); if (File.Exists(r)) { info.ReplyWithImage(r); } } else if (r.EndsWith(".png") && r.Contains("thumbnail")) { r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(r); } else { var imgPath = BloomFileLocator.GetBrowserFile("book.png"); info.ReplyWithImage(imgPath); //book.GetThumbNailOfBookCoverAsync(book.Type != Book.Book.BookType.Publication,image => RefreshOneThumbnail(book, image)); } } // else // { // var imgPath = FileLocator.GetFileDistributedWithApplication("root", "ui", "book.png"); // info.ReplyWithImage(imgPath); // } } else { info.ContentType = GetContentType(Path.GetExtension(r)); string path = BloomFileLocator.GetBrowserFile(r); //request.QueryString.GetValues() info.ReplyWithFileContent(path); } return(true); }
/// <summary> /// This is designed to be easily unit testable by not taking actual HttpContext, but doing everything through this IRequestInfo object /// </summary> /// <param name="info"></param> public void MakeReply(IRequestInfo info) { var r = info.LocalPathWithoutQuery.Replace("/bloom/", ""); r = r.Replace("library/", ""); if (r.Contains("libraryContents")) { GetLibraryBooks(info); } else if (r == "libraryName") { info.WriteCompleteOutput(_collectionSettings.CollectionName + " Library"); } else if (r.Contains("SourceCollectionsList")) { GetStoreBooks(info); } else if(r.StartsWith("thumbnails/")) { r = r.Replace("thumbnails/", ""); r = r.Replace("%5C", "/"); r = r.Replace("%20", " "); if (File.Exists(r)) { info.ReplyWithImage(r); } } else if (r.EndsWith(".png")) { info.ContentType = "image/png"; r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(r); } else { var imgPath = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", "book.png"); info.ReplyWithImage(imgPath); //book.GetThumbNailOfBookCoverAsync(book.Type != Book.Book.BookType.Publication,image => RefreshOneThumbnail(book, image)); } } // else // { // var imgPath = FileLocator.GetFileDistributedWithApplication("root", "ui", "book.png"); // info.ReplyWithImage(imgPath); // } } else { string path = FileLocator.GetFileDistributedWithApplication("BloomBrowserUI", r); //request.QueryString.GetValues() info.WriteCompleteOutput(File.ReadAllText(path)); } }
private bool ProcessAnyFileContent(IRequestInfo info, string localPath) { string modPath = localPath; string path = null; // When JavaScript inserts our path into the html it replaces the three magic html characters with these substitutes. // We need to convert back in order to match our key. Then, reverse the change we made to deal with quotation marks. string tempPath = UnescapeUrlQuotes(modPath.Replace("<", "<").Replace(">", ">").Replace("&", "&")); if (RobustFile.Exists(tempPath)) { modPath = tempPath; } try { if (localPath.Contains("favicon.ico")) //need something to pacify Chrome { path = FileLocator.GetFileDistributedWithApplication("BloomPack.ico"); } // Is this request the full path to an image file? For most images, we just have the filename. However, in at // least one use case, the image we want isn't in the folder of the PDF we're looking at. That case is when // we are looking at a "folio", a book that gathers up other books into one big PDF. In that case, we want // to find the image in the correct book folder. See AddChildBookContentsToFolio(); var possibleFullImagePath = localPath; // "OriginalImages/" at the beginning means we're generating a pdf and want full images, // but it has nothing to do with the actual file location. if (localPath.StartsWith(OriginalImageMarker + "/")) { possibleFullImagePath = localPath.Substring(15); } if (RobustFile.Exists(possibleFullImagePath) && Path.IsPathRooted(possibleFullImagePath)) { path = possibleFullImagePath; } else { // Surprisingly, this method will return localPath unmodified if it is a fully rooted path // (like C:\... or \\localhost\C$\...) to a file that exists. So this execution path // can return contents of any file that exists if the URL gives its full path...even ones that // are generated temp files most certainly NOT distributed with the application. path = FileLocator.GetFileDistributedWithApplication(BloomFileLocator.BrowserRoot, modPath); } } catch (ApplicationException e) { // Might be from GetFileDistributedWithApplication above, but we could be checking templates that // are NOT distributed with the application. // Otherwise ignore. Assume this means that this class/method cannot serve that request, // but something else may. if (e.Message.StartsWith("Could not locate the required file")) { // LocateFile includes userInstalledSearchPaths (e.g. a shortcut to a collection in a non-standard location) path = BloomFileLocator.sTheMostRecentBloomFileLocator.LocateFile(localPath); } } //There's probably a eventual way to make this problem go away, // but at the moment FF, looking for source maps to go with css, is // looking for those maps where we said the css was, which is in the actual // book folders. So instead redirect to our browser file folder. if (string.IsNullOrEmpty(path) || !RobustFile.Exists(path)) { var startOfBookLayout = localPath.IndexOf("bookLayout"); if (startOfBookLayout > 0) { path = BloomFileLocator.GetBrowserFile(localPath.Substring(startOfBookLayout)); } var startOfBookEdit = localPath.IndexOf("bookEdit"); if (startOfBookEdit > 0) { path = BloomFileLocator.GetBrowserFile(localPath.Substring(startOfBookEdit)); } } if (!RobustFile.Exists(path) && localPath.StartsWith("pageChooser/") && IsImageTypeThatCanBeReturned(localPath)) { // if we're in the page chooser dialog and looking for a thumbnail representing an image in a // template page, look for that thumbnail in the book that is the template source, // rather than in the folder that stores the page choose dialog HTML and code. var templateBook = _bookSelection.CurrentSelection.FindTemplateBook(); if (templateBook != null) { var pathMinusPrefix = localPath.Substring("pageChooser/".Length); var templatePath = Path.Combine(templateBook.FolderPath, pathMinusPrefix); if (RobustFile.Exists(templatePath)) { info.ReplyWithImage(templatePath); return(true); } // Might be a page from a different template than the one we based this book on path = BloomFileLocator.sTheMostRecentBloomFileLocator.LocateFile(pathMinusPrefix); if (!string.IsNullOrEmpty(path)) { info.ReplyWithImage(path); return(true); } } } // Use '%25' to detect that the % in a Url encoded character (for example space encoded as %20) was encoded as %25. // In this example we would have %2520 in info.RawUrl and %20 in localPath instead of a space. Note that if an // image has a % in the filename, like 'The other 50%', and it isn't doubly encoded, then this shouldn't be a // problem because we're triggering here only if the file isn't found. if (!RobustFile.Exists(localPath) && info.RawUrl.Contains("%25")) { // possibly doubly encoded? decode one more time and try. See https://silbloom.myjetbrains.com/youtrack/issue/BL-3835. // Some existing books have somehow acquired Url encoded coverImage data like the following: // <div data-book="coverImage" lang="*"> // The%20Moon%20and%20The%20Cap_Cover.png // </div> // This leads to data being stored doubly encoded in the program's run-time data. The coverImage data is supposed to be // Html/Xml encoded (using &), not Url encoded (using %). path = System.Web.HttpUtility.UrlDecode(localPath); } if (!RobustFile.Exists(path) && IsImageTypeThatCanBeReturned(localPath)) { // last resort...maybe we are in the process of renaming a book (BL-3345) and something mysteriously is still using // the old path. For example, I can't figure out what hangs on to the old path when an image is changed after // altering the main book title. var currentFolderPath = Path.Combine(_bookSelection.CurrentSelection.FolderPath, Path.GetFileName(localPath)); if (RobustFile.Exists(currentFolderPath)) { info.ReplyWithImage(currentFolderPath); return(true); } } if (!RobustFile.Exists(path)) { // On developer machines, we can lose part of path earlier. Try one more thing. path = info.LocalPathWithoutQuery.Substring(7); // skip leading "/bloom/"); } if (!RobustFile.Exists(path)) { ReportMissingFile(localPath, path); return(false); } info.ContentType = GetContentType(Path.GetExtension(modPath)); info.ReplyWithFileContent(path); return(true); }
private bool ProcessAnyFileContent(IRequestInfo info, string localPath) { string modPath = localPath; string path = null; // When JavaScript inserts our path into the html it replaces the three magic html characters with these substitutes. // We need to convert back in order to match our key. Then, reverse the change we made to deal with quotation marks. string tempPath = UnescapeUrlQuotes(modPath.Replace("<", "<").Replace(">", ">").Replace("&", "&")); if (RobustFile.Exists(tempPath)) modPath = tempPath; try { if (localPath.Contains("favicon.ico")) //need something to pacify Chrome path = FileLocator.GetFileDistributedWithApplication("BloomPack.ico"); // Is this request the full path to an image file? For most images, we just have the filename. However, in at // least one use case, the image we want isn't in the folder of the PDF we're looking at. That case is when // we are looking at a "folio", a book that gathers up other books into one big PDF. In that case, we want // to find the image in the correct book folder. See AddChildBookContentsToFolio(); var possibleFullImagePath = localPath; // "OriginalImages/" at the beginning means we're generating a pdf and want full images, // but it has nothing to do with the actual file location. if (localPath.StartsWith("OriginalImages/")) possibleFullImagePath = localPath.Substring(15); if(RobustFile.Exists(possibleFullImagePath) && Path.IsPathRooted(possibleFullImagePath)) { path = possibleFullImagePath; } else { // Surprisingly, this method will return localPath unmodified if it is a fully rooted path // (like C:\... or \\localhost\C$\...) to a file that exists. So this execution path // can return contents of any file that exists if the URL gives its full path...even ones that // are generated temp files most certainly NOT distributed with the application. path = FileLocator.GetFileDistributedWithApplication(BloomFileLocator.BrowserRoot, modPath); } } catch (ApplicationException) { // ignore. Assume this means that this class/method cannot serve that request, but something else may. } //There's probably a eventual way to make this problem go away, // but at the moment FF, looking for source maps to go with css, is // looking for those maps where we said the css was, which is in the actual // book folders. So instead redirect to our browser file folder. if (string.IsNullOrEmpty(path) || !RobustFile.Exists(path)) { var startOfBookLayout = localPath.IndexOf("bookLayout"); if (startOfBookLayout > 0) path = BloomFileLocator.GetBrowserFile(localPath.Substring(startOfBookLayout)); var startOfBookEdit = localPath.IndexOf("bookEdit"); if (startOfBookEdit > 0) path = BloomFileLocator.GetBrowserFile(localPath.Substring(startOfBookEdit)); } if (!RobustFile.Exists(path) && localPath.StartsWith("pageChooser/") && IsImageTypeThatCanBeReturned(localPath)) { // if we're in the page chooser dialog and looking for a thumbnail representing an image in a // template page, look for that thumbnail in the book that is the template source, // rather than in the folder that stores the page choose dialog HTML and code. var templatePath = Path.Combine(_bookSelection.CurrentSelection.FindTemplateBook().FolderPath, localPath.Substring("pageChooser/".Length)); if (RobustFile.Exists(templatePath)) { info.ReplyWithImage(templatePath); return true; } } // Use '%25' to detect that the % in a Url encoded character (for example space encoded as %20) was encoded as %25. // In this example we would have %2520 in info.RawUrl and %20 in localPath instead of a space. Note that if an // image has a % in the filename, like 'The other 50%', and it isn't doubly encoded, then this shouldn't be a // problem because we're triggering here only if the file isn't found. if (!RobustFile.Exists(localPath) && info.RawUrl.Contains("%25")) { // possibly doubly encoded? decode one more time and try. See https://silbloom.myjetbrains.com/youtrack/issue/BL-3835. // Some existing books have somehow acquired Url encoded coverImage data like the following: // <div data-book="coverImage" lang="*"> // The%20Moon%20and%20The%20Cap_Cover.png // </div> // This leads to data being stored doubly encoded in the program's run-time data. The coverImage data is supposed to be // Html/Xml encoded (using &), not Url encoded (using %). path = System.Web.HttpUtility.UrlDecode(localPath); } if (!RobustFile.Exists(path) && IsImageTypeThatCanBeReturned(localPath)) { // last resort...maybe we are in the process of renaming a book (BL-3345) and something mysteriously is still using // the old path. For example, I can't figure out what hangs on to the old path when an image is changed after // altering the main book title. var currentFolderPath = Path.Combine(_bookSelection.CurrentSelection.FolderPath, Path.GetFileName(localPath)); if (RobustFile.Exists(currentFolderPath)) { info.ReplyWithImage(currentFolderPath); return true; } } if (!RobustFile.Exists(path)) { // On developer machines, we can lose part of path earlier. Try one more thing. path = info.LocalPathWithoutQuery.Substring(7); // skip leading "/bloom/"); } if (!File.Exists(path)) { ReportMissingFile(localPath,path); return false; } info.ContentType = GetContentType(Path.GetExtension(modPath)); info.ReplyWithFileContent(path); return true; }
protected override bool ProcessRequest(IRequestInfo info) { if (base.ProcessRequest(info)) { return(true); } if (!_useCache) { return(false); } var imageFile = GetLocalPathWithoutQuery(info); // only process images var isSvg = imageFile.EndsWith(".svg", StringComparison.OrdinalIgnoreCase); if (!IsImageTypeThatCanBeDegraded(imageFile) && !isSvg) { return(false); } imageFile = imageFile.Replace("thumbnail", ""); var processImage = !isSvg; if (imageFile.StartsWith(OriginalImageMarker + "/")) { processImage = false; imageFile = imageFile.Substring((OriginalImageMarker + "/").Length); if (!RobustFile.Exists(imageFile)) { // We didn't find the file here, and don't want to use the following else if or we could errantly // find it in the browser root. For example, this outer if (imageFile.StartsWith...) was added because // we were accidentally finding license.png in a template book. See BL-4290. return(false); } } // This happens with the new way we are serving css files else if (!RobustFile.Exists(imageFile)) { var fileName = Path.GetFileName(imageFile); var sourceDir = FileLocator.GetDirectoryDistributedWithApplication(BloomFileLocator.BrowserRoot); imageFile = Directory.EnumerateFiles(sourceDir, fileName, SearchOption.AllDirectories).FirstOrDefault(); // image file not found if (string.IsNullOrEmpty(imageFile)) { return(false); } // BL-2368: Do not process files from the BloomBrowserUI directory. These files are already in the state we // want them. Running them through _cache.GetPathToResizedImage() is not necessary, and in PNG files // it converts all white areas to transparent. This is resulting in icons which only contain white // (because they are rendered on a dark background) becoming completely invisible. processImage = false; } var originalImageFile = imageFile; if (processImage) { // thumbnail requests have the thumbnail parameter set in the query string var thumb = info.GetQueryParameters()["thumbnail"] != null; imageFile = _cache.GetPathToResizedImage(imageFile, thumb); if (string.IsNullOrEmpty(imageFile)) { return(false); } } info.ReplyWithImage(imageFile, originalImageFile); return(true); }
/// <summary> /// This is designed to be easily unit testable by not taking actual HttpContext, but doing everything through this IRequestInfo object /// </summary> /// <param name="info"></param> public void MakeReply(IRequestInfo info) { if(info.LocalPathWithoutQuery.EndsWith("testconnection")) { info.WriteCompleteOutput("OK"); return; } var r = info.LocalPathWithoutQuery.Replace("/bloom/", ""); r = r.Replace("%3A", ":"); r = r.Replace("%20", " "); r = r.Replace("%27", "'"); if (r.EndsWith(".png") || r.EndsWith(".jpg")) { info.ContentType = r.EndsWith(".png") ? "image/png" : "image/jpeg"; r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(_cache.GetPathToResizedImage(r)); } else { Logger.WriteEvent("**ImageServer: File Missing: "+r); info.WriteError(404); } } } }
protected override bool ProcessRequest(IRequestInfo info) { if (base.ProcessRequest(info)) return true; var r = CorrectedLocalPath(info); const string slashBloomSlash = "/bloom/"; if (r.StartsWith(slashBloomSlash)) r = r.Substring(slashBloomSlash.Length); r = r.Replace("library/", ""); if (r.Contains("libraryContents")) { GetLibraryBooks(info); } else if (r == "libraryName") { info.WriteCompleteOutput(_collectionSettings.CollectionName + " Library"); } else if (r.Contains("SourceCollectionsList")) { GetStoreBooks(info); } else if(r.StartsWith("thumbnails/")) { r = r.Replace("thumbnails/", ""); r = r.Replace("%5C", "/"); r = r.Replace("%20", " "); if (File.Exists(r)) { info.ReplyWithImage(r); } } else if (r.EndsWith(".png") && r.Contains("thumbnail")) { r = r.Replace("thumbnail", ""); //if (r.Contains("thumb")) { if (File.Exists(r)) { info.ReplyWithImage(r); } else { var imgPath = BloomFileLocator.GetBrowserFile("book.png"); info.ReplyWithImage(imgPath); //book.GetThumbNailOfBookCoverAsync(book.Type != Book.Book.BookType.Publication,image => RefreshOneThumbnail(book, image)); } } // else // { // var imgPath = FileLocator.GetFileDistributedWithApplication("root", "ui", "book.png"); // info.ReplyWithImage(imgPath); // } } else { info.ContentType = GetContentType(Path.GetExtension(r)); string path = BloomFileLocator.GetBrowserFile(r); //request.QueryString.GetValues() info.ReplyWithFileContent(path); } return true; }
public void ReplyWithImage(string imagePath) { _requestInfo.ReplyWithImage(imagePath); }
protected override bool ProcessRequest(IRequestInfo info) { if (base.ProcessRequest(info)) return true; if (!_useCache) return false; var imageFile = GetLocalPathWithoutQuery(info); // only process images var isSvg = imageFile.EndsWith(".svg", StringComparison.OrdinalIgnoreCase); if (!IsImageTypeThatCanBeDegraded(imageFile) && !isSvg) return false; imageFile = imageFile.Replace("thumbnail", ""); var processImage = !isSvg; // This happens with the new way we are serving css files if (!RobustFile.Exists(imageFile)) { var fileName = Path.GetFileName(imageFile); var sourceDir = FileLocator.GetDirectoryDistributedWithApplication(BloomFileLocator.BrowserRoot); imageFile = Directory.EnumerateFiles(sourceDir, fileName, SearchOption.AllDirectories).FirstOrDefault(); // image file not found if (string.IsNullOrEmpty(imageFile)) return false; // BL-2368: Do not process files from the BloomBrowserUI directory. These files are already in the state we // want them. Running them through _cache.GetPathToResizedImage() is not necessary, and in PNG files // it converts all white areas to transparent. This is resulting in icons which only contain white // (because they are rendered on a dark background) becoming completely invisible. processImage = false; } if (processImage) { // thumbnail requests have the thumbnail parameter set in the query string var thumb = info.GetQueryParameters()["thumbnail"] != null; imageFile = _cache.GetPathToResizedImage(imageFile, thumb); if (string.IsNullOrEmpty(imageFile)) return false; } info.ReplyWithImage(imageFile); return true; }