Browse Source

v2.3.0.3

Added support for authorization config.


Former-commit-id: aa09b07f09009deb470fd44b875b70c0fe95442b
af/merge-core
JimBobSquarePants 13 years ago
parent
commit
eb24e42f09
  1. 22
      src/ImageProcessor.Web/NET45/Caching/DiskCache.cs
  2. 4
      src/ImageProcessor.Web/NET45/Caching/SQLContext.cs
  3. 50
      src/ImageProcessor.Web/NET45/HttpModules/ImageProcessingModule.cs
  4. 4
      src/ImageProcessor.Web/NET45/Properties/AssemblyInfo.cs
  5. 36
      src/ImageProcessor/Helpers/Extensions/StringExtensions.cs
  6. 35
      src/ImageProcessor/Imaging/ImageUtils.cs
  7. 2
      src/ImageProcessor/Processors/Format.cs
  8. 4
      src/ImageProcessor/Properties/AssemblyInfo.cs
  9. BIN
      src/Nuget/ImageProcessor.1.6.0.1.nupkg
  10. BIN
      src/Nuget/ImageProcessor.1.7.0.1.nupkg
  11. 1
      src/Nuget/ImageProcessor.Web.2.2.3.3.nupkg.REMOVED.git-id
  12. 1
      src/Nuget/ImageProcessor.Web.2.3.0.0.nupkg.REMOVED.git-id
  13. 1
      src/Nuget/ImageProcessor.Web.2.3.0.2.nupkg.REMOVED.git-id
  14. 1
      src/Nuget/ImageProcessor.Web.2.3.0.3.nupkg.REMOVED.git-id
  15. 7
      src/TestWebsites/NET45/Test_Website_NET45/Web.config

22
src/ImageProcessor.Web/NET45/Caching/DiskCache.cs

@ -11,6 +11,7 @@ namespace ImageProcessor.Web.Caching
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -19,6 +20,7 @@ namespace ImageProcessor.Web.Caching
using System.Web; using System.Web;
using System.Web.Hosting; using System.Web.Hosting;
using ImageProcessor.Helpers.Extensions; using ImageProcessor.Helpers.Extensions;
using ImageProcessor.Imaging;
using ImageProcessor.Web.Config; using ImageProcessor.Web.Config;
using ImageProcessor.Web.Helpers; using ImageProcessor.Web.Helpers;
#endregion #endregion
@ -429,7 +431,7 @@ namespace ImageProcessor.Web.Caching
// Use an md5 hash of the full path including the querystring to create the image name. // Use an md5 hash of the full path including the querystring to create the image name.
// That name can also be used as a key for the cached image and we should be able to use // That name can also be used as a key for the cached image and we should be able to use
// The first character of that hash as a subfolder. // The first character of that hash as a subfolder.
string parsedExtension = this.ParseExtension(this.fullPath); string parsedExtension = ImageUtils.GetExtension(this.fullPath);
string fallbackExtension = this.imageName.Substring(this.imageName.LastIndexOf(".", StringComparison.Ordinal) + 1); string fallbackExtension = this.imageName.Substring(this.imageName.LastIndexOf(".", StringComparison.Ordinal) + 1);
string encryptedName = this.fullPath.ToMD5Fingerprint(); string encryptedName = this.fullPath.ToMD5Fingerprint();
string firstSubpath = encryptedName.Substring(0, 1); string firstSubpath = encryptedName.Substring(0, 1);
@ -438,7 +440,7 @@ namespace ImageProcessor.Web.Caching
string cachedFileName = string.Format( string cachedFileName = string.Format(
"{0}.{1}", "{0}.{1}",
encryptedName, encryptedName,
!string.IsNullOrWhiteSpace(parsedExtension) ? parsedExtension : fallbackExtension); !string.IsNullOrWhiteSpace(parsedExtension) ? parsedExtension.Replace(".", string.Empty) : fallbackExtension);
cachedPath = Path.Combine(AbsoluteCachePath, firstSubpath, secondSubpath, cachedFileName); cachedPath = Path.Combine(AbsoluteCachePath, firstSubpath, secondSubpath, cachedFileName);
} }
@ -446,22 +448,6 @@ namespace ImageProcessor.Web.Caching
return cachedPath; return cachedPath;
} }
/// <summary>
/// Returns the correct file extension for the given string input
/// </summary>
/// <param name="input">
/// The string to parse.
/// </param>
/// <returns>
/// The correct file extension for the given string input if it can find one; otherwise an empty string.
/// </returns>
private string ParseExtension(string input)
{
Match match = FormatRegex.Match(input);
return match.Success ? match.Value : string.Empty;
}
/// <summary> /// <summary>
/// The rough date time compare. /// The rough date time compare.
/// </summary> /// </summary>

