Browse Source

Adding extension-less remote url parsing.

Former-commit-id: e84842820b2ef0a43ea878f329e17c44f17a3b9e
af/merge-core
James South 12 years ago
parent
commit
bed5b003be
  1. 4
      .gitignore
  2. 18
      src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs
  3. 21
      src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs
  4. 17
      src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs
  5. 32
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  6. 1
      src/TestWebsites/NET4/Views/Home/Index.cshtml
  7. 4
      src/TestWebsites/NET4/Web.config
  8. 3
      src/TestWebsites/NET4/cache/5/2/51610039b57900ffa3b6444378a9c2a2.jpg
  9. BIN
      src/TestWebsites/NET4/cache/cache.db
  10. 1
      src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml
  11. 1
      src/TestWebsites/NET45/Test_Website_NET45/Web.config
  12. 6
      src/packages/repositories.config

4
.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/*
##**/cache

18
src/ImageProcessor.Web/NET45/Config/ImageProcessorConfig.cs

@ -1,9 +1,13 @@
// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageProcessorConfig.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// -----------------------------------------------------------------------
// <summary>
// Encapsulates methods to allow the retrieval of ImageProcessor settings.
// <see cref="http://csharpindepth.com/Articles/General/Singleton.aspx" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Config
{
@ -16,8 +20,6 @@ namespace ImageProcessor.Web.Config
using System.Text;
using ImageProcessor.Processors;
using ImageProcessor.Web.Helpers;
#endregion
/// <summary>
@ -111,7 +113,7 @@ namespace ImageProcessor.Web.Config
#region Security
/// <summary>
/// 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.
/// </summary>
public Uri[] RemoteFileWhiteList
{
@ -122,7 +124,7 @@ namespace ImageProcessor.Web.Config
}
/// <summary>
///
/// Gets a list of image extensions for url[s] with no extension.
/// </summary>
public ImageSecuritySection.SafeUrl[] RemoteFileWhiteListExtensions
{

21
src/ImageProcessor.Web/NET45/Config/ImageSecuritySection.cs

@ -1,9 +1,12 @@
// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageSecuritySection.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// -----------------------------------------------------------------------
// <summary>
// Represents an image security section within a configuration file.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Config
{
@ -168,9 +171,9 @@ namespace ImageProcessor.Web.Config
public class SafeUrl : ConfigurationElement
{
/// <summary>
/// Gets or sets the url of the whitelisted file.
/// Gets or sets the url of the white listed file.
/// </summary>
/// <value>The url of the whitelisted file.</value>
/// <value>The url of the white listed file.</value>
[ConfigurationProperty("url", DefaultValue = "", IsRequired = true)]
public Uri Url
{
@ -179,6 +182,9 @@ namespace ImageProcessor.Web.Config
set { this["url"] = value; }
}
/// <summary>
/// Gets or sets a value indicating whether the white listed url is extension-less.
/// </summary>
[ConfigurationProperty("extensionLess", DefaultValue = false, IsRequired = false)]
public bool ExtensionLess
{
@ -187,6 +193,9 @@ namespace ImageProcessor.Web.Config
set { this["extensionLess"] = value; }
}
/// <summary>
/// Gets or sets the image format for the extension-less url.
/// </summary>
[ConfigurationProperty("imageFormat", DefaultValue = "", IsRequired = false)]
public string ImageFormat
{

17
src/ImageProcessor.Web/NET45/Helpers/RemoteFile.cs

@ -1,9 +1,12 @@
// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="RemoteFile.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// -----------------------------------------------------------------------
// <summary>
// Encapsulates methods used to download files from a website address.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Helpers
{
@ -46,12 +49,12 @@ namespace ImageProcessor.Web.Helpers
/// <summary>
/// The white-list of url[s] from which to download remote files.
/// </summary>
private static readonly Uri[] RemoteFileWhiteList = ImageProcessorConfig.Instance.RemoteFileWhiteList;
public static readonly ImageSecuritySection.SafeUrl[] RemoteFileWhiteListExtensions = ImageProcessorConfig.Instance.RemoteFileWhiteListExtensions;
/// <summary>
/// The white-list of url[s] from which to download remote files.
/// </summary>
public static readonly ImageSecuritySection.SafeUrl[] RemoteFileWhiteListExtensions = ImageProcessorConfig.Instance.RemoteFileWhiteListExtensions;
private static readonly Uri[] RemoteFileWhiteList = ImageProcessorConfig.Instance.RemoteFileWhiteList;
/// <summary>
/// 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");
}

32
src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs

@ -8,16 +8,13 @@
// </summary>
// --------------------------------------------------------------------------------------------------------------------
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
/// <returns>
/// The <see cref="T:System.Threading.Tasks.Task"/>.
/// </returns>
[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;

1
src/TestWebsites/NET4/Views/Home/Index.cshtml

@ -100,6 +100,7 @@
<h2>Remote</h2>
<img src="/remote.axd?http://images.mymovies.net/images/film/cin/500x377/fid11707.jpg?width=300" />
@*<img src="/remote.axd?http://www.theworldeffect.com/images/6a00e54fa8abf78833011570697305970b-800wi.jpg?width=300" />*@
<img src="/remote.axd?http://maps.googleapis.com/maps/api/staticmap?center=Albany,+NY&zoom=13&scale=false&size=600x300&maptype=roadmap&sensor=false&format=png&visual_refresh=true?width=300" />
</div>
</div>
</section>

4
src/TestWebsites/NET4/Web.config

@ -71,7 +71,9 @@
<imageProcessor>
<security allowRemoteDownloads="true" timeout="300000" maxBytes="524288" remotePrefix="/remote.axd">
<whiteList>
<add url="http://images.mymovies.net" />
<add url="http://images.mymovies.net"/>
<add url="http://www.theworldeffect.com" />
<add url="http://maps.googleapis.com" extensionLess="true" imageFormat="png"/>
</whiteList>
</security>
<cache virtualPath="~/cache" maxDays="56" />

3
src/TestWebsites/NET4/cache/5/2/51610039b57900ffa3b6444378a9c2a2.jpg

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:66b9e229f5cfd84fa563155485ba61cbe0679908d131f3e5ad60817ccc17a52d
size 27264

BIN
src/TestWebsites/NET4/cache/cache.db

Binary file not shown.

1
src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml

@ -100,6 +100,7 @@
<h2>Remote</h2>
<img src="/remote.axd?http://images.mymovies.net/images/film/cin/500x377/fid11707.jpg?width=300" />
@*<img src="/remote.axd?http://www.theworldeffect.com/images/6a00e54fa8abf78833011570697305970b-800wi.jpg?width=300" />*@
<img src="/remote.axd?http://maps.googleapis.com/maps/api/staticmap?center=Albany,+NY&zoom=13&scale=false&size=600x300&maptype=roadmap&sensor=false&format=png&visual_refresh=true?width=300" />
</div>
</div>
</section>

1
src/TestWebsites/NET45/Test_Website_NET45/Web.config

@ -67,6 +67,7 @@
<whiteList>
<add url="http://images.mymovies.net"/>
<add url="http://www.theworldeffect.com" />
<add url="http://maps.googleapis.com" extensionLess="true" imageFormat="png"/>
</whiteList>
</security>
<cache virtualPath="~/app_data/cache" maxDays="56"/>

6
src/packages/repositories.config

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\ImageProcessor.Web\NET4\packages.config" />
<repository path="..\ImageProcessor.Web\NET45\packages.config" />
<repository path="..\TestWebsites\NET45\Test_Website_NET45\packages.config" />
</repositories>
Loading…
Cancel
Save