/// <summary>
        /// Redirects to the specified URL.
        /// </summary>
        /// <param name="response">The response to use for redirection.</param>
        /// <param name="url">The URL to redirect to.</param>
        /// <param name="bypassSecurityWarning">If set to <c>true</c> security warnings will be bypassed.</param>
        public void Redirect(HttpResponseBase response, string url, bool bypassSecurityWarning)
            if (bypassSecurityWarning) {
                Logger.Log("Bypassing security warning via a response header and JavaScript.");

                url = JsEncodeUrl(url);

                // Clear the current response buffer.

                // Add a refresh header to the response for the new path.
                response.AddHeader("Refresh", "0;URL=" + url);

                // Also, add JavaScript to replace the current location as backup.
                response.Write("<script language=\"javascript\">window.location = '");
            } else {
                Logger.Log("Issuing permanent redirect.");

                // Permanent redirect.
                // TODO: Make the status code configurable (i.e. permanent vs. temporary).
                response.StatusCode = 301;
                response.RedirectLocation = url;

            // End the current response.
        public void Enrich(HttpResponseBase response, HttpRequestBase request, ISecurityEvaluator securityEvaluator, Settings settings)
            if (!securityEvaluator.IsSecureConnection(request, settings) || !settings.EnableHsts) {

            // Add the needed STS header.
            response.AddHeader("Strict-Transport-Security", string.Format("max-age={0:f0}", settings.HstsMaxAge));
        /// <summary>
        /// Gets any URI for the specified request that ensures it is being accessed by the proper protocol, if a match is found in the settings.
        /// </summary>
        /// <param name="request">The request to ensure proper access for.</param>
        /// <param name="response">The response to use if a redirection or other output is necessary.</param>
        /// <param name="security">The security setting to match.</param>
        /// <param name="settings">The settings used for any redirection.</param>
        /// <returns>A URL that ensures the requested resources matches the specified security; or null if the current request already does.</returns>
        public string GetUriForMatchedSecurityRequest(HttpRequestBase request, HttpResponseBase response, RequestSecurity security, Settings settings)
            string targetUrl = null;

            // Evaluate the request's security.
            Logger.Log("Determining if the connection is secure.");
            bool isSecureConnection = _securityEvaluator.IsSecureConnection(request, settings);

            if (security == RequestSecurity.Secure && !isSecureConnection ||
                security == RequestSecurity.Insecure && isSecureConnection) {
                Logger.Log("Calculating the target URI to switch to.");

                // Determine the target protocol and get any base target URL from the settings.
                string targetProtocolScheme;
                string baseTargetUrl;
                if (security == RequestSecurity.Secure) {
                    targetProtocolScheme = Uri.UriSchemeHttps;
                    baseTargetUrl = settings.BaseSecureUri;
                } else {
                    targetProtocolScheme = Uri.UriSchemeHttp;
                    baseTargetUrl = settings.BaseInsecureUri;

                if (string.IsNullOrEmpty(baseTargetUrl)) {
                    // If there is no base target URI, just switch the protocol scheme of the current request's URI.
                    // * Account for cookie-less sessions by applying the application modifier.
                    targetUrl = targetProtocolScheme + Uri.SchemeDelimiter + request.Url.Authority + response.ApplyAppPathModifier(request.RawUrl);
                } else {
                    // Build the appropriate URI based on the specified target URL.
                    var uri = new StringBuilder(baseTargetUrl);

                    // - Use the full request path, but remove any sub-application path.
                    if (request.ApplicationPath.Length > 1) {
                        uri.Remove(baseTargetUrl.Length, request.ApplicationPath.Length);

                    // Normalize the URI.
                    uri.Replace("//", "/", baseTargetUrl.Length - 1, uri.Length - baseTargetUrl.Length);

                    targetUrl = uri.ToString();

            return targetUrl;