4
src/ImageProcessor.Web/NET45/Caching/SQLContext.cs

@ -73,9 +73,9 @@ namespace ImageProcessor.Web.Caching
} }
} }
} }
catch (Exception ex) catch
{ {
throw ex; throw;
} }
} }

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

@ -12,10 +12,15 @@ namespace ImageProcessor.Web.HttpModules
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using System.Web.Hosting; using System.Web.Hosting;
using System.Web.Security;
using ImageProcessor.Helpers.Extensions; using ImageProcessor.Helpers.Extensions;
using ImageProcessor.Imaging; using ImageProcessor.Imaging;
using ImageProcessor.Web.Caching; using ImageProcessor.Web.Caching;
@ -74,16 +79,15 @@ namespace ImageProcessor.Web.HttpModules
#if NET45 #if NET45
EventHandlerTaskAsyncHelper wrapper = new EventHandlerTaskAsyncHelper(this.ContextBeginRequest); EventHandlerTaskAsyncHelper wrapper = new EventHandlerTaskAsyncHelper(this.PostAuthorizeRequest);
context.AddOnBeginRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler); context.AddOnPostAuthorizeRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler);
#else #else
context.BeginRequest += this.ContextBeginRequest; context.PostAuthorizeRequest += this.PostAuthorizeRequest;
#endif #endif
context.PreSendRequestHeaders += this.ContextPreSendRequestHeaders; context.PreSendRequestHeaders += this.ContextPreSendRequestHeaders;
} }
@ -99,7 +103,7 @@ namespace ImageProcessor.Web.HttpModules
#if NET45 #if NET45
/// <summary> /// <summary>
/// Occurs as the first event in the HTTP pipeline chain of execution when ASP.NET responds to a request. /// Occurs when the user for the current request has been authorized.
/// </summary> /// </summary>
/// <param name="sender"> /// <param name="sender">
/// The source of the event. /// The source of the event.
@ -110,7 +114,7 @@ namespace ImageProcessor.Web.HttpModules
/// <returns> /// <returns>
/// The <see cref="T:System.Threading.Tasks.Task"/>. /// The <see cref="T:System.Threading.Tasks.Task"/>.
/// </returns> /// </returns>
private Task ContextBeginRequest(object sender, EventArgs e) private Task PostAuthorizeRequest(object sender, EventArgs e)
{ {
HttpContext context = ((HttpApplication)sender).Context; HttpContext context = ((HttpApplication)sender).Context;
return this.ProcessImageAsync(context); return this.ProcessImageAsync(context);
@ -119,11 +123,11 @@ namespace ImageProcessor.Web.HttpModules
#else #else
/// <summary> /// <summary>
/// Occurs as the first event in the HTTP pipeline chain of execution when ASP.NET responds to a request. /// Occurs when the user for the current request has been authorized.
/// </summary> /// </summary>
/// <param name="sender">The source of the event.</param> /// <param name="sender">The source of the event.</param>
/// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that contains the event data.</param> /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that contains the event data.</param>
private async void ContextBeginRequest(object sender, EventArgs e) private async void PostAuthorizeRequest(object sender, EventArgs e)
{ {
HttpContext context = ((HttpApplication)sender).Context; HttpContext context = ((HttpApplication)sender).Context;
await this.ProcessImageAsync(context); await this.ProcessImageAsync(context);
@ -211,6 +215,31 @@ namespace ImageProcessor.Web.HttpModules
// Create a new cache to help process and cache the request. // Create a new cache to help process and cache the request.
DiskCache cache = new DiskCache(request, requestPath, fullPath, imageName, isRemote); DiskCache cache = new DiskCache(request, requestPath, fullPath, imageName, isRemote);
// Since we are now rewriting the path we need to check again that the current user has access
// to the rewritten path.
// Get the user for the current request
// If the user is anonymous or authentication doesn't work for this suffix avoid a NullReferenceException
// in the UrlAuthorizationModule by creating a generic identity.
string virtualCachedPath = cache.GetVirtualCachedPath();
IPrincipal user = context.User
?? new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]);
// Do we have permission to call UrlAuthorizationModule.CheckUrlAccessForPrincipal?
PermissionSet permission = new PermissionSet(PermissionState.None);
permission.AddPermission(new AspNetHostingPermission(AspNetHostingPermissionLevel.Unrestricted));
bool hasPermission = permission.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet);
bool isAllowed = true;
// Run the rewritten path past the auth system again, using the result as the default "AllowAccess" value
if (hasPermission && !context.SkipAuthorization)
{
isAllowed = UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualCachedPath, user, "GET");
}
if (isAllowed)
{
// Is the file new or updated? // Is the file new or updated?
bool isNewOrUpdated = await cache.IsNewOrUpdatedFileAsync(); bool isNewOrUpdated = await cache.IsNewOrUpdatedFileAsync();
@ -279,6 +308,11 @@ namespace ImageProcessor.Web.HttpModules
// The cached file is valid so just rewrite the path. // The cached file is valid so just rewrite the path.
context.RewritePath(cache.GetVirtualCachedPath(), false); context.RewritePath(cache.GetVirtualCachedPath(), false);
} }
else
{
throw new HttpException(403, "Access denied");
}
}
} }
/// <summary> /// <summary>

