/// <summary> /// Initializes a new instance of the <see cref="RuleSetContext"/> class. /// </summary> /// <param name="copy">The copy.</param> internal RuleSetContext(RuleSetContext copy) { if (copy == null) throw new ArgumentNullException("copy"); RuleSet = copy.RuleSet; RequestedUrl = copy.RequestedUrl; _responseContent = copy._responseContent; HttpContext = copy.HttpContext; IsOutputRuleSet = copy.IsOutputRuleSet; LogCategory = String.Empty; }
/// <summary> /// Initializes a new instance of the <see cref="RuleSetContext"/> class. /// </summary> /// <param name="copy">The copy.</param> internal RuleSetContext(RuleSetContext copy) { if (copy == null) { throw new ArgumentNullException("copy"); } RuleSet = copy.RuleSet; RequestedUrl = copy.RequestedUrl; _responseContent = copy._responseContent; HttpContext = copy.HttpContext; IsOutputRuleSet = copy.IsOutputRuleSet; LogCategory = String.Empty; }
/// <summary> /// Initializes a new instance of the <see cref="RuleContext"/> class. /// </summary> /// <param name="index">The index.</param> /// <param name="ruleSetContext">The rule set context.</param> /// <param name="currentContent"></param> /// <param name="rule">The rule.</param> public RuleContext(int index, RuleSetContext ruleSetContext, byte[] currentContent, IRule rule) : base(ruleSetContext) { if (currentContent == null) throw new ArgumentNullException("currentContent"); if (rule == null) throw new ArgumentNullException("rule"); RuleIndex = index; LogCategory = "Rule " + index; _currentContent = currentContent; _substitutedContent = currentContent; CurrentUrl = ruleSetContext.RequestedUrl; _substitutedUrl = ruleSetContext.RequestedUrl; CurrentRule = rule; }
/// <summary> /// Initializes a new instance of the <see cref="RuleContext"/> class. /// </summary> /// <param name="index">The index.</param> /// <param name="ruleSetContext">The rule set context.</param> /// <param name="currentContent"></param> /// <param name="rule">The rule.</param> public RuleContext(int index, RuleSetContext ruleSetContext, byte[] currentContent, IRule rule) : base(ruleSetContext) { if (currentContent == null) { throw new ArgumentNullException("currentContent"); } if (rule == null) { throw new ArgumentNullException("rule"); } RuleIndex = index; LogCategory = "Rule " + index; _currentContent = currentContent; _substitutedContent = currentContent; CurrentUrl = ruleSetContext.RequestedUrl; _substitutedUrl = ruleSetContext.RequestedUrl; CurrentRule = rule; }
/// <summary> /// Gets the value. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public string GetValue(string input, RuleSetContext context) { // if the value has already been cached then return that value instead of reprocessing if (GetKeyValue(context.HttpContext) != null) { return(GetKeyValue(context.HttpContext)); } string value = String.Empty; if ((_type & ServerVariableType.ServerVariables) != 0) { value = context.HttpContext.Request.ServerVariables[_name]; // check to see if the value was found if not try the switch statement if (String.IsNullOrEmpty(value)) { switch (_name) { case "TIME_YEAR": value = DateTime.Today.Year.ToString(); break; case "TIME_MON": value = DateTime.Today.Month.ToString(); break; case "TIME_DAY": value = DateTime.Today.Day.ToString(); break; case "TIME_HOUR": value = DateTime.Now.Hour.ToString(); break; case "TIME_MIN": value = DateTime.Now.Minute.ToString(); break; case "TIME_SEC": value = DateTime.Now.Second.ToString(); break; case "TIME_WDAY": value = DateTime.Today.DayOfWeek.ToString(); break; case "TIME": value = DateTime.Now.ToString("f"); break; case "API_VERSION": value = String.Empty; break; // TODO: figure out how to attack this case "THE_REQUEST": value = context.HttpContext.Request.ServerVariables["REQUEST_METHOD"] + " " + context.HttpContext.Request.ServerVariables["PATH_INFO"] + " " + context.HttpContext.Request.ServerVariables["SERVER_PROTOCOL"]; break; case "REQUEST_URI": value = context.HttpContext.Request.ServerVariables["URL"]; break; case "REQUEST_FILENAME": value = context.HttpContext.Request.ServerVariables["PATH_TRANSLATED"]; break; case "IS_SUBREQ": value = String.IsNullOrEmpty(context.HttpContext.Request.Headers["X-Rewriter-Transfer"]) ? Boolean.FalseString : Boolean.TrueString; break; } } } else if ((_type & ServerVariableType.Headers) != 0) { value = context.HttpContext.Request.Headers[_name]; } else if ((_type & ServerVariableType.QueryString) != 0) { value = context.HttpContext.Request.QueryString[_name]; } else if ((_type & ServerVariableType.Form) != 0) { value = context.HttpContext.Request.Form[_name]; } else if ((_type & ServerVariableType.Cookies) != 0) { var cookie = context.HttpContext.Request.Cookies[_name]; // if cookie was found set the value to the value of the cookie if (cookie != null) { value = cookie.Value; } } Manager.LogIf(context.LogLevel >= 2, "Input: " + value, context.LogCategory); SetKeyValue(context.HttpContext, value); return(value); }
/// <summary> /// Gets the value. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> public string GetValue(string input, RuleSetContext context) { // if the value has already been cached then return that value instead of reprocessing if (GetKeyValue(context.HttpContext) != null) return GetKeyValue(context.HttpContext); string value = String.Empty; if ((_type & ServerVariableType.ServerVariables) != 0) { value = context.HttpContext.Request.ServerVariables[_name]; // check to see if the value was found if not try the switch statement if (String.IsNullOrEmpty(value)) { switch (_name) { case "TIME_YEAR": value = DateTime.Today.Year.ToString(); break; case "TIME_MON": value = DateTime.Today.Month.ToString(); break; case "TIME_DAY": value = DateTime.Today.Day.ToString(); break; case "TIME_HOUR": value = DateTime.Now.Hour.ToString(); break; case "TIME_MIN": value = DateTime.Now.Minute.ToString(); break; case "TIME_SEC": value = DateTime.Now.Second.ToString(); break; case "TIME_WDAY": value = DateTime.Today.DayOfWeek.ToString(); break; case "TIME": value = DateTime.Now.ToString("f"); break; case "API_VERSION": value = String.Empty; break;// TODO: figure out how to attack this case "THE_REQUEST": value = context.HttpContext.Request.ServerVariables["REQUEST_METHOD"] + " " + context.HttpContext.Request.ServerVariables["PATH_INFO"] + " " + context.HttpContext.Request.ServerVariables["SERVER_PROTOCOL"]; break; case "REQUEST_URI": value = context.HttpContext.Request.ServerVariables["URL"]; break; case "REQUEST_FILENAME": value = context.HttpContext.Request.ServerVariables["PATH_TRANSLATED"]; break; case "IS_SUBREQ": value = String.IsNullOrEmpty(context.HttpContext.Request.Headers["X-Rewriter-Transfer"]) ? Boolean.FalseString : Boolean.TrueString; break; } } } else if ((_type & ServerVariableType.Headers) != 0) value = context.HttpContext.Request.Headers[_name]; else if ((_type & ServerVariableType.QueryString) != 0) value = context.HttpContext.Request.QueryString[_name]; else if ((_type & ServerVariableType.Form) != 0) value = context.HttpContext.Request.Form[_name]; else if ((_type & ServerVariableType.Cookies) != 0) { var cookie = context.HttpContext.Request.Cookies[_name]; // if cookie was found set the value to the value of the cookie if (cookie != null) value = cookie.Value; } Manager.LogIf(context.LogLevel >= 2, "Input: " + value, context.LogCategory); SetKeyValue(context.HttpContext, value); return value; }
/// <summary> /// /// </summary> /// <param name="httpContext"></param> /// <param name="content"></param> /// <returns></returns> public byte[] RunOutputRules(HttpContextBase httpContext, byte[] content) { var context = new RuleSetContext(this, content, httpContext); byte[] currentContent = content; if (!EngineEnabled) { Manager.LogIf(!EngineEnabled && LogLevel >= 9, "Rewrite Engine Is DISABLED", "OutRewrite"); } if (_outputRules.Count > 0 && EngineEnabled) { Manager.LogIf(LogLevel >= 1, "**********************************************************************************"); //Manager.LogIf(LogLevel >= 9, "Input: " + currentContent, "OutRewrite"); var temporyFlags = (IRuleFlagProcessor)null; bool skipNextChain = false; byte[] initialContent = currentContent; // process rules according to their settings for (int i = 0; i < _outputRules.Count; i++) { var ruleContext = new RuleContext(i, context, currentContent, _outputRules[i]); temporyFlags = _outputRules[i].Flags; bool containsChain = RuleFlagsProcessor.HasChain(_outputRules[i].Flags); bool previousContainsChain = RuleFlagsProcessor.HasChain(_outputRules[Math.Max(0, i - 1)].Flags); // if the previous rule doesn't contain a chain flag then set the initial URL // this will be used to reset a chain if one of the chain rules fail if (!previousContainsChain) { initialContent = currentContent; } // skip if the current rule or the last rule has a chain flag // and if the skip next chain is set if (skipNextChain && (previousContainsChain || containsChain)) { continue; } else { skipNextChain = false; } if (_outputRules[i].TryExecute(ruleContext)) { var flagResponse = temporyFlags.Apply(ruleContext); currentContent = ruleContext.SubstitutedContent; i = ruleContext.RuleIndex ?? -1; bool breakLoop = false; // apply the flags to the rules, and only do special processing // for the flag responses listed in the switch statement below switch (flagResponse) { case RuleFlagProcessorResponse.ExitRuleSet: return(null); case RuleFlagProcessorResponse.LastRule: breakLoop = true; break; } // break the loop because we have reached the last rule as indicated by a flag if (breakLoop) { break; } } else if (containsChain) { skipNextChain = true; // reset the current URL back to the initial URL from the start of the chain currentContent = initialContent; } else if (previousContainsChain) { // reset the current URL back to the initial URL from the start of the chain currentContent = initialContent; } } //Manager.LogIf(LogLevel >= 9, "Output: " + currentContent, "OutRewrite"); Manager.LogIf(LogLevel >= 1, "**********************************************************************************"); } return(currentContent); }
/// <summary> /// Runs the rules. /// </summary> /// <param name="httpContext">The HTTP context.</param> /// <param name="url">The URL.</param> /// <returns> /// Returns a rewritten <see cref="System.Uri"/>, or a value of <see langword="null"/> if no rewriting was done to <paramref name="url"/>. /// </returns> public Uri RunRules(HttpContextBase httpContext, Uri url) { var context = new RuleSetContext(this, url, httpContext); var currentUrl = url; if (!EngineEnabled) { Manager.LogIf(!EngineEnabled && LogLevel >= 9, "Rewrite Engine Is DISABLED", "Rewrite"); } if (_rules.Count > 0 && EngineEnabled) { Manager.LogIf(LogLevel >= 1, "**********************************************************************************"); Manager.LogIf(LogLevel >= 1, "Input: " + currentUrl, "Rewrite"); // check if max number of internal transfers have been exceeded if (InternalTransferCount(httpContext) > MaxInternalTransfers) { string message = "Exceeded the max number of internal transfers."; Manager.LogIf(LogLevel >= 1, message, "Error"); throw new HttpException(500, message); } var temporyFlags = (IRuleFlagProcessor)null; var skipNextChain = false; var initialUrl = currentUrl; if (!String.IsNullOrEmpty(VirtualBase) && VirtualBase != "/") { currentUrl = RemoveBase(VirtualBase, currentUrl); } // process rules according to their settings for (int i = 0; i < _rules.Count; i++) { var ruleContext = new RuleContext(i, context, currentUrl, _rules[i]); temporyFlags = _rules[i].Flags; // continue if this rule shouldn't be processed because it doesn't allow internal transfer requests if (RuleFlagsProcessor.HasNotForInternalSubRequests(temporyFlags) && IsInternalTransfer(httpContext)) { continue; } bool containsChain = RuleFlagsProcessor.HasChain(_rules[i].Flags); bool previousContainsChain = RuleFlagsProcessor.HasChain(_rules[Math.Max(0, i - 1)].Flags); // if the previous rule doesn't contain a chain flag then set the initial URL // this will be used to reset a chain if one of the chain rules fail if (!previousContainsChain) { initialUrl = currentUrl; } // skip if the current rule or the last rule has a chain flag // and if the skip next chain is set if (skipNextChain && (previousContainsChain || containsChain)) { continue; } else { skipNextChain = false; } if (_rules[i].TryExecute(ruleContext)) { var flagResponse = temporyFlags.Apply(ruleContext); currentUrl = ruleContext.SubstitutedUrl; i = ruleContext.RuleIndex ?? -1; bool breakLoop = false; // apply the flags to the rules, and only do special processing // for the flag responses listed in the switch statement below switch (flagResponse) { case RuleFlagProcessorResponse.ExitRuleSet: return(null); case RuleFlagProcessorResponse.LastRule: breakLoop = true; break; } // break the loop because we have reached the last rule as indicated by a flag if (breakLoop) { break; } } else if (containsChain) { skipNextChain = true; // reset the current URL back to the initial URL from the start of the chain currentUrl = initialUrl; } else if (previousContainsChain) { // reset the current URL back to the initial URL from the start of the chain currentUrl = initialUrl; } } // if the scheme, host, and ports do not match on the request vs the rewrite a redirect needs to be performed instead of a rewrite if (Uri.Compare(currentUrl, context.RequestedUrl, UriComponents.SchemeAndServer, UriFormat.SafeUnescaped, StringComparison.OrdinalIgnoreCase) != 0) { Manager.LogIf(LogLevel >= 1, "Output: 302 Redirect to " + currentUrl, "Rewrite"); Manager.Redirect(httpContext, "found", currentUrl); } if (!String.IsNullOrEmpty(VirtualBase) && VirtualBase != "/") { currentUrl = AddBase(VirtualBase, currentUrl); } Manager.LogIf(LogLevel >= 1, "Output: " + currentUrl, "Rewrite"); Manager.LogIf(LogLevel >= 1, "**********************************************************************************"); Manager.TryToAddXRewriteUrlHeader(httpContext); Manager.TryToAddVanityHeader(httpContext); } // if the http request url matches for both the request and the rewrite no work was done so the url should be null if (Uri.Compare(currentUrl, url, UriComponents.HttpRequestUrl, UriFormat.SafeUnescaped, StringComparison.OrdinalIgnoreCase) == 0) { currentUrl = null; } return(currentUrl); }
/// <summary> /// /// </summary> /// <param name="httpContext"></param> /// <param name="content"></param> /// <returns></returns> public byte[] RunOutputRules(HttpContextBase httpContext, byte[] content) { var context = new RuleSetContext(this, content, httpContext); byte[] currentContent = content; if (!EngineEnabled) Manager.LogIf(!EngineEnabled && LogLevel >= 9, "Rewrite Engine Is DISABLED", "OutRewrite"); if (_outputRules.Count > 0 && EngineEnabled) { Manager.LogIf(LogLevel >= 1, "**********************************************************************************"); //Manager.LogIf(LogLevel >= 9, "Input: " + currentContent, "OutRewrite"); var temporyFlags = (IRuleFlagProcessor)null; bool skipNextChain = false; byte[] initialContent = currentContent; // process rules according to their settings for (int i = 0; i < _outputRules.Count; i++) { var ruleContext = new RuleContext(i, context, currentContent, _outputRules[i]); temporyFlags = _outputRules[i].Flags; bool containsChain = RuleFlagsProcessor.HasChain(_outputRules[i].Flags); bool previousContainsChain = RuleFlagsProcessor.HasChain(_outputRules[Math.Max(0, i - 1)].Flags); // if the previous rule doesn't contain a chain flag then set the initial URL // this will be used to reset a chain if one of the chain rules fail if (!previousContainsChain) initialContent = currentContent; // skip if the current rule or the last rule has a chain flag // and if the skip next chain is set if (skipNextChain && (previousContainsChain || containsChain)) continue; else skipNextChain = false; if (_outputRules[i].TryExecute(ruleContext)) { var flagResponse = temporyFlags.Apply(ruleContext); currentContent = ruleContext.SubstitutedContent; i = ruleContext.RuleIndex ?? -1; bool breakLoop = false; // apply the flags to the rules, and only do special processing // for the flag responses listed in the switch statement below switch (flagResponse) { case RuleFlagProcessorResponse.ExitRuleSet: return null; case RuleFlagProcessorResponse.LastRule: breakLoop = true; break; } // break the loop because we have reached the last rule as indicated by a flag if (breakLoop) break; } else if (containsChain) { skipNextChain = true; // reset the current URL back to the initial URL from the start of the chain currentContent = initialContent; } else if (previousContainsChain) { // reset the current URL back to the initial URL from the start of the chain currentContent = initialContent; } } //Manager.LogIf(LogLevel >= 9, "Output: " + currentContent, "OutRewrite"); Manager.LogIf(LogLevel >= 1, "**********************************************************************************"); } return currentContent; }
/// <summary> /// Runs the rules. /// </summary> /// <param name="httpContext">The HTTP context.</param> /// <param name="url">The URL.</param> /// <returns> /// Returns a rewritten <see cref="System.Uri"/>, or a value of <see langword="null"/> if no rewriting was done to <paramref name="url"/>. /// </returns> public Uri RunRules(HttpContextBase httpContext, Uri url) { var context = new RuleSetContext(this, url, httpContext); var currentUrl = url; if (!EngineEnabled) Manager.LogIf(!EngineEnabled && LogLevel >= 9, "Rewrite Engine Is DISABLED", "Rewrite"); if (_rules.Count > 0 && EngineEnabled) { Manager.LogIf(LogLevel >= 1, "**********************************************************************************"); Manager.LogIf(LogLevel >= 1, "Input: " + currentUrl, "Rewrite"); // check if max number of internal transfers have been exceeded if (InternalTransferCount(httpContext) > MaxInternalTransfers) { string message = "Exceeded the max number of internal transfers."; Manager.LogIf(LogLevel >= 1, message, "Error"); throw new HttpException(500, message); } var temporyFlags = (IRuleFlagProcessor)null; var skipNextChain = false; var initialUrl = currentUrl; if (!String.IsNullOrEmpty(VirtualBase) && VirtualBase != "/") currentUrl = RemoveBase(VirtualBase, currentUrl); // process rules according to their settings for (int i = 0; i < _rules.Count; i++) { var ruleContext = new RuleContext(i, context, currentUrl, _rules[i]); temporyFlags = _rules[i].Flags; // continue if this rule shouldn't be processed because it doesn't allow internal transfer requests if (RuleFlagsProcessor.HasNotForInternalSubRequests(temporyFlags) && IsInternalTransfer(httpContext)) continue; bool containsChain = RuleFlagsProcessor.HasChain(_rules[i].Flags); bool previousContainsChain = RuleFlagsProcessor.HasChain(_rules[Math.Max(0, i - 1)].Flags); // if the previous rule doesn't contain a chain flag then set the initial URL // this will be used to reset a chain if one of the chain rules fail if (!previousContainsChain) initialUrl = currentUrl; // skip if the current rule or the last rule has a chain flag // and if the skip next chain is set if (skipNextChain && (previousContainsChain || containsChain)) continue; else skipNextChain = false; if (_rules[i].TryExecute(ruleContext)) { var flagResponse = temporyFlags.Apply(ruleContext); currentUrl = ruleContext.SubstitutedUrl; i = ruleContext.RuleIndex ?? -1; bool breakLoop = false; // apply the flags to the rules, and only do special processing // for the flag responses listed in the switch statement below switch (flagResponse) { case RuleFlagProcessorResponse.ExitRuleSet: return null; case RuleFlagProcessorResponse.LastRule: breakLoop = true; break; } // break the loop because we have reached the last rule as indicated by a flag if (breakLoop) break; } else if (containsChain) { skipNextChain = true; // reset the current URL back to the initial URL from the start of the chain currentUrl = initialUrl; } else if (previousContainsChain) { // reset the current URL back to the initial URL from the start of the chain currentUrl = initialUrl; } } // if the scheme, host, and ports do not match on the request vs the rewrite a redirect needs to be performed instead of a rewrite if (Uri.Compare(currentUrl, context.RequestedUrl, UriComponents.SchemeAndServer, UriFormat.SafeUnescaped, StringComparison.OrdinalIgnoreCase) != 0) { Manager.LogIf(LogLevel >= 1, "Output: 302 Redirect to " + currentUrl, "Rewrite"); Manager.Redirect(httpContext, "found", currentUrl); } if (!String.IsNullOrEmpty(VirtualBase) && VirtualBase != "/") currentUrl = AddBase(VirtualBase, currentUrl); Manager.LogIf(LogLevel >= 1, "Output: " + currentUrl, "Rewrite"); Manager.LogIf(LogLevel >= 1, "**********************************************************************************"); Manager.TryToAddXRewriteUrlHeader(httpContext); Manager.TryToAddVanityHeader(httpContext); } // if the http request url matches for both the request and the rewrite no work was done so the url should be null if (Uri.Compare(currentUrl, url, UriComponents.HttpRequestUrl, UriFormat.SafeUnescaped, StringComparison.OrdinalIgnoreCase) == 0) currentUrl = null; return currentUrl; }