Пример #1
0
        public void Created(ShapeCreatedContext context)
        {
            if (!IsActivable())
            {
                return;
            }

            if (context.ShapeType != "Layout" &&
                context.ShapeType != "DocumentZone" &&
                context.ShapeType != "PlaceChildContent" &&
                context.ShapeType != "ContentZone" &&
                context.ShapeType != "ShapeTracingMeta" &&
                context.ShapeType != "ShapeTracingTemplates" &&
                context.ShapeType != "DateTimeRelative")
            {
                var shapeMetadata = (ShapeMetadata)context.Shape.Metadata;
                var currentTheme  = _themeManager.GetRequestTheme(_workContext.HttpContext.Request.RequestContext);
                var shapeTable    = _shapeTableManager.GetShapeTable(currentTheme.Id);

                if (!shapeTable.Descriptors.ContainsKey(shapeMetadata.Type))
                {
                    return;
                }

                shapeMetadata.Wrappers.Add("ShapeTracingWrapper");
                shapeMetadata.OnDisplaying(OnDisplaying);
            }
        }
Пример #2
0
        public ActionResult Create(string template, string alternate, string returnUrl)
        {
            if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to create templates")) && !Request.IsLocal)
            {
                return(new HttpUnauthorizedResult());
            }

            alternate = alternate.Replace("__", "-").Replace("_", ".");

            var currentTheme      = _themeManager.GetRequestTheme(Request.RequestContext);
            var alternateFilename = Server.MapPath(Path.Combine(currentTheme.Location, currentTheme.Id, "Views", alternate));

            // use same extension as template, or ".cshtml" if it's a code template))
            if (_webSiteFolder.FileExists(template))
            {
                alternateFilename += Path.GetExtension(template);

                using (var stream = System.IO.File.Create(alternateFilename)) {
                    _webSiteFolder.CopyFileTo(template, stream);
                }
            }
            else
            {
                alternateFilename += ".cshtml";
                using (System.IO.File.Create(alternateFilename)) {}
            }

            return(this.RedirectLocal(returnUrl));
        }
        private void TraverseResouceShapes(IList <ResourceRequiredContext> resources, ResourceType resourceType, Action <ShapeTable, ResourceRequiredContext, string> processor)
        {
            var shapeKeyPrefix = resourceType == ResourceType.Style ? "Style__" : "Script__";

            var currentTheme = _themeManager.GetRequestTheme(_httpContextAccessor.Current().Request.RequestContext);
            var shapeTable   = _shapeTableLocator.Lookup(currentTheme.Id);

            foreach (var resource in resources)
            {
                var fullPath = resource.Resource.GetFullPath();
                if (!string.IsNullOrEmpty(fullPath))
                {
                    var shapeName = StaticFileBindingStrategy.GetAlternateShapeNameFromFileName(fullPath);
                    var shapeKey  = shapeKeyPrefix + shapeName;

                    // Simply included CDN stylesheets are not in the ShapeTable, so we have to check
                    if (shapeTable.Bindings.ContainsKey(shapeKey))
                    {
                        processor(shapeTable, resource, shapeKey);
                    }
                    else
                    {
                        // Maybe the original binding was removed previously and the combined shape binding remains.
                        shapeKey = CombinedShapeKey(shapeKey);
                        if (shapeTable.Bindings.ContainsKey(shapeKey))
                        {
                            processor(shapeTable, resource, shapeKey);
                        }
                    }
                }
            }
        }
 public Func <WorkContext, T> Get <T>(string name)
 {
     if (name == "CurrentTheme")
     {
         var currentTheme = _themeManager.GetRequestTheme(_httpContextAccessor.Current().Request.RequestContext);
         return(ctx => (T)(object)currentTheme);
     }
     return(null);
 }
        public Func <WorkContext, T> Get <T>(string name)
        {
            if (name == "CurrentTheme")
            {
                var context      = _httpContextAccessor.Current();
                var currentTheme = context != null && context.Request != null
                    ? _themeManager.GetRequestTheme(context.Request.RequestContext)
                    : null;

                return(ctx => (T)(object)currentTheme);
            }
            return(null);
        }