4
src/ImageProcessor.Web/NET45/Properties/AssemblyInfo.cs

@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("2.3.0.1")] [assembly: AssemblyVersion("2.3.0.2")]
[assembly: AssemblyFileVersion("2.3.0.1")] [assembly: AssemblyFileVersion("2.3.0.2")]

36
src/ImageProcessor/Helpers/Extensions/StringExtensions.cs

@ -8,9 +8,8 @@
namespace ImageProcessor.Helpers.Extensions namespace ImageProcessor.Helpers.Extensions
{ {
#region Using #region Using
using System.Diagnostics.Contracts; using System;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
@ -116,7 +115,10 @@ namespace ImageProcessor.Helpers.Extensions
/// <returns>An array of integers scraped from the String.</returns> /// <returns>An array of integers scraped from the String.</returns>
public static int[] ToPositiveIntegerArray(this string expression) public static int[] ToPositiveIntegerArray(this string expression)
{ {
Contract.Requires(!string.IsNullOrWhiteSpace(expression)); if (string.IsNullOrWhiteSpace(expression))
{
throw new ArgumentNullException("expression");
}
Regex regex = new Regex(@"\d+", RegexOptions.Compiled); Regex regex = new Regex(@"\d+", RegexOptions.Compiled);
@ -144,33 +146,9 @@ namespace ImageProcessor.Helpers.Extensions
/// <returns>True if the given string is a valid virtual path name</returns> /// <returns>True if the given string is a valid virtual path name</returns>
public static bool IsValidVirtualPathName(this string expression) public static bool IsValidVirtualPathName(this string expression)
{ {
// Check the start of the string. Uri uri;
if (expression.StartsWith("~/"))
{
// Trim the first two characters and test the path.
expression = expression.Substring(2);
return expression.IsValidPathName();
}
return false;
}
/// <summary>
/// Checks the string to see whether the value is a valid path name.
/// </summary>
/// <remarks>
/// For an explanation
/// <see cref="http://stackoverflow.com/questions/62771/how-check-if-given-string-is-legal-allowed-file-name-under-windows"/>
/// </remarks>
/// <param name="expression">The <see cref="T:System.String">String</see> instance that this method extends.</param>
/// <returns>True if the given string is a valid path name</returns>
public static bool IsValidPathName(this string expression)
{
// Create a regex of invalid characters and test it.
string invalidPathNameChars = new string(Path.GetInvalidFileNameChars());
Regex regFixPathName = new Regex("[" + Regex.Escape(invalidPathNameChars) + "]");
return !regFixPathName.IsMatch(expression); return Uri.TryCreate(expression, UriKind.Relative, out uri) && uri.IsWellFormedOriginalString();
} }
#endregion #endregion
} }

35
src/ImageProcessor/Imaging/ImageUtils.cs

@ -17,7 +17,6 @@ namespace ImageProcessor.Imaging
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
#endregion #endregion
/// <summary> /// <summary>
@ -28,7 +27,7 @@ namespace ImageProcessor.Imaging
/// <summary> /// <summary>
/// The image format regex. /// The image format regex.
/// </summary> /// </summary>
private static readonly Regex FormatRegex = new Regex(@"(\.?)(j(pg|peg)|bmp|png|gif|ti(f|ff))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.RightToLeft); private static readonly Regex FormatRegex = new Regex(@"(\.?)(j(pg|peg)|bmp|png|gif|ti(f|ff))", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.RightToLeft);
/// <summary> /// <summary>
/// Returns the correct response type based on the given request path. /// Returns the correct response type based on the given request path.
@ -41,27 +40,29 @@ namespace ImageProcessor.Imaging
/// </returns> /// </returns>
public static ResponseType GetResponseType(string request) public static ResponseType GetResponseType(string request)
{ {
foreach (Match match in FormatRegex.Matches(request)) Match match = FormatRegex.Matches(request)[0];
{
switch (match.Value.ToUpperInvariant()) switch (match.Value.ToUpperInvariant())
{ {
case "PNG": case "PNG":
case ".PNG":
return ResponseType.Png; return ResponseType.Png;
case "BMP": case "BMP":
case ".BMP":
return ResponseType.Bmp; return ResponseType.Bmp;
case "GIF": case "GIF":
case ".GIF":
return ResponseType.Gif; return ResponseType.Gif;
case "TIF": case "TIF":
case "TIFF": case "TIFF":
case ".TIF":
case ".TIFF":
return ResponseType.Tiff; return ResponseType.Tiff;
default: default:
return ResponseType.Jpeg; return ResponseType.Jpeg;
} }
} }
return ResponseType.Jpeg;
}
/// <summary> /// <summary>
/// Returns the correct image format based on the given file extension. /// Returns the correct image format based on the given file extension.
/// </summary> /// </summary>
@ -91,7 +92,7 @@ namespace ImageProcessor.Imaging
} }
} }
// TODO: Show custom exception?? // TODO: Show custom exception?
return null; return null;
} }
@ -115,7 +116,6 @@ namespace ImageProcessor.Imaging
case "Png": case "Png":
return ".png"; return ".png";
case "Tif": case "Tif":
return ".tif";
case "Tiff": case "Tiff":
return ".tif"; return ".tif";
default: default:
@ -197,9 +197,26 @@ namespace ImageProcessor.Imaging
/// <returns>True the value contains a valid image extension, otherwise false.</returns> /// <returns>True the value contains a valid image extension, otherwise false.</returns>
public static bool IsValidImageExtension(string fileName) public static bool IsValidImageExtension(string fileName)
{ {
return FormatRegex.IsMatch(fileName); return FormatRegex.IsMatch(fileName);
} }
/// <summary>
/// Returns the correct file extension for the given string input
/// </summary>
/// <param name="input">
/// The string to parse.
/// </param>
/// <returns>
/// The correct file extension for the given string input if it can find one; otherwise an empty string.
/// </returns>
public static string GetExtension(string input)
{
Match match = FormatRegex.Matches(input)[0];
return match.Success ? match.Value : string.Empty;
}
/// <summary>Returns a value indicating whether or not the given bitmap is indexed.</summary> /// <summary>Returns a value indicating whether or not the given bitmap is indexed.</summary>
/// <param name="image">The image to check</param> /// <param name="image">The image to check</param>
/// <returns>Whether or not the given bitmap is indexed.</returns> /// <returns>Whether or not the given bitmap is indexed.</returns>

