/// <summary> /// Takes the content of a CSS file and the original absolute url of that /// file, and changes all url() properties to absolute urls. /// This way, if the CSS file has been combined with other files, the /// images specified in the url() properties will still show. /// </summary> /// <param name="fileContent"></param> /// <param name="fileUrl"></param> private static void FixUrlProperties( ref string fileContent, Uri fileUrl, UrlProcessor urlProcessor) { StringBuilder fileContentSb = new StringBuilder(fileContent); const string regexpUrlProperty = @"url\([\s\n\r]*(?<url>(?!http://)(?!https://)[^)]*?)[\s\n\r]*\)"; Regex r = new Regex(regexpUrlProperty, RegexOptions.IgnoreCase); Match m = r.Match(fileContent); // Visit each url property while (m.Success) { string urlProperty = m.Value; CaptureCollection urlProperties = m.Groups["url"].Captures; if (urlProperties.Count > 0) { string relativeUrl = urlProperties[0].Value; string absoluteUrl = urlProcessor.ProcessedUrl(relativeUrl, true, true, fileUrl, null); fileContentSb.Replace(urlProperty, "url(" + absoluteUrl + ")"); } m = m.NextMatch(); } fileContent = fileContentSb.ToString(); }
private void ProcessAllImages (ControlCollection cc, UrlProcessor urlProcessor, bool removeWhitespace) { bool imagesNeedProcessing = urlProcessor.ImagesNeedProcessing (); foreach (Control c in cc) { if (c is LiteralControl) { LiteralControl lit = (LiteralControl)c; string literalContent = lit.Text; string newLiteralContent = literalContent; if (imagesNeedProcessing) { // The "src" group in this regexp doesn't just contain the image url, but also the src= and the quotes. // That allows us to replace the entire src="...", instead of the url. // If you only replace the old url with the new url, than if you have a tag with url "images/ball3.png" after a tag with "/images/ball3.png" // when the second url ("images/ball3.png") gets replaced, it alsos replace part of the first tag "/images/ball3.png" (because the first tag // contains the second tag). const string regexpImgGroup = @"<img[^>]*?(?<src>src[^=]*?=[^""']*?(?:""|')(?<url>[^""']*?)(?:""|'))[^>]*?>"; Regex r = new Regex (regexpImgGroup, RegexOptions.IgnoreCase); Match m = r.Match (literalContent); while (m.Success) { string oldSrc = m.Groups ["src"].Value; string oldUrl = m.Groups ["url"].Value; string newUrl = urlProcessor.ProcessedUrl (oldUrl, true, false, Control.Page.Request.Url, null); string newSrc = @"src=""" + newUrl + @""""; newLiteralContent = newLiteralContent.Replace (oldSrc, newSrc); m = m.NextMatch (); } } if (removeWhitespace) { newLiteralContent = CollapsedWhitespace (newLiteralContent); } lit.Text = newLiteralContent; } else if ((c is HtmlImage) && imagesNeedProcessing) { HtmlImage hi = (HtmlImage)c; string versionId = LastUpdateTimeImageControl (hi.Src, hi, urlProcessor.ThrowExceptionOnMissingFile); hi.Src = urlProcessor.ProcessedUrl (hi.Src, true, false, Control.Page.Request.Url, versionId); } else if ((c is HyperLink) && imagesNeedProcessing) { HyperLink hl = (HyperLink)c; string versionId = LastUpdateTimeImageControl (hl.ImageUrl, hl, urlProcessor.ThrowExceptionOnMissingFile); hl.ImageUrl = urlProcessor.ProcessedUrl (hl.ImageUrl, true, false, Control.Page.Request.Url, versionId); } else if ((c is Image) && imagesNeedProcessing) { Image i = (Image)c; string versionId = LastUpdateTimeImageControl (i.ImageUrl, i, urlProcessor.ThrowExceptionOnMissingFile); i.ImageUrl = urlProcessor.ProcessedUrl (i.ImageUrl, true, false, Control.Page.Request.Url, versionId); } else { ProcessAllImages (c.Controls, urlProcessor, removeWhitespace); } } }
/// <summary> /// Returns a combined file url. /// </summary> /// <param name="urlsHash"> /// Hash based on the urls of the files that make up the combined file. /// </param> /// <param name="versionId"> /// A string that is different for each version of the files that make up /// the combined file. This is used to make sure that a browser doesn't /// pick up an outdated version from its internal browser cache. /// </param> /// <param name="fileType"> /// </param> /// <param name="urlDomain"> /// Domain to be used for the url. /// Make null or empty if you don't want a domain used in the url. /// </param> /// <returns></returns> private static string CombinedFileUrl( string urlsHash, string versionId, FileTypeUtilities.FileType fileType, UrlProcessor urlProcessor) { string url = "/" + urlsHash + FileTypeUtilities.FileTypeToExtension(fileType); return urlProcessor.ProcessedUrl(url, false, false, null, versionId); }