Пример #6
0
        protected virtual IDictionary <string, object> GetCacheKeyParameters(ActionExecutingContext filterContext)
        {
            var result = new Dictionary <string, object>();

            // Vary by action parameters.
            foreach (var p in filterContext.ActionParameters)
            {
                result.Add("PARAM:" + p.Key, p.Value);
            }

            // Vary by theme.
            result.Add("theme", _themeManager.GetRequestTheme(filterContext.RequestContext).Id.ToLowerInvariant());

            // Vary by configured query string parameters.
            var queryString = filterContext.RequestContext.HttpContext.Request.QueryString;

            foreach (var key in queryString.AllKeys)
            {
                if (key == null || (CacheSettings.VaryByQueryStringParameters != null && !CacheSettings.VaryByQueryStringParameters.Contains(key)))
                {
                    continue;
                }
                result[key] = queryString[key];
            }

            // Vary by configured request headers.
            var requestHeaders = filterContext.RequestContext.HttpContext.Request.Headers;

            foreach (var varyByRequestHeader in CacheSettings.VaryByRequestHeaders)
            {
                if (requestHeaders.AllKeys.Contains(varyByRequestHeader))
                {
                    result["HEADER:" + varyByRequestHeader] = requestHeaders[varyByRequestHeader];
                }
            }


            // Vary by request culture if configured.
            if (CacheSettings.VaryByCulture)
            {
                result["culture"] = _workContext.CurrentCulture.ToLowerInvariant();
            }

            // Vary by authentication state if configured.
            if (CacheSettings.VaryByAuthenticationState)
            {
                result["auth"] = filterContext.HttpContext.User.Identity.IsAuthenticated.ToString().ToLowerInvariant();
            }

            return(result);
        }
Пример #7
0
        private string ComputeCacheKey(WidgetPart widgetPart, ControllerContext controllerContext)
        {
            var sb            = new StringBuilder();
            var workContext   = controllerContext.GetWorkContext();
            var theme         = _themeManager.GetRequestTheme(controllerContext.RequestContext).Id;
            var url           = GetAbsoluteUrl(controllerContext);
            var settings      = GetCacheSettings(workContext);
            var varyByHeaders = new HashSet <string>(settings.VaryByRequestHeaders);

            // Different tenants with the same urls have different entries.
            varyByHeaders.Add("HOST");

            var queryString    = controllerContext.RequestContext.HttpContext.Request.QueryString;
            var requestHeaders = controllerContext.RequestContext.HttpContext.Request.Headers;
            var parameters     = new Dictionary <string, object>();

            foreach (var key in queryString.AllKeys.Where(x => x != null))
            {
                parameters[key] = queryString[key];
            }

            foreach (var header in varyByHeaders)
            {
                if (requestHeaders.AllKeys.Contains(header))
                {
                    parameters["HEADER:" + header] = requestHeaders[header];
                }
            }

            sb.Append("layer=").Append(widgetPart.LayerId.GetValueOrDefault().ToString(CultureInfo.InvariantCulture)).Append(";");
            sb.Append("zone=").Append(widgetPart.Zone).Append(";");
            sb.Append("widget=").Append(widgetPart.Id.ToString(CultureInfo.InvariantCulture)).Append(";");
            sb.Append("tenant=").Append(_shellSettings.Name).Append(";");
            sb.Append("url=").Append(url.ToLowerInvariant()).Append(";");

            if (settings.VaryByCulture)
            {
                sb.Append("culture=").Append(workContext.CurrentCulture.ToLowerInvariant()).Append(";");
            }

            sb.Append("theme=").Append(theme.ToLowerInvariant()).Append(";");

            foreach (var pair in parameters)
            {
                sb.AppendFormat("{0}={1};", pair.Key.ToLowerInvariant(), Convert.ToString(pair.Value).ToLowerInvariant());
            }

            return(sb.ToString());
        }
        /// <summary>
        /// 在操作结果执行之前调用。
        /// </summary>
        /// <param name="filterContext">筛选器上下文。</param>
        public void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var viewResultBase = filterContext.Result as ViewResultBase;

            if (viewResultBase == null)
            {
                return;
            }

            if (_workContext.CurrentTheme == null)
            {
                _workContext.CurrentTheme = _themeManager.GetRequestTheme(filterContext.RequestContext);
            }

            viewResultBase.ViewEngineCollection = new ViewEngineCollection(new IViewEngine[] { _layoutAwareViewEngine });
        }
        private bool TransformRedirect(ActionExecutedContext filterContext)
        {
            // removes the target of the redirection from cache after a POST

            if (filterContext.Result == null)
            {
                throw new ArgumentNullException();
            }

            // status code can't be tested at this point, so test the result type instead
            if (!filterContext.HttpContext.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) ||
                !(filterContext.Result is RedirectResult))
            {
                return(false);
            }

            Logger.Debug("Redirect on POST");
            var redirectUrl = ((RedirectResult)(filterContext.Result)).Url;

            if (!VirtualPathUtility.IsAbsolute(redirectUrl))
            {
                var applicationRoot = filterContext.HttpContext.Request.ToRootUrlString();
                if (redirectUrl.StartsWith(applicationRoot, StringComparison.OrdinalIgnoreCase))
                {
                    redirectUrl = redirectUrl.Substring(applicationRoot.Length);
                }
            }

            // querystring invariant key
            var invariantCacheKey = ComputeCacheKey(
                _shellSettings.Name,
                redirectUrl,
                () => _workContext.CurrentCulture,
                _themeManager.GetRequestTheme(filterContext.RequestContext).Id,
                null
                );

            _cacheService.RemoveByTag(invariantCacheKey);

            filterContext.Result = new RedirectResult(redirectUrl, ((RedirectResult)filterContext.Result).Permanent);
            filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);

            return(true);
        }