2
src/ImageProcessor/Processors/Format.cs

@ -25,7 +25,7 @@ namespace ImageProcessor.Processors
/// <summary> /// <summary>
/// The regular expression to search strings for. /// The regular expression to search strings for.
/// </summary> /// </summary>
private static readonly Regex QueryRegex = new Regex(@"format=(jpeg|png|png8|bmp|gif|tif)", RegexOptions.Compiled); private static readonly Regex QueryRegex = new Regex(@"format=(j(pg|peg)|png|png8|bmp|gif|tif)", RegexOptions.Compiled);
#region IGraphicsProcessor Members #region IGraphicsProcessor Members
/// <summary> /// <summary>

4
src/ImageProcessor/Properties/AssemblyInfo.cs

@ -32,6 +32,6 @@ using System.Security;
// //
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("1.7.0.0")] [assembly: AssemblyVersion("1.7.0.1")]
[assembly: AssemblyFileVersion("1.7.0.0")] [assembly: AssemblyFileVersion("1.7.0.1")]

BIN
src/Nuget/ImageProcessor.1.6.0.1.nupkg

Binary file not shown.

BIN
src/Nuget/ImageProcessor.1.7.0.1.nupkg

Binary file not shown.

1
src/Nuget/ImageProcessor.Web.2.2.3.3.nupkg.REMOVED.git-id

