using System; using System.Text; using System.Text.RegularExpressions; namespace SebWindowsConfig.Utilities { public class SEBURLFilterRegexExpression { public Regex scheme; public Regex user; public Regex password; public Regex host; public int? port; public Regex path; public Regex query; public Regex fragment; public SEBURLFilterRegexExpression(string filterExpressionString) { SEBURLFilterExpression URLFromString = new SEBURLFilterExpression(filterExpressionString); try { this.scheme = RegexForFilterString(URLFromString.scheme); this.user = RegexForFilterString(URLFromString.user); this.password = RegexForFilterString(URLFromString.password); this.host = RegexForHostFilterString(URLFromString.host); this.port = URLFromString.port; this.path = RegexForPathFilterString(URLFromString.path); this.query = RegexForQueryFilterString(URLFromString.query); this.fragment = RegexForFilterString(URLFromString.fragment); } catch (Exception) { throw; } } public static Regex RegexForFilterString(string filterString) { if (string.IsNullOrEmpty(filterString)) { return null; } else { string regexString = Regex.Escape(filterString); regexString = regexString.Replace("\\*", ".*?"); // Add regex command characters for matching at start and end of a line (part) regexString = string.Format("^{0}$", regexString); try { Regex regex = new Regex(regexString, RegexOptions.IgnoreCase); return regex; } catch (Exception) { throw; } } } public static Regex RegexForHostFilterString(string filterString) { if (string.IsNullOrEmpty(filterString)) { return null; } else { try { // Check if host string has a dot "." prefix to disable subdomain matching if (filterString.Length > 1 && filterString.StartsWith(".")) { // Get host string without the "." prefix filterString = filterString.Substring(1); // Get regex for host <*://example.com> (without possible subdomains) return RegexForFilterString(filterString); } // Allow subdomain matching: Create combined regex for and <*.example.com> string regexString = Regex.Escape(filterString); regexString = regexString.Replace("\\*", ".*?"); // Add regex command characters for matching at start and end of a line (part) regexString = string.Format("^(({0})|(.*?\\.{0}))$", regexString); Regex regex = new Regex(regexString, RegexOptions.IgnoreCase); return regex; } catch (Exception) { throw; } } } public static Regex RegexForPathFilterString(string filterString) { // Trim a possible trailing slash "/", we will instead add a rule to also match paths to directories without trailing slash filterString = filterString.TrimEnd(new char[] { '/' }); ; if (string.IsNullOrEmpty(filterString)) { return null; } else { try { // Check if path string ends with a "/*" for matching contents of a directory if (filterString.EndsWith("/*")) { // As the path filter string matches for a directory, we need to add a string to match directories without trailing slash // Get path string without the "/*" suffix string filterStringDirectory = filterString.Substring(0, filterString.Length - 2); string regexString = Regex.Escape(filterString); regexString = regexString.Replace("\\*", ".*?"); string regexStringDir = Regex.Escape(filterString); regexStringDir = regexStringDir.Replace("\\*", ".*?"); // Add regex command characters for matching at start and end of a line (part) regexString = string.Format("^(({0})|({1}))$", regexString, regexStringDir); Regex regex = new Regex(regexString, RegexOptions.IgnoreCase); return regex; } else { return RegexForFilterString(filterString); } } catch (Exception) { throw; } } } public static Regex RegexForQueryFilterString(string filterString) { if (string.IsNullOrEmpty(filterString)) { return null; } else { if (filterString.Equals(".")) { // Add regex command characters for matching at start and end of a line (part) // and regex for no string allowed string regexString = @"^$"; try { Regex regex = new Regex(regexString, RegexOptions.IgnoreCase); return regex; } catch (Exception) { throw; } } else { return RegexForFilterString(filterString); } } } public override string ToString() { StringBuilder expressionString = new StringBuilder(); string part; expressionString.Append("^"); /// Scheme if (this.scheme != null) { // If there is a regex filter for scheme // get stripped regex pattern part = StringForRegexFilter(this.scheme); } else { // otherwise use the regex wildcard pattern for scheme part = @".*?"; } expressionString.AppendFormat("{0}:\\/\\/", part); /// User/Password if (this.user != null) { part = StringForRegexFilter(this.user); expressionString.Append(part); if (this.password != null) { expressionString.AppendFormat(":{0}@", StringForRegexFilter(this.password)); } else { expressionString.Append("@"); } } /// Host string hostPort = ""; if (this.host != null) { hostPort = StringForRegexFilter(this.host); } else { hostPort = ".*?"; } /// Port if (this.port != null && this.port > 0 && this.port <= 65535) { hostPort = string.Format("{0}:{1}", hostPort, this.port); } // When there is a host, but no path if (this.host != null && this.path == null) { hostPort = string.Format("(({0})|({0}\\/.*?))", hostPort); } expressionString.Append(hostPort); /// Path if (this.path != null) { string path = StringForRegexFilter(this.path); if (path.StartsWith("\\/")) { expressionString.Append(path); } else { expressionString.AppendFormat("\\/{0}", path); } } /// Query if (this.query != null) { // Check for special case Query = "?." which means no query string is allowed if (StringForRegexFilter(this.query).Equals(".")) { expressionString.AppendFormat("[^\\?]"); } else { expressionString.AppendFormat("\\?{0}", StringForRegexFilter(this.query)); } } else { expressionString.AppendFormat("(()|(\\?.*?))"); } /// Fragment if (this.fragment != null) { expressionString.AppendFormat("#{0}", StringForRegexFilter(this.fragment)); } expressionString.Append("$"); return expressionString.ToString(); } public string StringForRegexFilter(Regex regexFilter) { // Get pattern string from regular expression string regexPattern = regexFilter.ToString(); if (regexPattern.Length <= 2) { return ""; } // Remove the regex command characters for matching at start and end of a line regexPattern = regexPattern.Substring(1, regexPattern.Length - 2); return regexPattern; } } }