Пример #10
0
        public void Displaying(ShapeDisplayingContext context)
        {
            var shape   = context.Shape;
            var content = shape.ContentItem as IContent;

            if (content == null)
            {
                return;
            }

            if (!IsActivable(content))
            {
                return;
            }

            var shapeMetadata = (ShapeMetadata)context.Shape.Metadata;

            if (shapeMetadata.Wrappers.Contains("InlineShapeWrapper"))
            {
                return;
            }

            if (shapeMetadata.Type != "Widget" &&
                shapeMetadata.Type != "EditorTemplate")
            {
                var currentTheme = _themeManager.GetRequestTheme(_workContext.HttpContext.Request.RequestContext);
                var shapeTable   = _shapeTableManager.GetShapeTable(currentTheme.Id);

                foreach (var alternate in shapeMetadata.Alternates)
                {
                    if (shapeTable.Descriptors.ContainsKey(alternate + "_InlineEdit"))
                    {
                        shapeMetadata.Wrappers.Add("InlineShapeWrapper");
                        return;
                    }
                }

                if (shapeTable.Descriptors.ContainsKey(shapeMetadata.Type + "_InlineEdit"))
                {
                    shapeMetadata.Wrappers.Add("InlineShapeWrapper");
                }
            }
        }
Пример #11
0
        public void OnDisplaying(ShapeDisplayingContext context)
        {
            if (!IsActivable())
            {
                return;
            }

            var shape         = context.Shape;
            var shapeMetadata = (ShapeMetadata)context.Shape.Metadata;
            var currentTheme  = _themeManager.GetRequestTheme(_workContext.HttpContext.Request.RequestContext);
            var shapeTable    = _shapeTableManager.GetShapeTable(currentTheme.Id);

            if (!shapeMetadata.Wrappers.Contains("ShapeTracingWrapper"))
            {
                return;
            }

            var descriptor = shapeTable.Descriptors[shapeMetadata.Type];

            // dump the Shape's content
            var dump = new ObjectDumper(6).Dump(context.Shape, "Model");

            var sb = new StringBuilder();

            ConvertToJSon(dump, sb);
            shape._Dump = sb.ToString();

            shape.Template         = null;
            shape.OriginalTemplate = descriptor.BindingSource;

            foreach (var extension in new[] { ".cshtml", ".aspx" })
            {
                foreach (var alternate in shapeMetadata.Alternates.Reverse().Concat(new [] { shapeMetadata.Type }))
                {
                    var alternateFilename = FormatShapeFilename(alternate, shapeMetadata.Type, shapeMetadata.DisplayType, currentTheme.Location + "/" + currentTheme.Id, extension);
                    if (_webSiteFolder.FileExists(alternateFilename))
                    {
                        shape.Template = alternateFilename;
                    }
                }
            }

            if (shape.Template == null)
            {
                shape.Template = descriptor.BindingSource;
            }

            if (shape.Template == null)
            {
                shape.Template = descriptor.Bindings.Values.FirstOrDefault().BindingSource;
            }

            if (shape.OriginalTemplate == null)
            {
                shape.OriginalTemplate = descriptor.Bindings.Values.FirstOrDefault().BindingSource;
            }

            try {
                // we know that templates are classes if they contain ':'
                if (!shape.Template.Contains(":") && _webSiteFolder.FileExists(shape.Template))
                {
                    shape.TemplateContent = _webSiteFolder.ReadFile(shape.Template);
                }
            }
            catch {
                // the url might be invalid in case of a code shape
            }

            if (shapeMetadata.PlacementSource != null && _webSiteFolder.FileExists(shapeMetadata.PlacementSource))
            {
                context.Shape.PlacementContent = _webSiteFolder.ReadFile(shapeMetadata.PlacementSource);
            }

            // Inject the Zone name
            if (shapeMetadata.Type == "Zone")
            {
                shape.Hint = ((Zone)shape).ZoneName;
            }

            shape.ShapeId = _shapeId++;
        }