@ -1 +0,0 @@
01e1999a7804bb48ba37f247dfdb1bf01f05fa62

1
src/Nuget/ImageProcessor.Web.2.3.0.0.nupkg.REMOVED.git-id

@ -1 +0,0 @@
8b33cb0b4f13802b62d2511239e212680ad67158

1
src/Nuget/ImageProcessor.Web.2.3.0.2.nupkg.REMOVED.git-id

@ -0,0 +1 @@
8c5a374f583194706fa94a269f7ab4543dc4ece6

1
src/Nuget/ImageProcessor.Web.2.3.0.3.nupkg.REMOVED.git-id

@ -0,0 +1 @@
0a367af8c6588fe2be54ef5950820a7f06f7b0f1

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

@ -41,6 +41,7 @@
<httpModules> <httpModules>
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/> <add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web"/>
</httpModules> </httpModules>
</system.web> </system.web>
<system.webServer> <system.webServer>
@ -68,13 +69,13 @@
<add url="http://www.theworldeffect.com" /> <add url="http://www.theworldeffect.com" />
</whiteList> </whiteList>
</security> </security>
<cache virtualPath="~/cache" maxDays="56"/> <cache virtualPath="~/app_data/cache" maxDays="56"/>
<processing> <processing>
<plugins> <plugins>
<plugin name="Resize"> <plugin name="Resize">
<settings> <settings>
<setting key="MaxWidth" value="1024"/> <setting key="MaxWidth" value="3000"/>
<setting key="MaxHeight" value="768"/> <setting key="MaxHeight" value="3000"/>
</settings> </settings>
</plugin> </plugin>
</plugins> </plugins>

Loading…
Cancel
Save