/// <summary> /// Removes verbose data from the constructed instance. /// </summary> public override void TrimExcessData() { ApplicableDomains.Clear(); ExceptionDomains.Clear(); OriginalRule = string.Empty; }
/// <summary> /// Determines whether or not this filter is a match for the supplied HTTP request/response. /// </summary> /// <param name="uri"> /// The URI to check against for a match. /// </param> /// <param name="rawHeaders"> /// The headers for the request/response we're checking to see if we match against. These may /// modify the capability to match depending on their content, such as content-type, etc. /// </param> /// <returns> /// True if this filter is a positive match against the supplied URI, false otherwise. /// </returns> public bool IsMatch(Uri uri, NameValueCollection rawHeaders) { // Make sure that the headers match up with our options. if (this.Options != UrlFilterOptions.None) { string headerVal = null; long xmlHttpRequestBits = ((OptionsLong & (long)UrlFilterOptions.ExceptXmlHttpRequest) | (OptionsLong & (long)UrlFilterOptions.XmlHttpRequest)); if ((headerVal = rawHeaders.Get("X-Requested-With")) != null) { if (headerVal.EqualsAtICase("XMLHttpRequest", 0)) { xmlHttpRequestBits &= ~(long)UrlFilterOptions.XmlHttpRequest; } else { xmlHttpRequestBits &= ~(long)UrlFilterOptions.ExceptXmlHttpRequest; } } if (xmlHttpRequestBits != 0) { // XML HttpRequest bits were not cleared, meaning that one of those options was // not satisifed. return(false); } long thirdPartyBits = ((OptionsLong & (long)UrlFilterOptions.ThirdParty) | (OptionsLong & (long)UrlFilterOptions.ExceptThirdParty)); if ((headerVal = rawHeaders.Get("Referer")) != null) { if (Uri.TryCreate(headerVal, UriKind.RelativeOrAbsolute, out Uri refererUri)) { string hostWithoutWww = refererUri.Host; if (hostWithoutWww.StartsWithQuick("www.")) { hostWithoutWww = hostWithoutWww.Substring(4); } if (hostWithoutWww.EqualsAtICase(uri.Host, 0)) { thirdPartyBits &= ~(long)UrlFilterOptions.ExceptThirdParty; } else { thirdPartyBits &= ~(long)UrlFilterOptions.ThirdParty; } if (ApplicableDomains.Count > 0 && !ApplicableDomains.Contains(hostWithoutWww)) { return(false); } if (ExceptionDomains.Count > 0 && ExceptionDomains.Contains(hostWithoutWww)) { return(false); } // While we have the referer field, let's go ahead and check if we have // referer options and if we do or don't have a match. // // This is a shortcut. We unfortunately need to also execute this code also // when there are no options. if (ApplicableReferers.Count > 0 && !ApplicableReferers.Contains(hostWithoutWww)) { return(false); } if (ExceptReferers.Count > 0 && ExceptReferers.Contains(hostWithoutWww)) { return(false); } } } else { // The "Referer" field can be omitted when it's a brand new browser request/fresh // browser context, meaning that this request is not third party in the least // bit. So, we clear this bit in this special case. thirdPartyBits &= ~(long)UrlFilterOptions.ExceptThirdParty; } if (thirdPartyBits != 0) { // Third party bits not cleared, meaning that one of those options was not satisifed. return(false); } long contentTypeBits = ((OptionsLong & (long)UrlFilterOptions.Image) | (OptionsLong & (long)UrlFilterOptions.Script) | (OptionsLong & (long)UrlFilterOptions.StyleSheet) | (OptionsLong & (long)UrlFilterOptions.ExceptImage) | (OptionsLong & (long)UrlFilterOptions.ExceptScript) | (OptionsLong & (long)UrlFilterOptions.ExceptStyleSheet)); if ((headerVal = rawHeaders.Get("Content-Type")) != null) { if (headerVal.IndexOfQuick("script") != -1) { contentTypeBits &= ~(long)UrlFilterOptions.Script; } else { contentTypeBits &= ~(long)UrlFilterOptions.ExceptScript; if (headerVal.IndexOfQuick("image") != -1) { contentTypeBits &= ~(long)UrlFilterOptions.Image; } else { contentTypeBits &= ~(long)UrlFilterOptions.ExceptImage; if (headerVal.IndexOfQuick("css") != -1) { contentTypeBits &= ~(long)UrlFilterOptions.StyleSheet; } else { contentTypeBits &= ~(long)UrlFilterOptions.ExceptStyleSheet; } } } } if (contentTypeBits != 0) { // XML HttpRequest bits were not cleared, meaning that one of those options was // not satisifed. return(false); } } else { if (ApplicableReferers.Count > 0 || ExceptReferers.Count > 0) { string headerVal = null; if ((headerVal = rawHeaders.Get("Referer")) != null) { if (Uri.TryCreate(headerVal, UriKind.RelativeOrAbsolute, out Uri refererUri)) { string hostWithoutWww = refererUri.Host; if (hostWithoutWww.StartsWithQuick("www.")) { hostWithoutWww = hostWithoutWww.Substring(4); } if (ApplicableReferers.Count > 0 && !ApplicableReferers.Contains(hostWithoutWww)) { return(false); } if (ExceptReferers.Count > 0 && ExceptReferers.Contains(hostWithoutWww)) { return(false); } } } } } if (ApplicableDomains.Count > 0 || ExceptionDomains.Count > 0) { string hostWithoutWww = uri.Host; if (hostWithoutWww.StartsWithQuick("www.")) { hostWithoutWww = hostWithoutWww.Substring(4); } if (ApplicableDomains.Count > 0 && !ApplicableDomains.Contains(hostWithoutWww)) { return(false); } if (ExceptionDomains.Count > 0 && ExceptionDomains.Contains(hostWithoutWww)) { return(false); } } int matchIndex = 0; foreach (var part in Parts) { matchIndex = part.IsMatch(uri, matchIndex); if (matchIndex == -1) { return(false); } } // If all parts were found, then this match was a success. return(true); }