Пример #12
0
        protected virtual bool RequestIsCacheable(ActionExecutingContext filterContext)
        {
            var itemDescriptor = string.Empty;

            if (Logger.IsEnabled(LogLevel.Debug))
            {
                var url        = filterContext.RequestContext.HttpContext.Request.RawUrl;
                var area       = filterContext.RequestContext.RouteData.Values["area"];
                var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
                var action     = filterContext.ActionDescriptor.ActionName;
                var culture    = _workContext.CurrentCulture.ToLowerInvariant();
                var auth       = filterContext.HttpContext.User.Identity.IsAuthenticated.ToString().ToLowerInvariant();
                var theme      = _themeManager.GetRequestTheme(filterContext.RequestContext).Id.ToLowerInvariant();

                itemDescriptor = string.Format("{0} (Area: {1}, Controller: {2}, Action: {3}, Culture: {4}, Theme: {5}, Auth: {6})", url, area, controller, action, culture, theme, auth);
            }

            // Respect OutputCacheAttribute if applied.
            var actionAttributes     = filterContext.ActionDescriptor.GetCustomAttributes(typeof(OutputCacheAttribute), true);
            var controllerAttributes = filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(OutputCacheAttribute), true);
            var outputCacheAttribute = actionAttributes.Concat(controllerAttributes).Cast <OutputCacheAttribute>().FirstOrDefault();

            if (outputCacheAttribute != null)
            {
                if (outputCacheAttribute.Duration <= 0 || outputCacheAttribute.NoStore || outputCacheAttribute.LocationIsIn(OutputCacheLocation.Downstream, OutputCacheLocation.Client, OutputCacheLocation.None))
                {
                    Logger.Debug("Request for item '{0}' ignored based on OutputCache attribute.", itemDescriptor);
                    return(false);
                }
            }

            // Don't cache POST requests.
            if (filterContext.HttpContext.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase))
            {
                Logger.Debug("Request for item '{0}' ignored because HTTP method is POST.", itemDescriptor);
                return(false);
            }

            // Don't cache admin section requests.
            if (AdminFilter.IsApplied(new RequestContext(filterContext.HttpContext, new RouteData())))
            {
                Logger.Debug("Request for item '{0}' ignored because it's in admin section.", itemDescriptor);
                return(false);
            }

            // Ignore authenticated requests unless the setting to cache them is true.
            if (_workContext.CurrentUser != null && !CacheSettings.CacheAuthenticatedRequests)
            {
                Logger.Debug("Request for item '{0}' ignored because user is authenticated.", itemDescriptor);
                return(false);
            }

            // Don't cache ignored URLs.
            if (IsIgnoredUrl(filterContext.RequestContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath, CacheSettings.IgnoredUrls))
            {
                Logger.Debug("Request for item '{0}' ignored because the URL is configured as ignored.", itemDescriptor);
                return(false);
            }

            // Don't cache if individual route configuration says no.
            if (_cacheRouteConfig != null && _cacheRouteConfig.Duration == 0)
            {
                Logger.Debug("Request for item '{0}' ignored because route is configured to not be cached.", itemDescriptor);
                return(false);
            }

            // Ignore requests with the refresh key on the query string.
            foreach (var key in filterContext.RequestContext.HttpContext.Request.QueryString.AllKeys)
            {
                if (String.Equals(_refreshKey, key, StringComparison.OrdinalIgnoreCase))
                {
                    Logger.Debug("Request for item '{0}' ignored because refresh key was found on query string.", itemDescriptor);
                    return(false);
                }
            }

            return(true);
        }
        private bool TransformRedirect(ActionExecutedContext filterContext)
        {
            if (filterContext.Result == null)
            {
                throw new ArgumentNullException();
            }

            // status code can't be tested at this point, so test the result type instead
            if (!filterContext.HttpContext.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) ||
                !(filterContext.Result is RedirectResult))
            {
                return(false);
            }

            Logger.Debug("Redirect on POST");
            var redirectUrl = ((RedirectResult)(filterContext.Result)).Url;

            if (!VirtualPathUtility.IsAbsolute(redirectUrl))
            {
                var applicationRoot = filterContext.HttpContext.Request.ToRootUrlString();
                if (redirectUrl.StartsWith(applicationRoot, StringComparison.OrdinalIgnoreCase))
                {
                    redirectUrl = redirectUrl.Substring(applicationRoot.Length);
                }
            }

            // querystring invariant key
            var invariantCacheKey = ComputeCacheKey(
                _shellSettings.Name,
                redirectUrl,
                () => _workContext.CurrentCulture,
                _themeManager.GetRequestTheme(filterContext.RequestContext).Id,
                null
                );

            _cacheService.RemoveByTag(invariantCacheKey);

            // adding a refresh key so that the next request will not be cached
            var epIndex = redirectUrl.IndexOf('?');
            var qs      = new NameValueCollection();

            if (epIndex > 0)
            {
                qs = HttpUtility.ParseQueryString(redirectUrl.Substring(epIndex));
            }

            var refresh = _now.Ticks;

            qs.Remove(RefreshKey);

            qs.Add(RefreshKey, refresh.ToString("x"));
            var querystring = "?" + string.Join("&", Array.ConvertAll(qs.AllKeys, k => string.Format("{0}={1}", HttpUtility.UrlEncode(k), HttpUtility.UrlEncode(qs[k]))));

            if (epIndex > 0)
            {
                redirectUrl = redirectUrl.Substring(0, epIndex) + querystring;
            }
            else
            {
                redirectUrl = redirectUrl + querystring;
            }

            filterContext.Result = new RedirectResult(redirectUrl, ((RedirectResult)filterContext.Result).Permanent);
            filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);

            return(true);
        }
