#109: escape filter attribute/values only in toString()

This commit is contained in:
Sascha Tandel 2013-01-11 11:01:51 +01:00
parent 51e6abf477
commit 20368c58c1
14 changed files with 282 additions and 43 deletions

View File

@ -57,6 +57,7 @@ CLEAN_FILES += $(TAP) ./node_modules/tap
.PHONY: test .PHONY: test
test: $(TAP) test: $(TAP)
$(TAP) test/*.test.js $(TAP) test/*.test.js
$(TAP) test/filters/*.test.js
include ./tools/mk/Makefile.deps include ./tools/mk/Makefile.deps
include ./tools/mk/Makefile.targ include ./tools/mk/Makefile.targ

View File

@ -19,8 +19,8 @@ function ApproximateFilter(options) {
throw new TypeError('options.attribute (string) required'); throw new TypeError('options.attribute (string) required');
if (!options.value || typeof (options.value) !== 'string') if (!options.value || typeof (options.value) !== 'string')
throw new TypeError('options.value (string) required'); throw new TypeError('options.value (string) required');
this.attribute = escape(options.attribute); this.attribute = options.attribute;
this.value = escape(options.value); this.value = options.value;
} else { } else {
options = {}; options = {};
} }
@ -41,7 +41,7 @@ module.exports = ApproximateFilter;
ApproximateFilter.prototype.toString = function () { ApproximateFilter.prototype.toString = function () {
return '(' + this.attribute + '~=' + this.value + ')'; return '(' + escape(this.attribute) + '~=' + escape(this.value) + ')';
}; };

View File

@ -19,8 +19,8 @@ function EqualityFilter(options) {
throw new TypeError('options.attribute (string) required'); throw new TypeError('options.attribute (string) required');
if (!options.value || typeof (options.value) !== 'string') if (!options.value || typeof (options.value) !== 'string')
throw new TypeError('options.value (string) required'); throw new TypeError('options.value (string) required');
this.attribute = escape(options.attribute); this.attribute = options.attribute;
this.value = escape(options.value); this.value = options.value;
} else { } else {
options = {}; options = {};
} }
@ -41,7 +41,7 @@ module.exports = EqualityFilter;
EqualityFilter.prototype.toString = function () { EqualityFilter.prototype.toString = function () {
return '(' + this.attribute + '=' + this.value + ')'; return '(' + escape(this.attribute) + '=' + escape(this.value) + ')';
}; };

View File

@ -19,8 +19,8 @@ function GreaterThanEqualsFilter(options) {
throw new TypeError('options.attribute (string) required'); throw new TypeError('options.attribute (string) required');
if (!options.value || typeof (options.value) !== 'string') if (!options.value || typeof (options.value) !== 'string')
throw new TypeError('options.value (string) required'); throw new TypeError('options.value (string) required');
this.attribute = escape(options.attribute); this.attribute = options.attribute;
this.value = escape(options.value); this.value = options.value;
} else { } else {
options = {}; options = {};
} }
@ -42,7 +42,7 @@ module.exports = GreaterThanEqualsFilter;
GreaterThanEqualsFilter.prototype.toString = function () { GreaterThanEqualsFilter.prototype.toString = function () {
return '(' + this.attribute + '>=' + this.value + ')'; return '(' + escape(this.attribute) + '>=' + escape(this.value) + ')';
}; };

View File

@ -19,8 +19,8 @@ function LessThanEqualsFilter(options) {
throw new TypeError('options.attribute (string) required'); throw new TypeError('options.attribute (string) required');
if (!options.value || typeof (options.value) !== 'string') if (!options.value || typeof (options.value) !== 'string')
throw new TypeError('options.value (string) required'); throw new TypeError('options.value (string) required');
this.attribute = escape(options.attribute); this.attribute = options.attribute;
this.value = escape(options.value); this.value = options.value;
} else { } else {
options = {}; options = {};
} }
@ -42,7 +42,7 @@ module.exports = LessThanEqualsFilter;
LessThanEqualsFilter.prototype.toString = function () { LessThanEqualsFilter.prototype.toString = function () {
return '(' + this.attribute + '<=' + this.value + ')'; return '(' + escape(this.attribute) + '<=' + escape(this.value) + ')';
}; };

View File

@ -16,7 +16,7 @@ function PresenceFilter(options) {
if (typeof (options) === 'object') { if (typeof (options) === 'object') {
if (!options.attribute || typeof (options.attribute) !== 'string') if (!options.attribute || typeof (options.attribute) !== 'string')
throw new TypeError('options.attribute (string) required'); throw new TypeError('options.attribute (string) required');
this.attribute = escape(options.attribute); this.attribute = options.attribute;
} else { } else {
options = {}; options = {};
} }
@ -36,7 +36,7 @@ module.exports = PresenceFilter;
PresenceFilter.prototype.toString = function () { PresenceFilter.prototype.toString = function () {
return '(' + this.attribute + '=*)'; return '(' + escape(this.attribute) + '=*)';
}; };

View File

@ -18,22 +18,16 @@ function SubstringFilter(options) {
if (typeof (options) === 'object') { if (typeof (options) === 'object') {
if (!options.attribute || typeof (options.attribute) !== 'string') if (!options.attribute || typeof (options.attribute) !== 'string')
throw new TypeError('options.attribute (string) required'); throw new TypeError('options.attribute (string) required');
this.attribute = escape(options.attribute); this.attribute = options.attribute;
this.initial = options.initial ? escape(options.initial) : null; this.initial = options.initial ? options.initial : null;
_any = options.any ? options.any.slice(0) : []; this.any = options.any ? options.any.slice(0) : [];
this['final'] = escape(options['final']) || null; this['final'] = options['final'] || null;
} else { } else {
options = {}; options = {};
} }
if (!_any) if (!this.any)
_any = []; this.any = [];
this.any = [];
var self = this;
_any.forEach(function (a) {
self.any.push(escape(a));
});
options.type = Protocol.FILTER_SUBSTRINGS; options.type = Protocol.FILTER_SUBSTRINGS;
Filter.call(this, options); Filter.call(this, options);
@ -52,19 +46,19 @@ module.exports = SubstringFilter;
SubstringFilter.prototype.toString = function () { SubstringFilter.prototype.toString = function () {
var str = '(' + this.attribute + '='; var str = '(' + escape(this.attribute) + '=';
if (this.initial) if (this.initial)
str += this.initial; str += escape(this.initial);
str += '*'; str += '*';
this.any.forEach(function (s) { this.any.forEach(function (s) {
str += s + '*'; str += escape(s) + '*';
}); });
if (this['final']) if (this['final'])
str += this['final']; str += escape(this['final']);
str += ')'; str += ')';
@ -72,6 +66,10 @@ SubstringFilter.prototype.toString = function () {
}; };
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
SubstringFilter.prototype.matches = function (target) { SubstringFilter.prototype.matches = function (target) {
if (typeof (target) !== 'object') if (typeof (target) !== 'object')
throw new TypeError('target (object) required'); throw new TypeError('target (object) required');
@ -79,14 +77,14 @@ SubstringFilter.prototype.matches = function (target) {
if (target.hasOwnProperty(this.attribute)) { if (target.hasOwnProperty(this.attribute)) {
var re = ''; var re = '';
if (this.initial) if (this.initial)
re += '^' + this.initial + '.*'; re += '^' + escapeRegExp(this.initial) + '.*';
this.any.forEach(function (s) { this.any.forEach(function (s) {
re += s + '.*'; re += escapeRegExp(s) + '.*';
}); });
if (this['final']) if (this['final'])
re += this['final'] + '$'; re += escapeRegExp(this['final']) + '$';
var matcher = new RegExp(re); var matcher = new RegExp(re);
var self = this; var self = this;

View File

@ -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) { test('match true', function (t) {
var f = new ApproximateFilter({ var f = new ApproximateFilter({
attribute: 'foo', attribute: 'foo',
@ -107,3 +120,25 @@ test('parse bad', function (t) {
} }
t.end(); 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();
});

View File

@ -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) { test('match true', function (t) {
var f = new EqualityFilter({ var f = new EqualityFilter({
attribute: 'foo', attribute: 'foo',
@ -97,8 +110,9 @@ test('escape EqualityFilter inputs', function (t) {
value: 'bar))(' value: 'bar))('
}); });
t.equal(f.attribute, '\\28|\\28foo'); t.equal(f.attribute, '(|(foo');
t.equal(f.value, 'bar\\29\\29\\28'); t.equal(f.value, 'bar))(');
t.equal(f.toString(), '(\\28|\\28foo=bar\\29\\29\\28)');
t.end(); t.end();
}); });
@ -118,3 +132,25 @@ test('parse bad', function (t) {
} }
t.end(); 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();
});

View File

@ -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) { test('match true', function (t) {
var f = new GreaterThanEqualsFilter({ var f = new GreaterThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
@ -106,3 +119,25 @@ test('parse bad', function (t) {
} }
t.end(); 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();
});

View File

@ -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) { test('match true', function (t) {
var f = new LessThanEqualsFilter({ var f = new LessThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
@ -107,3 +120,25 @@ test('parse bad', function (t) {
} }
t.end(); 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();
});

View File

@ -36,7 +36,8 @@ test('( in filter', function (t) {
var f = parse(str); var f = parse(str);
t.ok(f); t.ok(f);
t.equal(f.attribute, 'foo'); 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(); t.end();
}); });
@ -45,7 +46,8 @@ test(') in filter', function (t) {
var f = parse(str); var f = parse(str);
t.ok(f); t.ok(f);
t.equal(f.attribute, 'foo'); 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(); t.end();
}); });
@ -54,8 +56,9 @@ test('( in filter', function (t) {
var str = 'foo(bar=baz\\()'; var str = 'foo(bar=baz\\()';
var f = parse(str); var f = parse(str);
t.ok(f); t.ok(f);
t.equal(f.attribute, 'foo\\28bar'); t.equal(f.attribute, 'foo(bar');
t.equal(f.value, 'baz\\28\\29'); t.equal(f.value, 'baz()');
t.equal(f.toString(), '(foo\\28bar=baz\\28\\29)');
t.end(); t.end();
}); });
@ -64,8 +67,9 @@ test('( in filter', function (t) {
var str = 'foo)(&(bar=baz)('; var str = 'foo)(&(bar=baz)(';
var f = parse(str); var f = parse(str);
t.ok(f); t.ok(f);
t.equal(f.attribute, 'foo\\29\\28&\\28bar'); t.equal(f.attribute, 'foo)(&(bar');
t.equal(f.value, 'baz\\29\\28'); t.equal(f.value, 'baz)(');
t.equal(f.toString(), '(foo\\29\\28&\\28bar=baz\\29\\28)');
t.end(); t.end();
}); });
@ -75,7 +79,8 @@ test('\\ in filter', function (t) {
var f = parse(str); var f = parse(str);
t.ok(f); t.ok(f);
t.equal(f.attribute, 'foo'); 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(); t.end();
}); });
@ -85,7 +90,8 @@ test('* in equality filter', function (t) {
var f = parse(str); var f = parse(str);
t.ok(f); t.ok(f);
t.equal(f.attribute, 'foo'); 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(); t.end();
}); });
@ -96,6 +102,7 @@ test('* substr filter (prefix)', function (t) {
t.ok(f); t.ok(f);
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo');
t.equal(f.initial, 'bar'); t.equal(f.initial, 'bar');
t.equal(f.toString(), '(foo=bar*)');
t.end(); t.end();
}); });
@ -120,6 +127,7 @@ test('presence filter', function (t) {
t.ok(f); t.ok(f);
t.equal(f.type, 'present'); t.equal(f.type, 'present');
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo');
t.equal(f.toString(), '(foo=*)');
t.end(); t.end();
}); });

View File

@ -42,6 +42,16 @@ test('Construct args', function (t) {
t.end(); 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) { test('match true', function (t) {
var f = new PresenceFilter({ var f = new PresenceFilter({
@ -76,3 +86,23 @@ test('parse ok', function (t) {
t.ok(f.matches({ foo: 'bar' })); t.ok(f.matches({ foo: 'bar' }));
t.end(); 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();
});

View File

@ -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) { test('match true', function (t) {
var f = new SubstringFilter({ var f = new SubstringFilter({
attribute: 'foo', attribute: 'foo',
@ -88,6 +107,20 @@ test('match any', function (t) {
t.end(); 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) { test('parse ok', function (t) {
var writer = new BerWriter(); var writer = new BerWriter();
writer.writeString('foo'); writer.writeString('foo');
@ -118,3 +151,31 @@ test('parse bad', function (t) {
} }
t.end(); 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();
});