diff --git a/.gitignore b/.gitignore index a39e0d3a0..7ee5bda06 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,7 @@ local.properties **/*.dotCover ## TODO: If you have NuGet Package Restore enabled, uncomment this -src/packages/ +##**/packages # Visual C++ cache files ipch/ @@ -165,4 +165,4 @@ pip-log.txt # cached images -**/cache/* \ No newline at end of file +##**/cache \ No newline at end of file diff --git a/src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs b/src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs index 76082ab7d..141538767 100644 --- a/src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs +++ b/src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs @@ -1,9 +1,13 @@ -// ----------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. // -// ----------------------------------------------------------------------- +// +// Encapsulates methods to allow the retrieval of ImageProcessor settings. +// +// +// -------------------------------------------------------------------------------------------------------------------- namespace ImageProcessor.Web.Config { @@ -16,8 +20,6 @@ namespace ImageProcessor.Web.Config using System.Text; using ImageProcessor.Processors; - using ImageProcessor.Web.Helpers; - #endregion /// @@ -111,7 +113,7 @@ namespace ImageProcessor.Web.Config #region Security /// - /// Gets a list of whitelisted url[s] that images can be downloaded from. + /// Gets a list of white listed url[s] that images can be downloaded from. /// public Uri[] RemoteFileWhiteList { @@ -122,7 +124,7 @@ namespace ImageProcessor.Web.Config } /// - /// + /// Gets a list of image extensions for url[s] with no extension. /// public ImageSecuritySection.SafeUrl[] RemoteFileWhiteListExtensions { diff --git a/src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs b/src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs index 16ec62db7..dac3dd84e 100644 --- a/src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs +++ b/src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs @@ -1,9 +1,12 @@ -// ----------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. // -// ----------------------------------------------------------------------- +// +// Represents an image security section within a configuration file. +// +// -------------------------------------------------------------------------------------------------------------------- namespace ImageProcessor.Web.Config { @@ -168,9 +171,9 @@ namespace ImageProcessor.Web.Config public class SafeUrl : ConfigurationElement { /// - /// Gets or sets the url of the whitelisted file. + /// Gets or sets the url of the white listed file. /// - /// The url of the whitelisted file. + /// The url of the white listed file. [ConfigurationProperty("url", DefaultValue = "", IsRequired = true)] public Uri Url { @@ -179,6 +182,9 @@ namespace ImageProcessor.Web.Config set { this["url"] = value; } } + /// + /// Gets or sets a value indicating whether the white listed url is extension-less. + /// [ConfigurationProperty("extensionLess", DefaultValue = false, IsRequired = false)] public bool ExtensionLess { @@ -187,6 +193,9 @@ namespace ImageProcessor.Web.Config set { this["extensionLess"] = value; } } + /// + /// Gets or sets the image format for the extension-less url. + /// [ConfigurationProperty("imageFormat", DefaultValue = "", IsRequired = false)] public string ImageFormat { diff --git a/src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs b/src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs index bd6cdee9c..13ce1c637 100644 --- a/src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs +++ b/src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs @@ -1,9 +1,12 @@ -// ----------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) James South. -// Licensed under the Apache License, Version 2.0. +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. // -// ----------------------------------------------------------------------- +// +// Encapsulates methods used to download files from a website address. +// +// -------------------------------------------------------------------------------------------------------------------- namespace ImageProcessor.Web.Helpers { @@ -46,12 +49,12 @@ namespace ImageProcessor.Web.Helpers /// /// The white-list of url[s] from which to download remote files. /// - private static readonly Uri[] RemoteFileWhiteList = ImageProcessorConfig.Instance.RemoteFileWhiteList; + public static readonly ImageSecuritySection.SafeUrl[] RemoteFileWhiteListExtensions = ImageProcessorConfig.Instance.RemoteFileWhiteListExtensions; /// /// The white-list of url[s] from which to download remote files. /// - public static readonly ImageSecuritySection.SafeUrl[] RemoteFileWhiteListExtensions = ImageProcessorConfig.Instance.RemoteFileWhiteListExtensions; + private static readonly Uri[] RemoteFileWhiteList = ImageProcessorConfig.Instance.RemoteFileWhiteList; /// /// The length of time, in milliseconds, that a remote file download attempt can last before timing out. @@ -177,6 +180,7 @@ namespace ImageProcessor.Web.Helpers if (value < 0) { + // ReSharper disable once NotResolvedInText throw new ArgumentOutOfRangeException("TimeoutLength"); } @@ -212,6 +216,7 @@ namespace ImageProcessor.Web.Helpers if (value < 0) { + // ReSharper disable once NotResolvedInText throw new ArgumentOutOfRangeException("MaxDownloadSize"); } diff --git a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs index eaeaee427..e90b47221 100644 --- a/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs @@ -8,16 +8,13 @@ // // -------------------------------------------------------------------------------------------------------------------- -using System.Linq; -using System.Security.Cryptography; -using System.Security.Policy; -using System.Text; - namespace ImageProcessor.Web.HttpModules { #region Using using System; + using System.Diagnostics.CodeAnalysis; using System.IO; + using System.Linq; using System.Net; using System.Reflection; using System.Security; @@ -176,6 +173,7 @@ namespace ImageProcessor.Web.HttpModules /// /// The . /// + [SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1122:UseStringEmptyForEmptyStrings", Justification = "Reviewed. Suppression is OK here.")] private async Task ProcessImageAsync(HttpContext context) { HttpRequest request = context.Request; @@ -206,6 +204,7 @@ namespace ImageProcessor.Web.HttpModules requestPath = paths[0]; + // Handle extension-less urls. if (paths.Count() > 2) { queryString = paths[2]; @@ -217,13 +216,12 @@ namespace ImageProcessor.Web.HttpModules } validExtensionLessUrl = RemoteFile.RemoteFileWhiteListExtensions.Any( - x => x.ExtensionLess == true && requestPath.StartsWith(x.Url.AbsoluteUri)); + x => x.ExtensionLess && requestPath.StartsWith(x.Url.AbsoluteUri)); if (validExtensionLessUrl) { extensionLessExtension = RemoteFile.RemoteFileWhiteListExtensions.First( - x => x.ExtensionLess == true && requestPath.StartsWith(x.Url.AbsoluteUri)).ImageFormat; - + x => x.ExtensionLess && requestPath.StartsWith(x.Url.AbsoluteUri)).ImageFormat; } } } @@ -234,7 +232,7 @@ namespace ImageProcessor.Web.HttpModules } // Only process requests that pass our sanitizing filter. - if ((ImageUtils.IsValidImageExtension(requestPath) || validExtensionLessUrl ) && !string.IsNullOrWhiteSpace(queryString)) + if ((ImageUtils.IsValidImageExtension(requestPath) || validExtensionLessUrl) && !string.IsNullOrWhiteSpace(queryString)) { string fullPath = string.Format("{0}?{1}", requestPath, queryString); string imageName = Path.GetFileName(requestPath); @@ -245,14 +243,11 @@ namespace ImageProcessor.Web.HttpModules if (!string.IsNullOrWhiteSpace(urlParameters)) { - //TODO: Add hash for querystring parameters - HashAlgorithm algorithm = MD5.Create(); // SHA1.Create() - var hashCode = algorithm.ComputeHash(Encoding.UTF8.GetBytes(urlParameters)); - StringBuilder sb = new StringBuilder(); - foreach (byte b in hashCode) - sb.Append(b.ToString("X2")); - imageName += sb.ToString(); - fullPath += sb.ToString(); + string hashedUrlParameters = urlParameters.ToMD5Fingerprint(); + + // TODO: Add hash for querystring parameters. + imageName += hashedUrlParameters; + fullPath += hashedUrlParameters; } imageName += "." + extensionLessExtension; @@ -360,7 +355,7 @@ namespace ImageProcessor.Web.HttpModules context.Response.AddHeader("Content-Length", "0"); context.Response.StatusCode = (int)HttpStatusCode.NotModified; context.Response.SuppressContent = true; - + context.Response.AddFileDependency(context.Server.MapPath(cache.GetVirtualCachedPath())); this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey]); if (!isRemote) @@ -400,6 +395,7 @@ namespace ImageProcessor.Web.HttpModules HttpCachePolicy cache = response.Cache; cache.SetCacheability(HttpCacheability.Public); cache.VaryByHeaders["Accept-Encoding"] = true; + cache.SetLastModifiedFromFileDependencies(); int maxDays = DiskCache.MaxFileCachedDuration; diff --git a/src/TestWebsites/NET4/Views/Home/Index.cshtml b/src/TestWebsites/NET4/Views/Home/Index.cshtml index 2efa21511..c1da5a373 100644 --- a/src/TestWebsites/NET4/Views/Home/Index.cshtml +++ b/src/TestWebsites/NET4/Views/Home/Index.cshtml @@ -100,6 +100,7 @@

