From 11b3a6655d29cf3248c995843a443603eed31226 Mon Sep 17 00:00:00 2001 From: Mark Cavage Date: Thu, 19 Jan 2012 15:12:19 -0800 Subject: [PATCH] Support escaping * in filter values --- lib/filters/index.js | 97 ++++++++++++++++++++++++++++----------- tst/filters/parse.test.js | 50 ++++++++++++++++++++ tst/laundry.test.js | 2 +- 3 files changed, 122 insertions(+), 27 deletions(-) diff --git a/lib/filters/index.js b/lib/filters/index.js index f54a474..2d4379f 100644 --- a/lib/filters/index.js +++ b/lib/filters/index.js @@ -138,40 +138,67 @@ function _buildFilterTree(expr) { tree.name = expr; } else { // pull out lhs and rhs of equality operator - + var clean = false; var splitAry = expr.split(operatorStr); tree.name = splitAry.shift(); tree.value = splitAry.join(operatorStr); - // substrings and extensible matching fall into the equality bin in the + // substrings fall into the equality bin in the // switch above so we need more processing here if (tree.tag === 'equalityMatch') { - if (tree.value.indexOf('*') !== -1) { - tree.tag = 'substrings'; - - split = tree.value.split('*'); - - // if the value string doesn't start with a * then theres no initial - // value else split will have an empty string in its first array - // index... - // we need to remove that empty string - if (tree.value.indexOf('*') !== 0) { - tree.initial = split.shift(); - } else { - split.shift(); - } - - //if the value string doesn't end with a * then theres no final value - //also same split stuff as the initial stuff above - if (tree.value.lastIndexOf('*') !== tree.value.length - 1) { - tree['final'] = split.pop(); - } else { - split.pop(); - } - tree.any = split; - } else if (tree.value.length === 0) { + if (tree.value.length === 0) { tree.tag = 'present'; + } else { + var substrNdx = 0; + var substr = false; + var esc = false; + + // Effectively a hand-rolled .shift() to support \* sequences + clean = true; + split = []; + substrNdx = 0; + split[substrNdx] = ''; + for (var i = 0; i < tree.value.length; i++) { + var c = tree.value[i]; + if (esc) { + split[substrNdx] += c; + esc = false; + } else if (c === '*') { + split[++substrNdx] = ''; + } else if (c === '\\') { + esc = true; + } else { + split[substrNdx] += c; + } + } + + if (split.length > 1) { + tree.tag = 'substrings'; + clean = true; + + // if the value string doesn't start with a * then theres no initial + // value else split will have an empty string in its first array + // index... + // we need to remove that empty string + if (tree.value.indexOf('*') !== 0) { + tree.initial = split.shift(); + } else { + split.shift(); + } + + // if the value string doesn't end with a * then theres no final + // value also same split stuff as the initial stuff above + if (tree.value.lastIndexOf('*') !== tree.value.length - 1) { + tree['final'] = split.pop(); + } else { + split.pop(); + } + tree.any = split; + } else { + tree.value = split[0]; // pick up the cleaned version + } } + } else if (tree.tag == 'extensibleMatch') { split = tree.name.split(':'); tree.extensible = { @@ -197,6 +224,24 @@ function _buildFilterTree(expr) { } } } + + // Cleanup any escape sequences + if (!clean) { + var val = ''; + var esc = false; + for (var i = 0; i < tree.value.length; i++) { + var c = tree.value[i]; + if (esc) { + val += c; + esc = false; + } else if (c === '\\') { + esc = true; + } else { + val += c; + } + } + tree.value = val; + } } return tree; diff --git a/tst/filters/parse.test.js b/tst/filters/parse.test.js index aee05ff..251376c 100644 --- a/tst/filters/parse.test.js +++ b/tst/filters/parse.test.js @@ -29,3 +29,53 @@ test('GH-50 = in filter', function(t) { 'uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc'); t.end(); }); + + +test('( in filter', function(t) { + var str = '(foo=bar\\()'; + var f = parse(str); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'bar('); + t.end(); +}); + + +test(') in filter', function(t) { + var str = '(foo=bar\\))'; + var f = parse(str); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'bar)'); + t.end(); +}); + + +test('\\ in filter', function(t) { + var str = '(foo=bar\\\\)'; + var f = parse(str); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'bar\\'); + t.end(); +}); + + +test('* in equality filter', function(t) { + var str = '(foo=bar\\*)'; + var f = parse(str); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'bar*'); + t.end(); +}); + + +test('* substr filter (prefix)', function(t) { + var str = '(foo=bar*)'; + var f = parse(str); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.initial, 'bar'); + t.end(); +}); diff --git a/tst/laundry.test.js b/tst/laundry.test.js index ee70cc0..d8aafc6 100644 --- a/tst/laundry.test.js +++ b/tst/laundry.test.js @@ -44,7 +44,7 @@ test('Evolution search filter (GH-3)', function(t) { }; server.search(suffix, function(req, res, next) { - console.log(req.filter.toString()); + console.log(req.filter.filters[0].type); if (req.filter.matches(entry.attributes)) res.send(entry); res.end();