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;
}