Remote

@**@ + diff --git a/src/TestWebsites/NET4/Web.config b/src/TestWebsites/NET4/Web.config index 1335fd3b2..fbc37ab45 100644 --- a/src/TestWebsites/NET4/Web.config +++ b/src/TestWebsites/NET4/Web.config @@ -71,7 +71,9 @@ - + + + diff --git a/src/TestWebsites/NET4/cache/5/2/51610039b57900ffa3b6444378a9c2a2.jpg b/src/TestWebsites/NET4/cache/5/2/51610039b57900ffa3b6444378a9c2a2.jpg deleted file mode 100644 index d9cc15a91..000000000 --- a/src/TestWebsites/NET4/cache/5/2/51610039b57900ffa3b6444378a9c2a2.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:66b9e229f5cfd84fa563155485ba61cbe0679908d131f3e5ad60817ccc17a52d -size 27264 diff --git a/src/TestWebsites/NET4/cache/cache.db b/src/TestWebsites/NET4/cache/cache.db deleted file mode 100644 index c1e11601e..000000000 Binary files a/src/TestWebsites/NET4/cache/cache.db and /dev/null differ diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml index de29c9501..1f6ef52b7 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml +++ b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml @@ -100,6 +100,7 @@

Remote

@**@ + diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Web.config b/src/TestWebsites/NET45/Test_Website_NET45/Web.config index c2a70cb67..1a9c7f035 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Web.config +++ b/src/TestWebsites/NET45/Test_Website_NET45/Web.config @@ -67,6 +67,7 @@ + diff --git a/src/packages/repositories.config b/src/packages/repositories.config new file mode 100644 index 000000000..eefad5d30 --- /dev/null +++ b/src/packages/repositories.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file