SEBWIN-314: Completed implementation of simplified filter rule.
This commit is contained in:
parent
6d1b282b33
commit
d3272814bd
3 changed files with 909 additions and 215 deletions
|
@ -89,7 +89,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Filters
|
||||||
|
|
||||||
filterComponent = path;
|
filterComponent = path;
|
||||||
if (filterComponent != null &&
|
if (filterComponent != null &&
|
||||||
!Regex.IsMatch(URLToFilter.AbsolutePath.Trim(new char[] { '/' }), filterComponent.ToString(), RegexOptions.IgnoreCase))
|
!Regex.IsMatch(URLToFilter.AbsolutePath.TrimEnd(new char[] { '/' }), filterComponent.ToString(), RegexOptions.IgnoreCase))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -404,8 +404,8 @@ namespace SafeExamBrowser.Browser.UnitTests.Filters
|
||||||
this.password = regexMatch.Groups[3].Value;
|
this.password = regexMatch.Groups[3].Value;
|
||||||
this.host = regexMatch.Groups[4].Value;
|
this.host = regexMatch.Groups[4].Value;
|
||||||
|
|
||||||
// Treat a special case when a query is interpreted as part of the host address
|
// Treat a special case when a query or fragment is interpreted as part of the host address
|
||||||
if (this.host.Contains("?"))
|
if (this.host.Contains("?") || this.host.Contains("#"))
|
||||||
{
|
{
|
||||||
string splitURLRegexPattern2 = @"([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?";
|
string splitURLRegexPattern2 = @"([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?";
|
||||||
Regex splitURLRegex2 = new Regex(splitURLRegexPattern2);
|
Regex splitURLRegex2 = new Regex(splitURLRegexPattern2);
|
||||||
|
@ -434,7 +434,7 @@ namespace SafeExamBrowser.Browser.UnitTests.Filters
|
||||||
this.port = UInt16.Parse(portNumber);
|
this.port = UInt16.Parse(portNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.path = regexMatch.Groups[6].Value.Trim(new char[] { '/' });
|
this.path = regexMatch.Groups[6].Value.TrimEnd(new char[] { '/' });
|
||||||
this.query = regexMatch.Groups[7].Value;
|
this.query = regexMatch.Groups[7].Value;
|
||||||
this.fragment = regexMatch.Groups[8].Value;
|
this.fragment = regexMatch.Groups[8].Value;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,16 +15,15 @@ namespace SafeExamBrowser.Browser.Filters.Rules
|
||||||
{
|
{
|
||||||
internal class SimplifiedRule : IRule
|
internal class SimplifiedRule : IRule
|
||||||
{
|
{
|
||||||
private const string URL_DELIMITER_PATTERN = @"(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*))?(?:\:([0-9\*]*))?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?";
|
private const string URL_DELIMITER_PATTERN = @"(?:([^\:]*)\://)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^/\:\?#]*))?(?:\:([0-9\*]*))?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?";
|
||||||
|
|
||||||
private Regex fragment;
|
private Regex fragment;
|
||||||
private Regex host;
|
private Regex host;
|
||||||
private Regex password;
|
|
||||||
private Regex path;
|
private Regex path;
|
||||||
private int? port;
|
private int? port;
|
||||||
private Regex query;
|
private Regex query;
|
||||||
private Regex scheme;
|
private Regex scheme;
|
||||||
private Regex user;
|
private Regex userInfo;
|
||||||
|
|
||||||
public FilterResult Result { get; private set; }
|
public FilterResult Result { get; private set; }
|
||||||
|
|
||||||
|
@ -41,14 +40,13 @@ namespace SafeExamBrowser.Browser.Filters.Rules
|
||||||
var url = new Uri(request.Url, UriKind.Absolute);
|
var url = new Uri(request.Url, UriKind.Absolute);
|
||||||
var isMatch = true;
|
var isMatch = true;
|
||||||
|
|
||||||
//isMatch &= scheme == default(Regex) || ...;
|
isMatch &= scheme == default(Regex) || scheme.IsMatch(url.Scheme);
|
||||||
//isMatch &= user == default(Regex) || ...;
|
isMatch &= userInfo == default(Regex) || userInfo.IsMatch(url.UserInfo);
|
||||||
//isMatch &= password == default(Regex) || ...;
|
|
||||||
isMatch &= host.IsMatch(url.Host);
|
isMatch &= host.IsMatch(url.Host);
|
||||||
isMatch &= !port.HasValue || port == url.Port;
|
isMatch &= !port.HasValue || port == url.Port;
|
||||||
//isMatch &= path == default(Regex) || ...;
|
isMatch &= path == default(Regex) || path.IsMatch(url.AbsolutePath);
|
||||||
//isMatch &= query == default(Regex) || ...;
|
isMatch &= query == default(Regex) || query.IsMatch(url.Query);
|
||||||
//isMatch &= fragment == default(Regex) || ...;
|
isMatch &= fragment == default(Regex) || fragment.IsMatch(url.Fragment);
|
||||||
|
|
||||||
return isMatch;
|
return isMatch;
|
||||||
}
|
}
|
||||||
|
@ -57,36 +55,58 @@ namespace SafeExamBrowser.Browser.Filters.Rules
|
||||||
{
|
{
|
||||||
var match = Regex.Match(expression, URL_DELIMITER_PATTERN);
|
var match = Regex.Match(expression, URL_DELIMITER_PATTERN);
|
||||||
|
|
||||||
//ParseScheme(match.Groups[1].Value);
|
ParseScheme(match.Groups[1].Value);
|
||||||
//ParseUser(match.Groups[2].Value);
|
ParseUserInfo(match.Groups[2].Value, match.Groups[3].Value);
|
||||||
//ParsePassword(match.Groups[3].Value);
|
|
||||||
ParseHost(match.Groups[4].Value);
|
ParseHost(match.Groups[4].Value);
|
||||||
ParsePort(match.Groups[5].Value);
|
ParsePort(match.Groups[5].Value);
|
||||||
//ParsePath(match.Groups[6].Value);
|
ParsePath(match.Groups[6].Value);
|
||||||
//ParseQuery(match.Groups[7].Value);
|
ParseQuery(match.Groups[7].Value);
|
||||||
//ParseFragment(match.Groups[8].Value);
|
ParseFragment(match.Groups[8].Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseScheme(string expression)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(expression))
|
||||||
|
{
|
||||||
|
expression = Regex.Escape(expression);
|
||||||
|
expression = ReplaceWildcard(expression);
|
||||||
|
|
||||||
|
scheme = Build(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseUserInfo(string username, string password)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(username))
|
||||||
|
{
|
||||||
|
var expression = default(string);
|
||||||
|
|
||||||
|
username = Regex.Escape(username);
|
||||||
|
password = Regex.Escape(password);
|
||||||
|
|
||||||
|
expression = string.IsNullOrEmpty(password) ? $@"{username}(:.*)?" : $@"{username}:{password}";
|
||||||
|
expression = ReplaceWildcard(expression);
|
||||||
|
|
||||||
|
userInfo = Build(expression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseHost(string expression)
|
private void ParseHost(string expression)
|
||||||
{
|
{
|
||||||
var hasToplevelDomain = Regex.IsMatch(expression, @"\.+");
|
var hasToplevelDomain = Regex.IsMatch(expression, @"\.+");
|
||||||
var hasSubdomain = Regex.IsMatch(expression, @"\.{2,}");
|
var hasSubdomain = Regex.IsMatch(expression, @"\.{2,}");
|
||||||
var allowOnlyExactSubdomain = expression.StartsWith(".");
|
var matchExactSubdomain = expression.StartsWith(".");
|
||||||
|
|
||||||
if (allowOnlyExactSubdomain)
|
|
||||||
{
|
|
||||||
expression = expression.Substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
expression = matchExactSubdomain ? expression.Substring(1) : expression;
|
||||||
expression = Regex.Escape(expression);
|
expression = Regex.Escape(expression);
|
||||||
expression = ReplaceWildcard(expression);
|
expression = ReplaceWildcard(expression);
|
||||||
|
|
||||||
if (!hasToplevelDomain)
|
if (!hasToplevelDomain)
|
||||||
{
|
{
|
||||||
expression = $@"{expression}(\.[a-z]+)";
|
expression = $@"{expression}(\.[a-z]+)?";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasSubdomain && !allowOnlyExactSubdomain)
|
if (!hasSubdomain && !matchExactSubdomain)
|
||||||
{
|
{
|
||||||
expression = $@"(.+?\.)*{expression}";
|
expression = $@"(.+?\.)*{expression}";
|
||||||
}
|
}
|
||||||
|
@ -102,6 +122,51 @@ namespace SafeExamBrowser.Browser.Filters.Rules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ParsePath(string expression)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(expression))
|
||||||
|
{
|
||||||
|
expression = Regex.Escape(expression);
|
||||||
|
expression = ReplaceWildcard(expression);
|
||||||
|
expression = expression.EndsWith("/") ? $@"{expression}?" : $@"{expression}/?";
|
||||||
|
|
||||||
|
path = Build(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseQuery(string expression)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(expression))
|
||||||
|
{
|
||||||
|
var noQueryAllowed = expression == ".";
|
||||||
|
|
||||||
|
if (noQueryAllowed)
|
||||||
|
{
|
||||||
|
expression = @"\??";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expression = Regex.Escape(expression);
|
||||||
|
expression = ReplaceWildcard(expression);
|
||||||
|
expression = $@"\??{expression}";
|
||||||
|
}
|
||||||
|
|
||||||
|
query = Build(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseFragment(string expression)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(expression))
|
||||||
|
{
|
||||||
|
expression = Regex.Escape(expression);
|
||||||
|
expression = ReplaceWildcard(expression);
|
||||||
|
expression = $"#?{expression}";
|
||||||
|
|
||||||
|
fragment = Build(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Regex Build(string expression)
|
private Regex Build(string expression)
|
||||||
{
|
{
|
||||||
return new Regex($"^{expression}$", RegexOptions.IgnoreCase);
|
return new Regex($"^{expression}$", RegexOptions.IgnoreCase);
|
||||||
|
@ -109,7 +174,7 @@ namespace SafeExamBrowser.Browser.Filters.Rules
|
||||||
|
|
||||||
private string ReplaceWildcard(string expression)
|
private string ReplaceWildcard(string expression)
|
||||||
{
|
{
|
||||||
return expression.Replace(@"\*", ".*?");
|
return expression.Replace(@"\*", ".*");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateExpression(string expression)
|
private void ValidateExpression(string expression)
|
||||||
|
|
Loading…
Reference in a new issue