/// <summary> /// This is where we filter requests and intercept those that want resizing performed. /// We first strip FakeExtension, then verify the remaining file extension is supported for decoding. /// We fire URL rewriting events. If the result includes any supported querystring params afterwards, we process the request. Otherwise we let it fall back to IIS/ASP.NET. /// If the file doesn't exist, we also ignore the request. They're going to cause a 404 anyway. /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected virtual void CheckRequest_PostAuthorizeRequest(object sender, EventArgs e) { //Skip requests if the Request object isn't populated HttpApplication app = sender as HttpApplication; if (app == null) return; if (app.Context == null) return; if (app.Context.Request == null) return; conf.FirePostAuthorizeRequest(this, app.Context); //Allow handlers of the above event to change filePath/pathinfo so we can successfull test the extension string originalPath = conf.PreRewritePath; //Trim fake extensions so IsAcceptedImageType will work properly string filePath = conf.TrimFakeExtensions(originalPath); //Is this an image request? Checks the file extension for .jpg, .png, .tiff, etc. if (conf.SkipFileTypeCheck || conf.IsAcceptedImageType(filePath)) { //Copy the querystring so we can mod it to death without messing up other stuff. NameValueCollection q = conf.ModifiedQueryString; //Call URL rewriting events UrlEventArgs ue = new UrlEventArgs(filePath, q); conf.FireRewritingEvents(this, app.Context,ue); //Pull data back out of event object, resolving app-relative paths string virtualPath = PathUtils.ResolveAppRelativeAssumeAppRelative(ue.VirtualPath); q = ue.QueryString; //Store the modified querystring in request for use by VirtualPathProviders conf.ModifiedQueryString = q; // app.Context.Items["modifiedQueryString"] = q; //See if resizing is wanted (i.e. one of the querystring commands is present). //Called after processPath so processPath can add them if needed. //Checks for thumnail, format, width, height, maxwidth, maxheight and a lot more if (conf.HasPipelineDirective(q)) { //Who's the user IPrincipal user = app.Context.User as IPrincipal; // no user (must be anonymous...).. Or authentication doesn't work for this suffix. Whatever, just avoid a nullref in the UrlAuthorizationModule if (user == null) user = new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]); //Do we have permission to call UrlAuthorizationModule.CheckUrlAccessForPrincipal? bool canCheckUrl = System.Security.SecurityManager.IsGranted(new System.Security.Permissions.SecurityPermission(System.Security.Permissions.PermissionState.Unrestricted)); //Run the rewritten path past the auth system again, using the result as the default "AllowAccess" value bool isAllowed = true; if (canCheckUrl && !app.Context.SkipAuthorization) try { isAllowed = UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualPath, user, "GET"); } catch (NotImplementedException) { } //For MONO support IUrlAuthorizationEventArgs authEvent = new UrlAuthorizationEventArgs(virtualPath, new NameValueCollection(q), isAllowed); //Allow user code to deny access, but not modify the url or querystring. conf.FireAuthorizeImage(this, app.Context, authEvent); if (!authEvent.AllowAccess) throw new ImageProcessingException(403, "Access denied", "Access denied"); //Does the file exist physically? (false if VppUsage=always or file is missing) bool existsPhysically = (conf.VppUsage != VppUsageOption.Always) && System.IO.File.Exists(HostingEnvironment.MapPath(virtualPath)); //If not present physically (and VppUsage!=never), try to get the virtual file. Null indicates a missing file IVirtualFile vf = (conf.VppUsage != VppUsageOption.Never && !existsPhysically) ? conf.GetFile(virtualPath, q) : null; //Only process files that exist if (existsPhysically || vf != null) { try{ HandleRequest(app.Context, virtualPath, q, vf); //Catch not found exceptions } catch (System.IO.FileNotFoundException notFound) { //Some VPPs are optimisitic , or could be a race condition FileMissing(app.Context, virtualPath, q); throw new ImageMissingException("The specified resource could not be located", "File not found", notFound); } catch (System.IO.DirectoryNotFoundException notFound) { FileMissing(app.Context, virtualPath, q); throw new ImageMissingException("The specified resource could not be located", "File not found", notFound); } } else FileMissing(app.Context, virtualPath, q); } } }
public PostAuthorizeResult PostAuthorize() { conf.FirePostAuthorizeRequest(sender as IHttpModule, context); conf.FireHeartbeat(); //Allow handlers of the above event to change filePath/pathinfo so we can successfully test the extension string originalPath = conf.PreRewritePath; //Trim fake extensions so IsAcceptedImageType will work properly string filePath = conf.TrimFakeExtensions(originalPath); //Is this an image request? Checks the file extension for .jpg, .png, .tiff, etc. if (!(conf.SkipFileTypeCheck || conf.IsAcceptedImageType(filePath))) { return(PostAuthorizeResult.UnrelatedFileType); } //Copy the querystring so we can mod it to death without messing up other stuff. NameValueCollection queryCopy = new NameValueCollection(conf.ModifiedQueryString); Performance.GlobalPerf.Singleton.PreRewriteQuery(queryCopy); //Call URL rewriting events UrlEventArgs ue = new UrlEventArgs(filePath, queryCopy); conf.FireRewritingEvents(sender, context, ue); //Pull data back out of event object, resolving app-relative paths RewrittenVirtualPath = PathUtils.ResolveAppRelativeAssumeAppRelative(ue.VirtualPath); RewrittenQuery = ue.QueryString; RewrittenInstructions = new Instructions(RewrittenQuery); //Store the modified querystring in request for use by VirtualPathProviders during URL Authorization conf.ModifiedQueryString = RewrittenQuery; RewrittenVirtualPathIsAcceptedImageType = conf.IsAcceptedImageType(RewrittenVirtualPath); RewrittenQueryHasDirective = conf.HasPipelineDirective(RewrittenQuery); RewrittenMappedPath = HostingEnvironment.MapPath(RewrittenVirtualPath); ProcessingIndicated = false; CachingIndicated = false; if (RewrittenQueryHasDirective) { //By default, we process it if is both (a) a recognized image extension, and (b) has a resizing directive (not just 'cache'). //Check for resize directive by removing ('non-resizing' items from the current querystring) ProcessingIndicated = RewrittenInstructions.Process == ProcessWhen.Always || ((RewrittenInstructions.Process == ProcessWhen.Default || RewrittenInstructions.Process == null) && RewrittenVirtualPathIsAcceptedImageType && conf.HasPipelineDirective(RewrittenInstructions.Exclude("cache", "process", "useresizingpipeline", "404", "404.filterMode", "404.except"))); CachingIndicated = RewrittenInstructions.Cache == ServerCacheMode.Always || ((RewrittenInstructions.Cache == ServerCacheMode.Default || RewrittenInstructions.Cache == null) && ProcessingIndicated); //Resolve the 'cache' setting to 'no' unless we want it cache. TODO: Understand this better if (!CachingIndicated) { RewrittenInstructions.Cache = ServerCacheMode.No; } Performance.GlobalPerf.Singleton.QueryRewrittenWithDirective(RewrittenVirtualPath); } if (RewrittenQueryHasDirective || conf.AuthorizeAllImages) { var authEvent = new UrlAuthorizationEventArgs(RewrittenVirtualPath, new NameValueCollection(RewrittenQuery), true); //Allow user code to deny access, but not modify the URL or querystring. conf.FireAuthorizeImage(sender, context, authEvent); if (!authEvent.AllowAccess) { return(PostAuthorizeResult.AccessDenied403); } } return(PostAuthorizeResult.Complete); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="virtualPath"></param> /// <param name="settings"></param> public void ExecuteVirtualPathResult(ControllerContext context, string virtualPath, NameValueCollection settings) { var app = (HttpApplication) context.HttpContext.GetService(typeof(HttpApplication)); NameValueCollection q = settings; //Call URL rewriting events UrlEventArgs ue = new UrlEventArgs(virtualPath, q); conf.FireRewritingEvents(null, app.Context,ue); //Pull data back out of event object, resolving app-relative paths virtualPath = PathUtils.ResolveAppRelativeAssumeAppRelative(ue.VirtualPath); q = ue.QueryString; //Store the modified querystring in request for use by VirtualPathProviders conf.ModifiedQueryString = q; bool isAllowed = true; if (this.ReauthorizeFinalPath){ //Who's the user IPrincipal user = app.Context.User as IPrincipal; // no user (must be anonymous...).. Or authentication doesn't work for this suffix. Whatever, just avoid a nullref in the UrlAuthorizationModule if (user == null) user = new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]); //Do we have permission to call UrlAuthorizationModule.CheckUrlAccessForPrincipal? bool canCheckUrl = System.Security.SecurityManager.IsGranted(new System.Security.Permissions.SecurityPermission(System.Security.Permissions.PermissionState.Unrestricted)); //Run the rewritten path past the auth system again, using the result as the default "AllowAccess" value if (canCheckUrl) try { isAllowed = UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualPath, user, "GET"); } catch (NotImplementedException) { } //For MONO support } //Allow user code to deny access, but not modify the url or querystring. IUrlAuthorizationEventArgs authEvent = new UrlAuthorizationEventArgs(virtualPath, new NameValueCollection(q), isAllowed); conf.FireAuthorizeImage(null, app.Context, authEvent); if (!authEvent.AllowAccess) throw new ImageProcessingException(403, "Access denied", "Access denied"); //Does the file exist physically? (false if VppUsage=always or file is missing) bool existsPhysically = (conf.VppUsage != VppUsageOption.Always) && System.IO.File.Exists(HostingEnvironment.MapPath(virtualPath)); //If not present physically (and VppUsage!=never), try to get the virtual file. Null indicates a missing file IVirtualFile vf = (conf.VppUsage != VppUsageOption.Never && !existsPhysically) ? conf.GetFile(virtualPath, q) : null; //Only process files that exist if (existsPhysically || vf != null) { try{ ExecuteVirtualFileResult(app.Context, virtualPath, q, vf); //Catch not found exceptions } catch (System.IO.FileNotFoundException notFound) { //Some VPPs are optimisitic , or could be a race condition FileMissing(app.Context, virtualPath, q); throw new ImageMissingException("The specified resource could not be located", "File not found", notFound); } } else FileMissing(app.Context, virtualPath, q); }