Пример #14
0
        public override IList <ResourceRequiredContext> BuildRequiredResources(string stringResourceType)
        {
            // It's necessary to make a copy since making a change to the local variable also changes the private one.
            var resources = new List <ResourceRequiredContext>(base.BuildRequiredResources(stringResourceType));

            var settingsPart = _cacheManager.Get("Piedone.Combinator.CombinatorSettingsPart", ctx =>
            {
                _combinatorEventMonitor.MonitorConfigurationChanged(ctx);

                return(_siteService.GetSiteSettings().As <CombinatorSettingsPart>());
            });

            if (resources.Count == 0 ||
                Orchard.UI.Admin.AdminFilter.IsApplied(_httpContextAccessor.Current().Request.RequestContext) && !settingsPart.EnableForAdmin)
            {
                return(resources);
            }

            var resourceType = ResourceTypeHelper.StringTypeToEnum(stringResourceType);

            try
            {
                var settings = new CombinatorSettings
                {
                    CombineCDNResources     = settingsPart.CombineCDNResources,
                    EmbedCssImages          = settingsPart.EmbedCssImages,
                    EmbeddedImagesMaxSizeKB = settingsPart.EmbeddedImagesMaxSizeKB,
                    MinifyResources         = settingsPart.MinifyResources
                };

                if (!String.IsNullOrEmpty(settingsPart.CombinationExcludeRegex))
                {
                    settings.CombinationExcludeFilter = new Regex(settingsPart.CombinationExcludeRegex);
                }
                if (!String.IsNullOrEmpty(settingsPart.EmbedCssImagesStylesheetExcludeRegex))
                {
                    settings.EmbedCssImagesStylesheetExcludeFilter = new Regex(settingsPart.EmbedCssImagesStylesheetExcludeRegex);
                }
                if (!String.IsNullOrEmpty(settingsPart.MinificationExcludeRegex))
                {
                    settings.MinificationExcludeFilter = new Regex(settingsPart.MinificationExcludeRegex);
                }

                if (!String.IsNullOrEmpty(settingsPart.ResourceSetRegexes))
                {
                    var setRegexes = new List <Regex>();
                    foreach (var regex in settingsPart.ResourceSetRegexes.Trim().Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        if (!String.IsNullOrEmpty(regex))
                        {
                            setRegexes.Add(new Regex(regex));
                        }
                    }
                    settings.ResourceSetFilters = setRegexes.ToArray();
                }

                if (resourceType == ResourceType.Style)
                {
                    // Checking for overridden stylesheets
                    var currentTheme = _themeManager.GetRequestTheme(_httpContextAccessor.Current().Request.RequestContext);
                    var shapeTable   = _shapeTableLocator.Lookup(currentTheme.Id);

                    foreach (var resource in resources)
                    {
                        var shapeName = StylesheetBindingStrategy.GetAlternateShapeNameFromFileName(resource.Resource.GetFullPath());

                        // Simply included CDN stylesheets are not in the ShapeTable, so we have to check
                        if (shapeTable.Bindings.ContainsKey("Style__" + shapeName))
                        {
                            var binding = shapeTable.Bindings["Style__" + shapeName].BindingSource;
                            resource.Resource.SetUrl(binding, null);
                        }
                    }

                    return(_combinatorService.CombineStylesheets(resources, settings));
                }
                else if (resourceType == ResourceType.JavaScript)
                {
                    return(_combinatorService.CombineScripts(resources, settings));
                }

                return(base.BuildRequiredResources(stringResourceType));
            }
            catch (Exception ex)
            {
                if (ex.IsFatal())
                {
                    throw;
                }
                Logger.Error(ex, "Error when combining " + resourceType + " files");
                return(base.BuildRequiredResources(stringResourceType));
            }
        }
