void IHttpHandler.ProcessRequest(HttpContext context)
        {
            var url = EwfApp.GetRequestAppRelativeUrl(context.Request);

            // We assume that all URL version strings will have the same length as the format string.
            var prefixedVersionStringIndex = url.LastIndexOf(".") - (urlVersionStringPrefix.Length + EwfSafeResponseWriter.UrlVersionStringFormat.Length);

            if (prefixedVersionStringIndex < 0)
            {
                throw new ResourceNotAvailableException("Failed to find the version and extension in the URL.", null);
            }
            var cssInfo =
                EwfApp.GlobalType.Assembly.CreateInstance(
                    CombineNamespacesAndProcessEwfIfNecessary(
                        EwfApp.GlobalType.Namespace,
                        url.Remove(prefixedVersionStringIndex).Separate("/", false).Select(StandardLibraryMethods.GetCSharpIdentifier).Aggregate((a, b) => a + "." + b) +
                        "+Info")) as StaticCssInfo;

            if (cssInfo == null)
            {
                throw new ResourceNotAvailableException("Failed to create an Info object for the request.", null);
            }
            var urlVersionString = url.Substring(prefixedVersionStringIndex + urlVersionStringPrefix.Length, EwfSafeResponseWriter.UrlVersionStringFormat.Length);

            if (EwfSafeResponseWriter.GetUrlVersionString(cssInfo.GetResourceLastModificationDateAndTime()) != urlVersionString)
            {
                throw new ResourceNotAvailableException("The URL version string does not match the last-modification date/time of the resource.", null);
            }

            new EwfSafeResponseWriter(
                () => File.ReadAllText(cssInfo.FilePath),
                urlVersionString,
                () => new ResponseMemoryCachingSetup(cssInfo.GetUrl(false, false, false), cssInfo.GetResourceLastModificationDateAndTime())).WriteResponse();
        }
        /// <summary>
        /// Call this from Application_End in your Global.asax.cs file. Besides this call, there should be no other code in the method.
        /// </summary>
        public static void CleanUpStatics()
        {
            if (!ewlInitialized)
            {
                return;
            }

            if (!AppTools.SecondaryInitFailed)
            {
                EwfApp.ExecuteWithBasicExceptionHandling(
                    () => {
                    if (appInitializer != null)
                    {
                        appInitializer.CleanUpStatics();
                    }
                },
                    false,
                    false);
            }

            AppTools.CleanUp();

            if (!EwfApp.FrameworkInitialized)
            {
                var waitHandle = new ManualResetEvent(false);
                initFailureUnloadTimer.Dispose(waitHandle);
                waitHandle.WaitOne();
            }
        }
