From 9c5ed685c5ba3207eb83a21e834b9bb2ccb1aaf1 Mon Sep 17 00:00:00 2001 From: Austin King Date: Tue, 13 Mar 2012 16:40:39 -0700 Subject: [PATCH] First stab at RFC 2254 filter escaping --- lib/filters/approx_filter.js | 6 +++-- lib/filters/equality_filter.js | 6 +++-- lib/filters/escape.js | 43 ++++++++++++++++++++++++++++++++++ lib/filters/ge_filter.js | 6 +++-- lib/filters/le_filter.js | 6 +++-- lib/filters/presence_filter.js | 4 +++- lib/filters/substr_filter.js | 6 +++-- test/filters/eq.test.js | 11 +++++++++ test/filters/parse.test.js | 29 +++++++++++++++++++---- 9 files changed, 101 insertions(+), 16 deletions(-) create mode 100644 lib/filters/escape.js diff --git a/lib/filters/approx_filter.js b/lib/filters/approx_filter.js index e654b83..4faff38 100644 --- a/lib/filters/approx_filter.js +++ b/lib/filters/approx_filter.js @@ -3,6 +3,8 @@ var assert = require('assert'); var util = require('util'); +var escape = require('./escape').escape; + var Filter = require('./filter'); var Protocol = require('../protocol'); @@ -17,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 = options.attribute; - this.value = options.value; + this.attribute = escape(options.attribute); + this.value = escape(options.value); } else { options = {}; } diff --git a/lib/filters/equality_filter.js b/lib/filters/equality_filter.js index 4bd9bf7..87b7931 100644 --- a/lib/filters/equality_filter.js +++ b/lib/filters/equality_filter.js @@ -3,6 +3,8 @@ var assert = require('assert'); var util = require('util'); +var escape = require('./escape').escape; + var Filter = require('./filter'); var Protocol = require('../protocol'); @@ -17,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 = options.attribute; - this.value = options.value; + this.attribute = escape(options.attribute); + this.value = escape(options.value); } else { options = {}; } diff --git a/lib/filters/escape.js b/lib/filters/escape.js new file mode 100644 index 0000000..e8706c9 --- /dev/null +++ b/lib/filters/escape.js @@ -0,0 +1,43 @@ +// Copyright 2011 Mark Cavage, Inc. All rights reserved. + +/** + * RFC 2254 Escaping of filter strings + * + * Raw Escaped + * (o=Parens (R Us)) (o=Parens \28R Us\29) + * (cn=star*) (cn=star\2A) + * (filename=C:\MyFile) (filename=C:\5cMyFile) + * + * Use substr_filter to avoid having * ecsaped. + */ +exports.escape = function (inp) { + if (typeof inp === 'string') { + var esc = ""; + for (var i=0; i < inp.length; i++) { + switch (inp[i]) { + case '*': + esc += "\\2a"; + break; + case '(': + esc += "\\28"; + break; + case ')': + esc += "\\29"; + break; + case '\\': + esc += "\\5c"; + break; + case '\0': + esc += "\\00"; + break; + default: + esc += inp[i]; + break; + } + } + return esc; + + } else { + return inp; + } +}; \ No newline at end of file diff --git a/lib/filters/ge_filter.js b/lib/filters/ge_filter.js index c25163d..8ca7e52 100644 --- a/lib/filters/ge_filter.js +++ b/lib/filters/ge_filter.js @@ -3,6 +3,8 @@ var assert = require('assert'); var util = require('util'); +var escape = require('./escape').escape; + var Filter = require('./filter'); var Protocol = require('../protocol'); @@ -17,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 = options.attribute; - this.value = options.value; + this.attribute = escape(options.attribute); + this.value = escape(options.value); } else { options = {}; } diff --git a/lib/filters/le_filter.js b/lib/filters/le_filter.js index b5fd910..c2eab53 100644 --- a/lib/filters/le_filter.js +++ b/lib/filters/le_filter.js @@ -3,6 +3,8 @@ var assert = require('assert'); var util = require('util'); +var escape = require('./escape').escape; + var Filter = require('./filter'); var Protocol = require('../protocol'); @@ -17,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 = options.attribute; - this.value = options.value; + this.attribute = escape(options.attribute); + this.value = escape(options.value); } else { options = {}; } diff --git a/lib/filters/presence_filter.js b/lib/filters/presence_filter.js index 8a57ca4..a5ac76c 100644 --- a/lib/filters/presence_filter.js +++ b/lib/filters/presence_filter.js @@ -3,6 +3,8 @@ var assert = require('assert'); var util = require('util'); +var escape = require('./escape').escape; + var Filter = require('./filter'); var Protocol = require('../protocol'); @@ -14,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 = options.attribute; + this.attribute = escape(options.attribute); } else { options = {}; } diff --git a/lib/filters/substr_filter.js b/lib/filters/substr_filter.js index 4c1c57c..a8045fa 100644 --- a/lib/filters/substr_filter.js +++ b/lib/filters/substr_filter.js @@ -3,6 +3,8 @@ var assert = require('assert'); var util = require('util'); +var escape = require('./escape').escape; + var Filter = require('./filter'); var Protocol = require('../protocol'); @@ -15,8 +17,8 @@ function SubstringFilter(options) { if (typeof (options) === 'object') { if (!options.attribute || typeof (options.attribute) !== 'string') throw new TypeError('options.attribute (string) required'); - this.attribute = options.attribute; - this.initial = options.initial || null; + this.attribute = escape(options.attribute); + this.initial = options.initial ? escape(options.initial) : null; this.any = options.any ? options.any.slice(0) : []; this['final'] = options['final'] || null; } else { diff --git a/test/filters/eq.test.js b/test/filters/eq.test.js index 454c38f..58958ff 100644 --- a/test/filters/eq.test.js +++ b/test/filters/eq.test.js @@ -91,6 +91,17 @@ test('parse ok', function (t) { t.end(); }); +test('escape EqualityFilter inputs', function (t) { + var f = new EqualityFilter({ + attribute: '(|(foo', + value: 'bar))(' + }); + + t.equal(f.attribute, '\\28|\\28foo'); + t.equal(f.value, 'bar\\29\\29\\28'); + t.end(); +}); + test('parse bad', function (t) { var writer = new BerWriter(); diff --git a/test/filters/parse.test.js b/test/filters/parse.test.js index c4a4754..c0dfbe4 100644 --- a/test/filters/parse.test.js +++ b/test/filters/parse.test.js @@ -36,17 +36,36 @@ test('( in filter', function (t) { var f = parse(str); t.ok(f); t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar('); + t.equal(f.value, 'bar\\28'); 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.equal(f.value, 'bar\\29'); + t.end(); +}); + + +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.end(); +}); + + +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.end(); }); @@ -56,7 +75,7 @@ test('\\ in filter', function (t) { var f = parse(str); t.ok(f); t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar\\'); + t.equal(f.value, 'bar\\5c'); t.end(); }); @@ -66,7 +85,7 @@ test('* in equality filter', function (t) { var f = parse(str); t.ok(f); t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar*'); + t.equal(f.value, 'bar\\2a'); t.end(); });