Пример #15
0
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // only cache view results, but don't return already as we still need to process redirections
            if (!(filterContext.Result is ViewResultBase) && !(AuthorizedContentTypes.Contains(filterContext.HttpContext.Response.ContentType)))
            {
                _filter = null;
            }

            // ignore error results from cache
            if (filterContext.HttpContext.Response.StatusCode != (int)HttpStatusCode.OK)
            {
                // Never cache non-200 responses.
                filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                filterContext.HttpContext.Response.Cache.SetNoStore();
                filterContext.HttpContext.Response.Cache.SetMaxAge(new TimeSpan(0));

                _filter = null;
                return;
            }

            // if the result of a POST is a Redirect, remove any Cache Item for this url
            // so that the redirected client gets a fresh result
            // also add a random token to the query string so that public cachers (IIS, proxies, ...) don't return cached content
            // i.e., Comment creation

            // ignore in admin
            if (AdminFilter.IsApplied(new RequestContext(filterContext.HttpContext, new RouteData())))
            {
                return;
            }

            _workContext = _workContextAccessor.GetContext();

            // ignore authenticated requests
            if (_workContext.CurrentUser != null)
            {
                return;
            }

            // todo: look for RedirectToRoute to, or intercept 302s

            if (filterContext.HttpContext.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) &&
                filterContext.Result is RedirectResult)
            {
                Logger.Debug("Redirect on POST");
                var redirectUrl = ((RedirectResult)filterContext.Result).Url;

                if (!VirtualPathUtility.IsAbsolute(redirectUrl))
                {
                    var applicationRoot = filterContext.HttpContext.Request.ToRootUrlString();
                    if (redirectUrl.StartsWith(applicationRoot, StringComparison.OrdinalIgnoreCase))
                    {
                        redirectUrl = redirectUrl.Substring(applicationRoot.Length);
                    }
                }

                // querystring invariant key
                var invariantCacheKey = ComputeCacheKey(
                    _shellSettings.Name,
                    redirectUrl,
                    () => _workContext.CurrentCulture,
                    _themeManager.GetRequestTheme(filterContext.RequestContext).Id,
                    null
                    );

                _cacheService.RemoveByTag(invariantCacheKey);

                // adding a refresh key so that the next request will not be cached
                var epIndex = redirectUrl.IndexOf('?');
                var qs      = new NameValueCollection();
                if (epIndex > 0)
                {
                    qs = HttpUtility.ParseQueryString(redirectUrl.Substring(epIndex));
                }

                var refresh = _now.Ticks;
                qs.Remove(RefreshKey);

                qs.Add(RefreshKey, refresh.ToString("x"));
                var querystring = "?" + string.Join("&", Array.ConvertAll(qs.AllKeys, k => string.Format("{0}={1}", HttpUtility.UrlEncode(k), HttpUtility.UrlEncode(qs[k]))));

                if (epIndex > 0)
                {
                    redirectUrl = redirectUrl.Substring(0, epIndex) + querystring;
                }
                else
                {
                    redirectUrl = redirectUrl + querystring;
                }

                filterContext.Result = new RedirectResult(redirectUrl, ((RedirectResult)filterContext.Result).Permanent);
                filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            }
        }
