#80 added support for escaping pipe control characters (#113)

* #80 added support for escaping comma and pipe control characters

* Update SieveModel.cs

Fix build. Accidentally broken by resolving conflicts.

* Migrate UnitTests to xUnit

Co-authored-by: Clayton Andersen <candersen@restaurant365.com>
Co-authored-by: ITDancer13 <kevin@ksommer.eu>
Co-authored-by: ITDancer139 <kevinitdancersommer@gmail.com>
This commit is contained in:
Clayton Andersen 2021-05-15 04:50:12 -07:00 committed by GitHub
parent 7ced211758
commit 285468522c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 3 deletions

View File

@ -9,6 +9,7 @@ namespace Sieve.Models
public FilterTerm() { } public FilterTerm() { }
private const string EscapedPipePattern = @"(?<!($|[^\\])(\\\\)*?\\)\|"; private const string EscapedPipePattern = @"(?<!($|[^\\])(\\\\)*?\\)\|";
private const string PipeToEscape = @"\|";
private static readonly string[] Operators = new string[] { private static readonly string[] Operators = new string[] {
"!@=*", "!@=*",
@ -36,7 +37,11 @@ namespace Sieve.Models
var filterSplits = value.Split(Operators, StringSplitOptions.RemoveEmptyEntries) var filterSplits = value.Split(Operators, StringSplitOptions.RemoveEmptyEntries)
.Select(t => t.Trim()).ToArray(); .Select(t => t.Trim()).ToArray();
Names = Regex.Split(filterSplits[0], EscapedPipePattern).Select(t => t.Trim()).ToArray(); Names = Regex.Split(filterSplits[0], EscapedPipePattern).Select(t => t.Trim()).ToArray();
Values = filterSplits.Length > 1 ? Regex.Split(filterSplits[1], EscapedPipePattern).Select(t => t.Trim()).ToArray() : null; Values = filterSplits.Length > 1
? Regex.Split(filterSplits[1], EscapedPipePattern)
.Select(t => t.Replace(PipeToEscape, "|").Trim())
.ToArray()
: null;
Operator = Array.Find(Operators, o => value.Contains(o)) ?? "=="; Operator = Array.Find(Operators, o => value.Contains(o)) ?? "==";
OperatorParsed = GetOperatorParsed(Operator); OperatorParsed = GetOperatorParsed(Operator);
OperatorIsCaseInsensitive = Operator.EndsWith("*"); OperatorIsCaseInsensitive = Operator.EndsWith("*");
@ -90,6 +95,5 @@ namespace Sieve.Models
&& Values.SequenceEqual(other.Values) && Values.SequenceEqual(other.Values)
&& Operator == other.Operator; && Operator == other.Operator;
} }
} }
} }

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;

View File

@ -613,5 +613,61 @@ namespace SieveUnitTests
Assert.Equal(1,posts[2].Id); Assert.Equal(1,posts[2].Id);
Assert.Equal(0,posts[3].Id); Assert.Equal(0,posts[3].Id);
} }
[Fact]
public void CanFilter_WithEscapeCharacter()
{
var comments = new List<Comment>
{
new Comment
{
Id = 0,
DateCreated = DateTimeOffset.UtcNow,
Text = "Here is, a comment"
},
new Comment
{
Id = 1,
DateCreated = DateTimeOffset.UtcNow.AddDays(-1),
Text = "Here is, another comment"
},
}.AsQueryable();
var model = new SieveModel
{
Filters = "Text==Here is\\, another comment"
};
var result = _processor.Apply(model, comments);
Assert.Equal(1, result.Count());
}
[Fact]
public void OrEscapedPipeValueFilteringWorks()
{
var comments = new List<Comment>
{
new Comment
{
Id = 0,
DateCreated = DateTimeOffset.UtcNow,
Text = "Here is | a comment"
},
new Comment
{
Id = 1,
DateCreated = DateTimeOffset.UtcNow.AddDays(-1),
Text = "Here is | another comment"
},
}.AsQueryable();
var model = new SieveModel()
{
Filters = "Text==Here is \\| a comment|Here is \\| another comment",
};
var result = _processor.Apply(model, comments);
Assert.Equal(2, result.Count());
}
} }
} }