Пример #3
0
        internal string GetUrl(bool ensureUserCanAccessResource, bool ensureResourceNotDisabled, bool makeAbsolute)
        {
            var url = buildUrl() + uriFragmentIdentifier.PrependDelimiter("#");

            if (ensureUserCanAccessResource && !UserCanAccessResource)
            {
                throw new ApplicationException("GetUrl was called for a resource that the authenticated user cannot access. The URL would have been " + url + ".");
            }
            if (ensureResourceNotDisabled && AlternativeMode is DisabledResourceMode)
            {
                throw new ApplicationException("GetUrl was called for a resource that is disabled. The URL would have been " + url + ".");
            }
            if (makeAbsolute)
            {
                url = url.Replace("~", EwfApp.GetDefaultBaseUrl(ShouldBeSecureGivenCurrentRequest));
            }
            return(url);
        }
        private static Tuple <string, string, string> getNameAndDomainAndPath(string name, string domain, string path, bool omitNamePrefix)
        {
            var defaultAttributes = EwfConfigurationStatics.AppConfiguration.DefaultCookieAttributes;
            var defaultBaseUrl    = new Uri(EwfApp.GetDefaultBaseUrl(false));

            domain = domain ?? defaultAttributes.Domain ?? "";

            // It's important that the cookie path not end with a slash. If it does, Internet Explorer will not transmit the cookie if the user requests the root URL
            // of the application without a trailing slash, e.g. integration.redstapler.biz/Todd. One justification for adding a trailing slash to the cookie path is
            // http://stackoverflow.com/questions/2156399/restful-cookie-path-fails-in-ie-without-trailing-slash.
            path = path ?? defaultAttributes.Path;
            path = path != null ? "/" + path : defaultBaseUrl.AbsolutePath;

            // Ensure that the domain and path of the cookie are in scope for both the request URL and resource URL. These two URLs can be different on shortcut URL
            // requests, requests that transfer to the log-in page, etc.
            var requestUrls = new[] { AppRequestState.Instance.Url, EwfPage.Instance.InfoAsBaseType.GetUrl(false, false, true) };

            foreach (var url in requestUrls)
            {
                var uri = new Uri(url);
                if (domain.Any() && !("." + uri.Host).EndsWith("." + domain))
                {
                    throw new ApplicationException("The cookie domain of \"{0}\" is not in scope for \"{1}\".".FormatWith(domain, url));
                }
                if (path != "/" && !(uri.AbsolutePath + "/").StartsWith(path + "/"))
                {
                    throw new ApplicationException("The cookie path of \"{0}\" is not in scope for \"{1}\".".FormatWith(path, url));
                }
            }
            if (!domain.Any())
            {
                var requestHosts = requestUrls.Select(i => new Uri(i).Host);
                if (requestHosts.Distinct().Count() > 1)
                {
                    throw new ApplicationException(
                              "The cookie domain could arbitrarily be either {0} depending upon the request URL.".FormatWith(
                                  StringTools.ConcatenateWithDelimiter(" or ", requestHosts.ToArray())));
                }
            }

            return(Tuple.Create((omitNamePrefix ? "" : defaultAttributes.NamePrefix ?? "") + name, domain, path));
        }
        void IHttpHandler.ProcessRequest(HttpContext context)
        {
            var url = EwfApp.GetRequestAppRelativeUrl(context.Request);

            var queryIndex = url.IndexOf("?", StringComparison.Ordinal);

            if (queryIndex >= 0)
            {
                url = url.Remove(queryIndex);
            }

            var extensionIndex = url.LastIndexOf(".", StringComparison.Ordinal);

            var versionStringOrFileExtensionIndex = extensionIndex;
            var urlVersionString = "";

            if (url.StartsWith(VersionedFilesFolderName + "/") || url.StartsWith(EwfFolderName + "/" + VersionedFilesFolderName + "/"))
            {
                urlVersionString = "invariant";
            }
            else
            {
                // We assume that all URL version strings will have the same length as the format string.
                var prefixedVersionStringIndex = extensionIndex - (urlVersionStringPrefix.Length + EwfSafeResponseWriter.UrlVersionStringFormat.Length);

                if (prefixedVersionStringIndex >= 0)
                {
                    DateTimeOffset dateAndTime;
                    var            versionString = url.Substring(prefixedVersionStringIndex + urlVersionStringPrefix.Length, EwfSafeResponseWriter.UrlVersionStringFormat.Length);
                    if (DateTimeOffset.TryParseExact(
                            versionString,
                            EwfSafeResponseWriter.UrlVersionStringFormat,
                            DateTimeFormatInfo.InvariantInfo,
                            DateTimeStyles.None,
                            out dateAndTime))
                    {
                        versionStringOrFileExtensionIndex = prefixedVersionStringIndex;
                        urlVersionString = versionString;
                    }
                }
            }

            if (versionStringOrFileExtensionIndex < 0)
            {
                throw new ResourceNotAvailableException("Failed to find the extension in the URL.", null);
            }
            var extension      = url.Substring(extensionIndex);
            var staticFileInfo =
                EwfApp.GlobalType.Assembly.CreateInstance(
                    CombineNamespacesAndProcessEwfIfNecessary(
                        EwfApp.GlobalType.Namespace,
                        (url.Remove(versionStringOrFileExtensionIndex) + extension.CapitalizeString()).Separate("/", false)
                        .Select(StandardLibraryMethods.GetCSharpIdentifier)
                        .Aggregate((a, b) => a + "." + b) + "+Info")) as StaticFileInfo;

            if (staticFileInfo == null)
            {
                throw new ResourceNotAvailableException("Failed to create an Info object for the request.", null);
            }

            var mediaTypeOverride = EwfApp.Instance.GetMediaTypeOverrides().SingleOrDefault(i => i.FileExtension == extension);
            var contentType       = mediaTypeOverride != null ? mediaTypeOverride.MediaType : MimeTypeMap.MimeTypeMap.GetMimeType(extension);

            Func <string>         cacheKeyGetter = () => staticFileInfo.GetUrl(false, false, false);
            EwfSafeResponseWriter responseWriter;

            if (contentType == ContentTypes.Css)
            {
                Func <string> cssGetter = () => File.ReadAllText(staticFileInfo.FilePath);
                responseWriter = urlVersionString.Any()
                                                         ? new EwfSafeResponseWriter(
                    cssGetter,
                    urlVersionString,
                    () => new ResponseMemoryCachingSetup(cacheKeyGetter(), staticFileInfo.GetResourceLastModificationDateAndTime()))
                                                         : new EwfSafeResponseWriter(
                    () => new EwfResponse(ContentTypes.Css, new EwfResponseBodyCreator(() => CssPreprocessor.TransformCssFile(cssGetter()))),
                    staticFileInfo.GetResourceLastModificationDateAndTime(),
                    memoryCacheKeyGetter: cacheKeyGetter);
            }
            else
            {
                Func <EwfResponse> responseCreator = () => new EwfResponse(
                    contentType,
                    new EwfResponseBodyCreator(
                        responseStream => {
                    using (var fileStream = File.OpenRead(staticFileInfo.FilePath))
                        IoMethods.CopyStream(fileStream, responseStream);
                }));
                responseWriter = urlVersionString.Any()
                                                         ? new EwfSafeResponseWriter(
                    responseCreator,
                    urlVersionString,
                    memoryCachingSetupGetter:
                    () => new ResponseMemoryCachingSetup(cacheKeyGetter(), staticFileInfo.GetResourceLastModificationDateAndTime()))
                                                         : new EwfSafeResponseWriter(
                    responseCreator,
                    staticFileInfo.GetResourceLastModificationDateAndTime(),
                    memoryCacheKeyGetter: cacheKeyGetter);
            }
            responseWriter.WriteResponse();
        }
        /// <summary>
        /// Call this from Application_Start in your Global.asax.cs file. Besides this call, there should be no other code in the method.
        /// </summary>
        /// <param name="globalInitializer">The system's global initializer. Do not pass null.</param>
        /// <param name="appInitializer">The application initializer, which performs web-site specific initialization and cleanup. If you have one of these you
        /// should name the class AppInitializer.</param>
        public static void InitStatics(SystemInitializer globalInitializer, SystemInitializer appInitializer = null)
        {
            // This is a hack to support data-access state in WCF services.
            var wcfDataAccessState = new ThreadLocal <DataAccessState>(() => new DataAccessState());

            // Initialize system.
            var initTimeDataAccessState = new ThreadLocal <DataAccessState>(() => new DataAccessState());

            try {
                AppTools.Init(
                    globalInitializer,
                    Path.GetFileName(Path.GetDirectoryName(HttpRuntime.AppDomainAppPath)),
                    false,
                    mainDataAccessStateGetter:
                    () => {
                    return(EwfApp.Instance != null
                                                                       ? EwfApp.Instance.RequestState != null ? EwfApp.Instance.RequestState.DataAccessState : initTimeDataAccessState.Value
                                                                       : System.ServiceModel.OperationContext.Current != null ? wcfDataAccessState.Value : null);
                });
            }
            catch {
                // Suppress all exceptions since there is no way to report them.
                return;
            }
            ewlInitialized = true;

            // Initialize web application.
            if (!AppTools.SecondaryInitFailed)
            {
                EwfApp.ExecuteWithBasicExceptionHandling(
                    () => {
                    EwfConfigurationStatics.Init();

                    // Prevent MiniProfiler JSON exceptions caused by pages with hundreds of database queries.
                    MiniProfiler.Settings.MaxJsonResponseSize = int.MaxValue;

                    var globalType       = BuildManager.GetGlobalAsaxType().BaseType;
                    var metaLogicFactory =
                        globalType.Assembly.CreateInstance("RedStapler.StandardLibrary.EnterpriseWebFramework." + globalType.Namespace + ".MetaLogicFactory") as
                        AppMetaLogicFactory;
                    if (metaLogicFactory == null)
                    {
                        throw new ApplicationException("Meta logic factory not found.");
                    }
                    EwfApp.Init(globalType, metaLogicFactory);

                    EwfPage.Init(
                        () => {
                        var cssInfos = new List <ResourceInfo>();
                        cssInfos.AddRange(EwfApp.MetaLogicFactory.CreateBasicCssInfos());
                        if (EwfUiStatics.AppMasterPage != null)
                        {
                            cssInfos.AddRange(EwfApp.MetaLogicFactory.CreateEwfUiCssInfos());
                        }
                        cssInfos.AddRange(EwfApp.Instance.GetStyleSheets());
                        if (EwfUiStatics.AppMasterPage != null)
                        {
                            cssInfos.AddRange(EwfUiStatics.AppProvider.GetStyleSheets());
                        }
                        return(cssInfos);
                    });
                    CssPreprocessingStatics.Init(globalInitializer.GetType().Assembly, globalType.Assembly);
                    EwfUiStatics.Init(globalType);

                    EwfInitializationOps.appInitializer = appInitializer;
                    if (appInitializer != null)
                    {
                        appInitializer.InitStatics();
                    }

                    initTimeDataAccessState     = null;
                    EwfApp.FrameworkInitialized = true;
                },
                    false,
                    false);
            }

            // If initialization failed, unload and restart the application after a reasonable delay.
            if (!EwfApp.FrameworkInitialized)
            {
                const int unloadDelay = 60000;                 // milliseconds
                initFailureUnloadTimer = new Timer(
                    state => EwfApp.ExecuteWithBasicExceptionHandling(
                        () => {
                    if (AppTools.IsDevelopmentInstallation)
                    {
                        return;
                    }
                    HttpRuntime.UnloadAppDomain();

                    // Restart the application by making a request. Idea from Rick Strahl:
                    // http://weblog.west-wind.com/posts/2013/Oct/02/Use-IIS-Application-Initialization-for-keeping-ASPNET-Apps-alive.
                    //
                    // Disable server certificate validation so that this request gets through even for web sites that don't use a certificate that is trusted by
                    // default. There is no security risk since we're not sending any sensitive information and we're not using the response.
                    NetTools.ExecuteWithResponse(IisConfigurationStatics.GetFirstBaseUrlForCurrentSite(false), response => { }, disableCertificateValidation: true);
                },
                        false,
                        false),
                    null,
                    unloadDelay,
                    Timeout.Infinite);
            }
        }