Пример #16
0
        private bool TransformRedirect(ActionExecutedContext filterContext)
        {
            // removes the target of the redirection from cache after a POST

            if (filterContext.Result == null)
            {
                throw new ArgumentNullException();
            }

            if (AdminFilter.IsApplied(new RequestContext(filterContext.HttpContext, new RouteData())))
            {
                return(false);
            }

            var redirectResult = filterContext.Result as RedirectResult;

            // status code can't be tested at this point, so test the result type instead
            if (redirectResult == null ||
                !filterContext.HttpContext.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase))
            {
                return(false);
            }

            Logger.Debug("Redirect on POST");
            var redirectUrl = redirectResult.Url;

            if (!VirtualPathUtility.IsAbsolute(redirectUrl))
            {
                var applicationRoot = new UrlHelper(filterContext.HttpContext.Request.RequestContext).MakeAbsolute("/");
                if (redirectUrl.StartsWith(applicationRoot, StringComparison.OrdinalIgnoreCase))
                {
                    redirectUrl = "~/" + redirectUrl.Substring(applicationRoot.Length);
                    redirectUrl = VirtualPathUtility.ToAbsolute(redirectUrl);
                }
            }

            // querystring invariant key
            var invariantCacheKey = ComputeCacheKey(
                _shellSettings.Name,
                redirectUrl,
                () => _workContext.CurrentCulture,
                _themeManager.GetRequestTheme(filterContext.RequestContext).Id,
                null
                );

            // remove all cached version of the same page
            _cacheService.RemoveByTag(invariantCacheKey);

            // adding a refresh key so that the redirection doesn't get restored
            // from a cached version on a proxy
            // this can happen when using public caching, we want to force the
            // client to get a fresh copy of the redirectUrl page

            if (GetMaxAge() > 0)
            {
                var epIndex = redirectUrl.IndexOf('?');
                var qs      = new NameValueCollection();
                if (epIndex > 0)
                {
                    qs = HttpUtility.ParseQueryString(redirectUrl.Substring(epIndex));
                }

                // substract Epoch to get a smaller number
                var refresh = _now.Ticks - Epoch;
                qs.Remove(RefreshKey);

                qs.Add(RefreshKey, refresh.ToString("x"));
                var querystring = "?" + string.Join("&", Array.ConvertAll(qs.AllKeys, k => string.Format("{0}={1}", HttpUtility.UrlEncode(k), HttpUtility.UrlEncode(qs[k]))));

                if (epIndex > 0)
                {
                    redirectUrl = redirectUrl.Substring(0, epIndex) + querystring;
                }
                else
                {
                    redirectUrl = redirectUrl + querystring;
                }
            }

            filterContext.Result = new RedirectResult(redirectUrl, redirectResult.Permanent);
            filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);

            return(true);
        }
