diff --git a/src/ImageProcessor.Playground/Program.cs b/src/ImageProcessor.Playground/Program.cs index c4cd7bc64..bcc6e517f 100644 --- a/src/ImageProcessor.Playground/Program.cs +++ b/src/ImageProcessor.Playground/Program.cs @@ -53,7 +53,7 @@ namespace ImageProcessor.PlayGround Image mask = Image.FromFile(Path.Combine(resolvedPath, "mask.png")); Image overlay = Image.FromFile(Path.Combine(resolvedPath, "imageprocessor.128.png")); //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "monster.png")); - IEnumerable files = GetFilesByExtensions(di, ".jpg"); + IEnumerable files = GetFilesByExtensions(di, ".gif"); //IEnumerable files = GetFilesByExtensions(di, ".gif", ".webp", ".bmp", ".jpg", ".png", ".tif"); foreach (FileInfo fileInfo in files) @@ -88,11 +88,10 @@ namespace ImageProcessor.PlayGround //.Resize(new Size((int)(size.Width * 1.1), 0)) //.ContentAwareResize(layer) //.Constrain(size) - //.Rotate(-64) //.Mask(mask) //.Format(new PngFormat()) //.BackgroundColor(Color.Cyan) - .ReplaceColor(Color.FromArgb(255, 223, 224), Color.FromArgb(121, 188, 255), 128) + //.ReplaceColor(Color.FromArgb(255, 223, 224), Color.FromArgb(121, 188, 255), 128) //.Resize(size) // .Resize(new ResizeLayer(size, ResizeMode.Max)) // .Resize(new ResizeLayer(size, ResizeMode.Stretch)) @@ -104,9 +103,10 @@ namespace ImageProcessor.PlayGround //.Filter(MatrixFilters.Comic) //.Flip() //.Filter(MatrixFilters.HiSatch) - //.Pixelate(8) + .Pixelate(8) + .Rotate(45) //.GaussianSharpen(10) - .Format(new PngFormat()) + //.Format(new PngFormat() { IsIndexed = true }) //.Format(new PngFormat() { IsIndexed = true }) //.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name))); .Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", Path.GetFileNameWithoutExtension(fileInfo.Name) + ".png"))); diff --git a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs index d9fea45c0..8f5f0d998 100644 --- a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs @@ -316,151 +316,161 @@ namespace ImageProcessor.Web.HttpModules } else { - requestPath = HostingEnvironment.MapPath(request.Path); - queryString = HttpUtility.UrlDecode(request.QueryString.ToString()); - } - - // Only process requests that pass our sanitizing filter. - if (!string.IsNullOrWhiteSpace(queryString)) - { - // Replace any presets in the querystring with the actual value. - queryString = this.ReplacePresetsInQueryString(queryString); - - string parts = !string.IsNullOrWhiteSpace(urlParameters) ? "?" + urlParameters : string.Empty; - string fullPath = string.Format("{0}{1}?{2}", requestPath, parts, queryString); - object resourcePath; - - if (hasMultiParams) + if (string.IsNullOrWhiteSpace(currentService.Prefix)) { - resourcePath = string.IsNullOrWhiteSpace(urlParameters) - ? new Uri(requestPath, UriKind.RelativeOrAbsolute) - : new Uri(requestPath + "?" + urlParameters, UriKind.RelativeOrAbsolute); + requestPath = HostingEnvironment.MapPath(request.Path); + queryString = HttpUtility.UrlDecode(request.QueryString.ToString()); } else { - resourcePath = requestPath; + requestPath = HttpUtility.UrlDecode(request.QueryString.ToString()); } + } - // Check whether the path is valid for other requests. - if (resourcePath == null || !currentService.IsValidRequest(resourcePath.ToString())) - { - return; - } + // If the current service doesn't require a prefix, don't fetch it. + // Let the static file handler take over. + if (string.IsNullOrWhiteSpace(currentService.Prefix) && string.IsNullOrWhiteSpace(queryString)) + { + return; + } + + // Replace any presets in the querystring with the actual value. + queryString = this.ReplacePresetsInQueryString(queryString); + + string parts = !string.IsNullOrWhiteSpace(urlParameters) ? "?" + urlParameters : string.Empty; + string fullPath = string.Format("{0}{1}?{2}", requestPath, parts, queryString); + object resourcePath; + + if (hasMultiParams) + { + resourcePath = string.IsNullOrWhiteSpace(urlParameters) + ? new Uri(requestPath, UriKind.RelativeOrAbsolute) + : new Uri(requestPath + "?" + urlParameters, UriKind.RelativeOrAbsolute); + } + else + { + resourcePath = requestPath; + } - // Create a new cache to help process and cache the request. - DiskCache cache = new DiskCache(requestPath, fullPath, queryString); - string cachedPath = cache.CachedPath; + // Check whether the path is valid for other requests. + if (resourcePath == null || !currentService.IsValidRequest(resourcePath.ToString())) + { + return; + } - // 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.VirtualCachedPath; + // Create a new cache to help process and cache the request. + DiskCache cache = new DiskCache(requestPath, fullPath, queryString); + string cachedPath = cache.CachedPath; - IPrincipal user = context.User ?? new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]); + // 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.VirtualCachedPath; - // 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); + IPrincipal user = context.User ?? new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]); - bool isAllowed = true; + // 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); - // Run the rewritten path past the authorization system again. - // We can then use the result as the default "AllowAccess" value - if (hasPermission && !context.SkipAuthorization) - { - isAllowed = UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualCachedPath, user, "GET"); - } + bool isAllowed = true; - if (isAllowed) - { - // Is the file new or updated? - bool isNewOrUpdated = cache.IsNewOrUpdatedFile(cachedPath); + // Run the rewritten path past the authorization system again. + // We can then use the result as the default "AllowAccess" value + if (hasPermission && !context.SkipAuthorization) + { + isAllowed = UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualCachedPath, user, "GET"); + } - // Only process if the file has been updated. - if (isNewOrUpdated) + if (isAllowed) + { + // Is the file new or updated? + bool isNewOrUpdated = cache.IsNewOrUpdatedFile(cachedPath); + + // Only process if the file has been updated. + if (isNewOrUpdated) + { + // Process the image. + using (ImageFactory imageFactory = new ImageFactory(preserveExifMetaData != null && preserveExifMetaData.Value)) { - // Process the image. - using (ImageFactory imageFactory = new ImageFactory(preserveExifMetaData != null && preserveExifMetaData.Value)) + using (await this.locker.LockAsync(cachedPath)) { - using (await this.locker.LockAsync(cachedPath)) - { - byte[] imageBuffer = await currentService.GetImage(resourcePath); + byte[] imageBuffer = await currentService.GetImage(resourcePath); - using (MemoryStream memoryStream = new MemoryStream(imageBuffer)) - { - // Reset the position of the stream to ensure we're reading the correct part. - memoryStream.Position = 0; + using (MemoryStream memoryStream = new MemoryStream(imageBuffer)) + { + // Reset the position of the stream to ensure we're reading the correct part. + memoryStream.Position = 0; - // Process the Image - imageFactory.Load(memoryStream).AutoProcess(queryString).Save(cachedPath); + // Process the Image + imageFactory.Load(memoryStream).AutoProcess(queryString).Save(cachedPath); - // Add to the cache. - cache.AddImageToCache(cachedPath); + // Add to the cache. + cache.AddImageToCache(cachedPath); - // Store the cached path, response type, and cache dependency in the context for later retrieval. - context.Items[CachedPathKey] = cachedPath; - context.Items[CachedResponseTypeKey] = imageFactory.CurrentImageFormat.MimeType; - context.Items[CachedResponseFileDependency] = new List { cachedPath }; - } + // Store the cached path, response type, and cache dependency in the context for later retrieval. + context.Items[CachedPathKey] = cachedPath; + context.Items[CachedResponseTypeKey] = imageFactory.CurrentImageFormat.MimeType; + context.Items[CachedResponseFileDependency] = new List { cachedPath }; } } } + } - // Image is from the cache so the mime-type will need to be set. - if (context.Items[CachedResponseTypeKey] == null) - { - string mimetype = ImageHelpers.GetMimeType(cachedPath); - - if (!string.IsNullOrEmpty(mimetype)) - { - context.Items[CachedResponseTypeKey] = mimetype; - } - } + // Image is from the cache so the mime-type will need to be set. + if (context.Items[CachedResponseTypeKey] == null) + { + string mimetype = ImageHelpers.GetMimeType(cachedPath); - if (context.Items[CachedResponseFileDependency] == null) + if (!string.IsNullOrEmpty(mimetype)) { - context.Items[CachedResponseFileDependency] = new List { cachedPath }; + context.Items[CachedResponseTypeKey] = mimetype; } + } - string incomingEtag = context.Request.Headers["If" + "-None-Match"]; + if (context.Items[CachedResponseFileDependency] == null) + { + context.Items[CachedResponseFileDependency] = new List { cachedPath }; + } - if (incomingEtag != null && !isNewOrUpdated) - { - // Set the Content-Length header so the client doesn't wait for - // content but keeps the connection open for other requests. - context.Response.AddHeader("Content-Length", "0"); - context.Response.StatusCode = (int)HttpStatusCode.NotModified; - context.Response.SuppressContent = true; + string incomingEtag = context.Request.Headers["If" + "-None-Match"]; - if (isFileLocal) - { - // Set the headers and quit. - // Some services might only provide filename so we can't monitor for the browser. - this.SetHeaders( - context, - (string)context.Items[CachedResponseTypeKey], - Path.GetFileName(requestPath) == requestPath ? new List { cachedPath } : new List { requestPath, cachedPath }); - } - else - { - this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey], new List { cachedPath }); - } + if (incomingEtag != null && !isNewOrUpdated) + { + // Set the Content-Length header so the client doesn't wait for + // content but keeps the connection open for other requests. + context.Response.AddHeader("Content-Length", "0"); + context.Response.StatusCode = (int)HttpStatusCode.NotModified; + context.Response.SuppressContent = true; - // Complete the requests but don't abort the thread. - context.ApplicationInstance.CompleteRequest(); - return; + if (isFileLocal) + { + // Set the headers and quit. + // Some services might only provide filename so we can't monitor for the browser. + this.SetHeaders( + context, + (string)context.Items[CachedResponseTypeKey], + Path.GetFileName(requestPath) == requestPath ? new List { cachedPath } : new List { requestPath, cachedPath }); + } + else + { + this.SetHeaders(context, (string)context.Items[CachedResponseTypeKey], new List { cachedPath }); } - // The cached file is valid so just rewrite the path. - context.RewritePath(virtualCachedPath, false); - } - else - { - throw new HttpException(403, "Access denied"); + // Complete the requests but don't abort the thread. + context.ApplicationInstance.CompleteRequest(); + return; } + + // The cached file is valid so just rewrite the path. + context.RewritePath(virtualCachedPath, false); + } + else + { + throw new HttpException(403, "Access denied"); } } }