From 20368c58c132ea5c6bab6f0e1520843c6009453a Mon Sep 17 00:00:00 2001 From: Sascha Tandel Date: Fri, 11 Jan 2013 11:01:51 +0100 Subject: [PATCH] #109: escape filter attribute/values only in toString() --- Makefile | 1 + lib/filters/approx_filter.js | 6 ++-- lib/filters/equality_filter.js | 6 ++-- lib/filters/ge_filter.js | 6 ++-- lib/filters/le_filter.js | 6 ++-- lib/filters/presence_filter.js | 4 +-- lib/filters/substr_filter.js | 36 ++++++++++---------- test/filters/approx.test.js | 35 +++++++++++++++++++ test/filters/eq.test.js | 40 ++++++++++++++++++++-- test/filters/ge.test.js | 35 +++++++++++++++++++ test/filters/le.test.js | 35 +++++++++++++++++++ test/filters/parse.test.js | 24 ++++++++----- test/filters/presence.test.js | 30 +++++++++++++++++ test/filters/substr.test.js | 61 ++++++++++++++++++++++++++++++++++ 14 files changed, 282 insertions(+), 43 deletions(-) diff --git a/Makefile b/Makefile index c5bdca9..328e67a 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,7 @@ CLEAN_FILES += $(TAP) ./node_modules/tap .PHONY: test test: $(TAP) $(TAP) test/*.test.js + $(TAP) test/filters/*.test.js include ./tools/mk/Makefile.deps include ./tools/mk/Makefile.targ diff --git a/lib/filters/approx_filter.js b/lib/filters/approx_filter.js index 4faff38..14b5aac 100644 --- a/lib/filters/approx_filter.js +++ b/lib/filters/approx_filter.js @@ -19,8 +19,8 @@ function ApproximateFilter(options) { throw new TypeError('options.attribute (string) required'); if (!options.value || typeof (options.value) !== 'string') throw new TypeError('options.value (string) required'); - this.attribute = escape(options.attribute); - this.value = escape(options.value); + this.attribute = options.attribute; + this.value = options.value; } else { options = {}; } @@ -41,7 +41,7 @@ module.exports = ApproximateFilter; ApproximateFilter.prototype.toString = function () { - return '(' + this.attribute + '~=' + this.value + ')'; + return '(' + escape(this.attribute) + '~=' + escape(this.value) + ')'; }; diff --git a/lib/filters/equality_filter.js b/lib/filters/equality_filter.js index 9638507..1ff1d8f 100644 --- a/lib/filters/equality_filter.js +++ b/lib/filters/equality_filter.js @@ -19,8 +19,8 @@ function EqualityFilter(options) { throw new TypeError('options.attribute (string) required'); if (!options.value || typeof (options.value) !== 'string') throw new TypeError('options.value (string) required'); - this.attribute = escape(options.attribute); - this.value = escape(options.value); + this.attribute = options.attribute; + this.value = options.value; } else { options = {}; } @@ -41,7 +41,7 @@ module.exports = EqualityFilter; EqualityFilter.prototype.toString = function () { - return '(' + this.attribute + '=' + this.value + ')'; + return '(' + escape(this.attribute) + '=' + escape(this.value) + ')'; }; diff --git a/lib/filters/ge_filter.js b/lib/filters/ge_filter.js index 8ca7e52..98f099d 100644 --- a/lib/filters/ge_filter.js +++ b/lib/filters/ge_filter.js @@ -19,8 +19,8 @@ function GreaterThanEqualsFilter(options) { throw new TypeError('options.attribute (string) required'); if (!options.value || typeof (options.value) !== 'string') throw new TypeError('options.value (string) required'); - this.attribute = escape(options.attribute); - this.value = escape(options.value); + this.attribute = options.attribute; + this.value = options.value; } else { options = {}; } @@ -42,7 +42,7 @@ module.exports = GreaterThanEqualsFilter; GreaterThanEqualsFilter.prototype.toString = function () { - return '(' + this.attribute + '>=' + this.value + ')'; + return '(' + escape(this.attribute) + '>=' + escape(this.value) + ')'; }; diff --git a/lib/filters/le_filter.js b/lib/filters/le_filter.js index c2eab53..a2f5520 100644 --- a/lib/filters/le_filter.js +++ b/lib/filters/le_filter.js @@ -19,8 +19,8 @@ function LessThanEqualsFilter(options) { throw new TypeError('options.attribute (string) required'); if (!options.value || typeof (options.value) !== 'string') throw new TypeError('options.value (string) required'); - this.attribute = escape(options.attribute); - this.value = escape(options.value); + this.attribute = options.attribute; + this.value = options.value; } else { options = {}; } @@ -42,7 +42,7 @@ module.exports = LessThanEqualsFilter; LessThanEqualsFilter.prototype.toString = function () { - return '(' + this.attribute + '<=' + this.value + ')'; + return '(' + escape(this.attribute) + '<=' + escape(this.value) + ')'; }; diff --git a/lib/filters/presence_filter.js b/lib/filters/presence_filter.js index a5ac76c..f37ec36 100644 --- a/lib/filters/presence_filter.js +++ b/lib/filters/presence_filter.js @@ -16,7 +16,7 @@ function PresenceFilter(options) { if (typeof (options) === 'object') { if (!options.attribute || typeof (options.attribute) !== 'string') throw new TypeError('options.attribute (string) required'); - this.attribute = escape(options.attribute); + this.attribute = options.attribute; } else { options = {}; } @@ -36,7 +36,7 @@ module.exports = PresenceFilter; PresenceFilter.prototype.toString = function () { - return '(' + this.attribute + '=*)'; + return '(' + escape(this.attribute) + '=*)'; }; diff --git a/lib/filters/substr_filter.js b/lib/filters/substr_filter.js index 417a2cc..00c00f9 100644 --- a/lib/filters/substr_filter.js +++ b/lib/filters/substr_filter.js @@ -18,22 +18,16 @@ function SubstringFilter(options) { if (typeof (options) === 'object') { if (!options.attribute || typeof (options.attribute) !== 'string') throw new TypeError('options.attribute (string) required'); - this.attribute = escape(options.attribute); - this.initial = options.initial ? escape(options.initial) : null; - _any = options.any ? options.any.slice(0) : []; - this['final'] = escape(options['final']) || null; + this.attribute = options.attribute; + this.initial = options.initial ? options.initial : null; + this.any = options.any ? options.any.slice(0) : []; + this['final'] = options['final'] || null; } else { options = {}; } - if (!_any) - _any = []; - - this.any = []; - var self = this; - _any.forEach(function (a) { - self.any.push(escape(a)); - }); + if (!this.any) + this.any = []; options.type = Protocol.FILTER_SUBSTRINGS; Filter.call(this, options); @@ -52,19 +46,19 @@ module.exports = SubstringFilter; SubstringFilter.prototype.toString = function () { - var str = '(' + this.attribute + '='; + var str = '(' + escape(this.attribute) + '='; if (this.initial) - str += this.initial; + str += escape(this.initial); str += '*'; this.any.forEach(function (s) { - str += s + '*'; + str += escape(s) + '*'; }); if (this['final']) - str += this['final']; + str += escape(this['final']); str += ')'; @@ -72,6 +66,10 @@ SubstringFilter.prototype.toString = function () { }; +function escapeRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); +} + SubstringFilter.prototype.matches = function (target) { if (typeof (target) !== 'object') throw new TypeError('target (object) required'); @@ -79,14 +77,14 @@ SubstringFilter.prototype.matches = function (target) { if (target.hasOwnProperty(this.attribute)) { var re = ''; if (this.initial) - re += '^' + this.initial + '.*'; + re += '^' + escapeRegExp(this.initial) + '.*'; this.any.forEach(function (s) { - re += s + '.*'; + re += escapeRegExp(s) + '.*'; }); if (this['final']) - re += this['final'] + '$'; + re += escapeRegExp(this['final']) + '$'; var matcher = new RegExp(re); var self = this; diff --git a/test/filters/approx.test.js b/test/filters/approx.test.js index d0d66b4..151d38f 100644 --- a/test/filters/approx.test.js +++ b/test/filters/approx.test.js @@ -46,6 +46,19 @@ test('Construct args', function (t) { }); +test('GH-109 = escape value only in toString()', function (t) { + var f = new ApproximateFilter({ + attribute: 'foo', + value: 'ba(r)' + }); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'ba(r)'); + t.equal(f.toString(), '(foo~=ba\\28r\\29)'); + t.end(); +}); + + test('match true', function (t) { var f = new ApproximateFilter({ attribute: 'foo', @@ -107,3 +120,25 @@ test('parse bad', function (t) { } t.end(); }); + + +test('GH-109 = to ber uses plain values', function (t) { + var f = new ApproximateFilter({ + attribute: 'foo', + value: 'ba(r)' + }); + t.ok(f); + var writer = new BerWriter(); + f.toBer(writer); + + var f = new ApproximateFilter(); + t.ok(f); + + var reader = new BerReader(writer.buffer); + reader.readSequence(); + t.ok(f.parse(reader)); + + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'ba(r)'); + t.end(); +}); diff --git a/test/filters/eq.test.js b/test/filters/eq.test.js index 58958ff..2f15ecc 100644 --- a/test/filters/eq.test.js +++ b/test/filters/eq.test.js @@ -46,6 +46,19 @@ test('Construct args', function (t) { }); +test('GH-109 = escape value only in toString()', function (t) { + var f = new EqualityFilter({ + attribute: 'foo', + value: 'ba(r)' + }); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'ba(r)'); + t.equal(f.toString(), '(foo=ba\\28r\\29)'); + t.end(); +}); + + test('match true', function (t) { var f = new EqualityFilter({ attribute: 'foo', @@ -97,8 +110,9 @@ test('escape EqualityFilter inputs', function (t) { value: 'bar))(' }); - t.equal(f.attribute, '\\28|\\28foo'); - t.equal(f.value, 'bar\\29\\29\\28'); + t.equal(f.attribute, '(|(foo'); + t.equal(f.value, 'bar))('); + t.equal(f.toString(), '(\\28|\\28foo=bar\\29\\29\\28)'); t.end(); }); @@ -118,3 +132,25 @@ test('parse bad', function (t) { } t.end(); }); + + +test('GH-109 = to ber uses plain values', function (t) { + var f = new EqualityFilter({ + attribute: 'foo', + value: 'ba(r)' + }); + t.ok(f); + var writer = new BerWriter(); + f.toBer(writer); + + var f = new EqualityFilter(); + t.ok(f); + + var reader = new BerReader(writer.buffer); + reader.readSequence(); + t.ok(f.parse(reader)); + + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'ba(r)'); + t.end(); +}); diff --git a/test/filters/ge.test.js b/test/filters/ge.test.js index b04b4c0..e8fa3c7 100644 --- a/test/filters/ge.test.js +++ b/test/filters/ge.test.js @@ -46,6 +46,19 @@ test('Construct args', function (t) { }); +test('GH-109 = escape value only in toString()', function (t) { + var f = new GreaterThanEqualsFilter({ + attribute: 'foo', + value: 'ba(r)' + }); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'ba(r)'); + t.equal(f.toString(), '(foo>=ba\\28r\\29)'); + t.end(); +}); + + test('match true', function (t) { var f = new GreaterThanEqualsFilter({ attribute: 'foo', @@ -106,3 +119,25 @@ test('parse bad', function (t) { } t.end(); }); + + +test('GH-109 = to ber uses plain values', function (t) { + var f = new GreaterThanEqualsFilter({ + attribute: 'foo', + value: 'ba(r)' + }); + t.ok(f); + var writer = new BerWriter(); + f.toBer(writer); + + var f = new GreaterThanEqualsFilter(); + t.ok(f); + + var reader = new BerReader(writer.buffer); + reader.readSequence(); + t.ok(f.parse(reader)); + + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'ba(r)'); + t.end(); +}); diff --git a/test/filters/le.test.js b/test/filters/le.test.js index f4a0f57..8244bdd 100644 --- a/test/filters/le.test.js +++ b/test/filters/le.test.js @@ -46,6 +46,19 @@ test('Construct args', function (t) { }); +test('GH-109 = escape value only in toString()', function (t) { + var f = new LessThanEqualsFilter({ + attribute: 'foo', + value: 'ba(r)' + }); + t.ok(f); + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'ba(r)'); + t.equal(f.toString(), '(foo<=ba\\28r\\29)'); + t.end(); +}); + + test('match true', function (t) { var f = new LessThanEqualsFilter({ attribute: 'foo', @@ -107,3 +120,25 @@ test('parse bad', function (t) { } t.end(); }); + + +test('GH-109 = to ber uses plain values', function (t) { + var f = new LessThanEqualsFilter({ + attribute: 'foo', + value: 'ba(r)' + }); + t.ok(f); + var writer = new BerWriter(); + f.toBer(writer); + + var f = new LessThanEqualsFilter(); + t.ok(f); + + var reader = new BerReader(writer.buffer); + reader.readSequence(); + t.ok(f.parse(reader)); + + t.equal(f.attribute, 'foo'); + t.equal(f.value, 'ba(r)'); + t.end(); +}); diff --git a/test/filters/parse.test.js b/test/filters/parse.test.js index 6302cc0..4588f13 100644 --- a/test/filters/parse.test.js +++ b/test/filters/parse.test.js @@ -36,7 +36,8 @@ test('( in filter', function (t) { var f = parse(str); t.ok(f); t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar\\28'); + t.equal(f.value, 'bar('); + t.equal(f.toString(), '(foo=bar\\28)'); t.end(); }); @@ -45,7 +46,8 @@ test(') in filter', function (t) { var f = parse(str); t.ok(f); t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar\\29'); + t.equal(f.value, 'bar)'); + t.equal(f.toString(), '(foo=bar\\29)'); t.end(); }); @@ -54,8 +56,9 @@ test('( in filter', function (t) { var str = 'foo(bar=baz\\()'; var f = parse(str); t.ok(f); - t.equal(f.attribute, 'foo\\28bar'); - t.equal(f.value, 'baz\\28\\29'); + t.equal(f.attribute, 'foo(bar'); + t.equal(f.value, 'baz()'); + t.equal(f.toString(), '(foo\\28bar=baz\\28\\29)'); t.end(); }); @@ -64,8 +67,9 @@ test('( in filter', function (t) { var str = 'foo)(&(bar=baz)('; var f = parse(str); t.ok(f); - t.equal(f.attribute, 'foo\\29\\28&\\28bar'); - t.equal(f.value, 'baz\\29\\28'); + t.equal(f.attribute, 'foo)(&(bar'); + t.equal(f.value, 'baz)('); + t.equal(f.toString(), '(foo\\29\\28&\\28bar=baz\\29\\28)'); t.end(); }); @@ -75,7 +79,8 @@ test('\\ in filter', function (t) { var f = parse(str); t.ok(f); t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar\\5c'); + t.equal(f.value, 'bar\\'); + t.equal(f.toString(), '(foo=bar\\5c)'); t.end(); }); @@ -85,7 +90,8 @@ test('* in equality filter', function (t) { var f = parse(str); t.ok(f); t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar\\2a'); + t.equal(f.value, 'bar*'); + t.equal(f.toString(), '(foo=bar\\2a)'); t.end(); }); @@ -96,6 +102,7 @@ test('* substr filter (prefix)', function (t) { t.ok(f); t.equal(f.attribute, 'foo'); t.equal(f.initial, 'bar'); + t.equal(f.toString(), '(foo=bar*)'); t.end(); }); @@ -120,6 +127,7 @@ test('presence filter', function (t) { t.ok(f); t.equal(f.type, 'present'); t.equal(f.attribute, 'foo'); + t.equal(f.toString(), '(foo=*)'); t.end(); }); diff --git a/test/filters/presence.test.js b/test/filters/presence.test.js index e97b28e..a4eaba4 100644 --- a/test/filters/presence.test.js +++ b/test/filters/presence.test.js @@ -42,6 +42,16 @@ test('Construct args', function (t) { t.end(); }); +test('GH-109 = escape value only in toString()', function (t) { + var f = new PresenceFilter({ + attribute: 'fo)o' + }); + t.ok(f); + t.equal(f.attribute, 'fo)o'); + t.equal(f.toString(), '(fo\\29o=*)'); + t.end(); +}); + test('match true', function (t) { var f = new PresenceFilter({ @@ -76,3 +86,23 @@ test('parse ok', function (t) { t.ok(f.matches({ foo: 'bar' })); t.end(); }); + + +test('GH-109 = to ber uses plain values', function (t) { + var f = new PresenceFilter({ + attribute: 'f(o)o' + }); + t.ok(f); + var writer = new BerWriter(); + f.toBer(writer); + + var f = new PresenceFilter(); + t.ok(f); + + var reader = new BerReader(writer.buffer); + reader.readSequence(); + t.ok(f.parse(reader)); + + t.equal(f.attribute, 'f(o)o'); + t.end(); +}); diff --git a/test/filters/substr.test.js b/test/filters/substr.test.js index df8af38..fbea921 100644 --- a/test/filters/substr.test.js +++ b/test/filters/substr.test.js @@ -52,6 +52,25 @@ test('Construct args', function (t) { }); +test('GH-109 = escape value only in toString()', function (t) { + var f = new SubstringFilter({ + attribute: 'fo(o', + initial: 'ba(r)', + any: ['zi)g', 'z(ag'], + 'final': '(baz)' + }); + t.ok(f); + t.equal(f.attribute, 'fo(o'); + t.equal(f.initial, 'ba(r)'); + t.equal(f.any.length, 2); + t.equal(f.any[0], 'zi)g'); + t.equal(f.any[1], 'z(ag'); + t.equal(f['final'], '(baz)'); + t.equal(f.toString(), '(fo\\28o=ba\\28r\\29*zi\\29g*z\\28ag*\\28baz\\29)'); + t.end(); +}); + + test('match true', function (t) { var f = new SubstringFilter({ attribute: 'foo', @@ -88,6 +107,20 @@ test('match any', function (t) { t.end(); }); + +test('GH-109 = escape for regex in matches', function (t) { + var f = new SubstringFilter({ + attribute: 'fo(o', + initial: 'ba(r)', + any: ['zi)g', 'z(ag'], + 'final': '(baz)' + }); + t.ok(f); + t.ok(f.matches({ 'fo(o': ['ba(r)_zi)g-z(ag~(baz)']})); + t.end(); +}); + + test('parse ok', function (t) { var writer = new BerWriter(); writer.writeString('foo'); @@ -118,3 +151,31 @@ test('parse bad', function (t) { } t.end(); }); + + +test('GH-109 = to ber uses plain values', function (t) { + var f = new SubstringFilter({ + attribute: 'fo(o', + initial: 'ba(r)', + any: ['zi)g', 'z(ag'], + 'final': '(baz)' + }); + t.ok(f); + var writer = new BerWriter(); + f.toBer(writer); + + var f = new SubstringFilter(); + t.ok(f); + + var reader = new BerReader(writer.buffer); + reader.readSequence(); + t.ok(f.parse(reader)); + + t.equal(f.attribute, 'fo(o'); + t.equal(f.initial, 'ba(r)'); + t.equal(f.any.length, 2); + t.equal(f.any[0], 'zi)g'); + t.equal(f.any[1], 'z(ag'); + t.equal(f['final'], '(baz)'); + t.end(); +});