Пример #17
0
        private string ComputeCacheKey(IContent content, string displayType, string groupId)
        {
            var sb          = new StringBuilder();
            var workContext = _workContextAccessor.GetContext();
            var theme       = _themeManager.GetRequestTheme(workContext.HttpContext.Request.RequestContext).Id;

            var parameters = new Dictionary <string, object>();

            var queryString = workContext.HttpContext.Request.QueryString;

            foreach (var varyByQueryString in _cacheSettings.VaryByQueryStringParameters)
            {
                if (queryString.AllKeys.Contains(varyByQueryString))
                {
                    parameters["QueryString:" + varyByQueryString] = queryString[varyByQueryString];
                }
            }

            var requestHeaders = workContext.HttpContext.Request.Headers;

            foreach (var varyByRequestHeader in _cacheSettings.VaryByRequestHeaders)
            {
                if (requestHeaders.AllKeys.Contains(varyByRequestHeader))
                {
                    parameters["HEADER:" + varyByRequestHeader] = requestHeaders[varyByRequestHeader];
                }
            }

            if (_cacheSettings.VaryByCulture)
            {
                parameters["culture"] = workContext.CurrentCulture.ToLowerInvariant();
            }

            if (_cacheSettings.VaryByAuthenticationState)
            {
                parameters["auth"] = workContext.HttpContext.User.Identity.IsAuthenticated.ToString().ToLowerInvariant();
            }

            if (_cacheSettings.VaryByUser)
            {
                parameters["user"] = workContext.HttpContext.User.Identity.IsAuthenticated ?
                                     workContext.HttpContext.User.Identity.Name.ToLowerInvariant() :
                                     "anonymous";
            }

            if (_cacheSettings.VaryByUrl)
            {
                parameters["url"] = workContext.HttpContext.Request.Url.AbsolutePath.ToLowerInvariant();
            }

            //sb.Append("layer=").Append(content.LayerId.ToString(CultureInfo.InvariantCulture)).Append(";");
            //sb.Append("zone=").Append(content.Zone).Append(";");
            sb.Append("id=").Append(content.Id.ToString(CultureInfo.InvariantCulture)).Append(";");
            sb.Append("displaytype=").Append(displayType).Append(";");
            sb.Append("groupid=").Append(groupId).Append(";");
            sb.Append("tenant=").Append(_shellSettings.Name).Append(";");
            sb.Append("theme=").Append(theme.ToLowerInvariant()).Append(";");

            foreach (var pair in parameters)
            {
                sb.AppendFormat("{0}={1};", pair.Key.ToLowerInvariant(), Convert.ToString(pair.Value).ToLowerInvariant());
            }

            return(sb.ToString());
        }