@ldapjs/filter
Advanced tools
Comparing version 2.0.0-rc.2 to 2.0.0-rc.3
'use strict' | ||
const protocol = require('@ldapjs/protocol') | ||
const { search } = require('@ldapjs/protocol') | ||
const AndFilter = require('../filters/and') | ||
const ApproximateFilter = require('../filters/approximate') | ||
const EqualityFilter = require('../filters/equality') | ||
const ExtensibleFilter = require('../filters/extensible') | ||
const GreaterThanEqualsFilter = require('../filters/greater-than-equals') | ||
const LessThanEqualsFilter = require('../filters/less-than-equals') | ||
const NotFilter = require('../filters/not') | ||
const OrFilter = require('../filters/or') | ||
const PresenceFilter = require('../filters/presence') | ||
const SubstringFilter = require('../filters/substring') | ||
const FILTERS = { | ||
[search.FILTER_AND]: require('../filters/and'), | ||
[search.FILTER_APPROX]: require('../filters/approximate'), | ||
[search.FILTER_EQUALITY]: require('../filters/equality'), | ||
[search.FILTER_EXT]: require('../filters/extensible'), | ||
[search.FILTER_GE]: require('../filters/greater-than-equals'), | ||
[search.FILTER_LE]: require('../filters/less-than-equals'), | ||
[search.FILTER_NOT]: require('../filters/not'), | ||
[search.FILTER_OR]: require('../filters/or'), | ||
[search.FILTER_PRESENT]: require('../filters/presence'), | ||
[search.FILTER_SUBSTRINGS]: require('../filters/substring') | ||
} | ||
@@ -37,6 +39,8 @@ /** | ||
const filterStartOffset = ber.offset | ||
const type = ber.readSequence() | ||
switch (type) { | ||
case protocol.search.FILTER_AND: { | ||
f = new AndFilter() | ||
case search.FILTER_AND: | ||
case search.FILTER_OR: { | ||
f = new FILTERS[type]() | ||
parseSet(f) | ||
@@ -46,49 +50,19 @@ break | ||
case protocol.search.FILTER_APPROX: { | ||
f = ApproximateFilter.parse(getBerBuffer(ber)) | ||
break | ||
} | ||
case protocol.search.FILTER_EQUALITY: { | ||
f = EqualityFilter.parse(getBerBuffer(ber)) | ||
return f | ||
} | ||
case protocol.search.FILTER_EXT: { | ||
f = ExtensibleFilter.parse(getBerBuffer(ber)) | ||
return f | ||
} | ||
case protocol.search.FILTER_GE: { | ||
f = GreaterThanEqualsFilter.parse(getBerBuffer(ber)) | ||
return f | ||
} | ||
case protocol.search.FILTER_LE: { | ||
f = LessThanEqualsFilter.parse(getBerBuffer(ber)) | ||
return f | ||
} | ||
case protocol.search.FILTER_NOT: { | ||
case search.FILTER_NOT: { | ||
const innerFilter = _parse(ber) | ||
f = new NotFilter({ filter: innerFilter }) | ||
f = new FILTERS[type]({ filter: innerFilter }) | ||
break | ||
} | ||
case protocol.search.FILTER_OR: { | ||
f = new OrFilter() | ||
parseSet(f) | ||
case search.FILTER_APPROX: | ||
case search.FILTER_EQUALITY: | ||
case search.FILTER_EXT: | ||
case search.FILTER_GE: | ||
case search.FILTER_LE: | ||
case search.FILTER_PRESENT: | ||
case search.FILTER_SUBSTRINGS: { | ||
f = FILTERS[type].parse(getBerBuffer(ber)) | ||
break | ||
} | ||
case protocol.search.FILTER_PRESENT: { | ||
f = PresenceFilter.parse(getBerBuffer(ber)) | ||
break | ||
} | ||
case protocol.search.FILTER_SUBSTRINGS: { | ||
f = SubstringFilter.parse(getBerBuffer(ber)) | ||
break | ||
} | ||
default: { | ||
@@ -105,3 +79,6 @@ throw Error( | ||
const end = ber.offset + ber.length | ||
while (ber.offset < end) { f.addClause(_parse(ber)) } | ||
while (ber.offset < end) { | ||
const parsed = _parse(ber) | ||
f.addClause(parsed) | ||
} | ||
} | ||
@@ -117,3 +94,3 @@ | ||
// construct a valid TLV buffer, we must rewind the offset by 2 bytes. | ||
ber.setOffset(ber.offset - 2) | ||
ber.setOffset(filterStartOffset) | ||
@@ -120,0 +97,0 @@ // Next, we need the tag so that we can supply it to the raw buffer read |
@@ -17,2 +17,3 @@ 'use strict' | ||
const SubstringFilter = require('../filters/substring') | ||
const parseString = require('../string-parsing/parse-string') | ||
@@ -196,1 +197,12 @@ tap.test('throws if BerReader not supplied', async t => { | ||
}) | ||
tap.test('parses evolution filter', async t => { | ||
const evolutionFilterFixture = require('./_fixtures/evolution-filter') | ||
const filter = parseString(evolutionFilterFixture.text) | ||
const ber = filter.toBer() | ||
t.equal(ber.buffer.compare(evolutionFilterFixture.bytes), 0) | ||
const filterFromBer = parse(ber) | ||
t.equal(filterFromBer.toString(), evolutionFilterFixture.text) | ||
}) |
'use strict' | ||
const FilterString = require('../filter-string') | ||
const { BerReader } = require('@ldapjs/asn1') | ||
const { search } = require('@ldapjs/protocol') | ||
@@ -107,19 +106,8 @@ | ||
static parse (buffer) { | ||
const reader = new BerReader(buffer) | ||
const seq = reader.readSequence() | ||
if (seq !== search.FILTER_AND) { | ||
const expected = '0x' + search.FILTER_AND.toString(16).padStart(2, '0') | ||
const found = '0x' + seq.toString(16).padStart(2, '0') | ||
throw Error(`expected and filter sequence ${expected}, got ${found}`) | ||
} | ||
// TODO: in order to parse a AND filter, we need to read the lenght | ||
// and the next tag. We must then parse the filter represented by | ||
// that tag and pass sub-buffer (of the read length) to the associated | ||
// filter's parse method. Which means we need to first finish all other | ||
// filter implementations. ~ 2022-06-19 | ||
const filter = new FilterString() | ||
return new AndFilter({ filters: [filter] }) | ||
const parseNestedFilter = require('./utils/parse-nested-filter') | ||
return parseNestedFilter({ | ||
buffer, | ||
constructor: AndFilter, | ||
startTag: search.FILTER_AND | ||
}) | ||
} | ||
@@ -126,0 +114,0 @@ } |
@@ -77,12 +77,16 @@ 'use strict' | ||
t.test('parses buffer', async t => { | ||
const input = Buffer.from([ | ||
0xa0, 0x0c, 0xa3, 0x0a, // and tag, length, eq tag, length | ||
0x04, 0x03, 0x66, 0x6f, 0x6f, // OctetString "foo" | ||
0x04, 0x03, 0x62, 0x61, 0x72 // OctetString "bar" | ||
]) | ||
const f = AndFilter.parse(input) | ||
const input = new AndFilter({ | ||
filters: [new EqualityFilter({ attribute: 'cn', value: 'foo' })] | ||
}) | ||
const f = AndFilter.parse(input.toBer().buffer) | ||
t.equal(f.clauses.length, 1) | ||
t.equal(f.toString(), '(&())') | ||
t.equal(f.toString(), '(&(cn=foo))') | ||
}) | ||
t.test('parses simple all-match filter', async t => { | ||
const input = Buffer.from([0xa0, 0x00]) | ||
const f = AndFilter.parse(input) | ||
t.equal(f.toString(), '(&)') | ||
}) | ||
t.test('throws for unexpected sequence', async t => { | ||
@@ -96,3 +100,3 @@ const input = Buffer.from([ | ||
() => AndFilter.parse(input), | ||
Error('expected and filter sequence 0xa0, got 0xa3') | ||
Error('expected filter tag 0xa0, got 0xa3') | ||
) | ||
@@ -99,0 +103,0 @@ }) |
'use strict' | ||
const FilterString = require('../filter-string') | ||
const { BerReader } = require('@ldapjs/asn1') | ||
const { search } = require('@ldapjs/protocol') | ||
@@ -105,19 +104,8 @@ | ||
static parse (buffer) { | ||
const reader = new BerReader(buffer) | ||
const seq = reader.readSequence() | ||
if (seq !== search.FILTER_NOT) { | ||
const expected = '0x' + search.FILTER_NOT.toString(16).padStart(2, '0') | ||
const found = '0x' + seq.toString(16).padStart(2, '0') | ||
throw Error(`expected not filter sequence ${expected}, got ${found}`) | ||
} | ||
// TODO: in order to parse a NOT filter, we need to read the lenght | ||
// and the next tag. We must then parse the filter represented by | ||
// that tag and pass sub-buffer (of the read length) to the associated | ||
// filter's parse method. Which means we need to first finish all other | ||
// filter implementations. ~ 2022-06-19 | ||
const filter = new FilterString() | ||
return new NotFilter({ filter }) | ||
const parseNestedFilter = require('./utils/parse-nested-filter') | ||
return parseNestedFilter({ | ||
buffer, | ||
constructor: NotFilter, | ||
startTag: search.FILTER_NOT | ||
}) | ||
} | ||
@@ -124,0 +112,0 @@ } |
'use strict' | ||
const tap = require('tap') | ||
const EqualityFilter = require('./equality') | ||
const NotFilter = require('./not') | ||
const EqualityFilter = require('./equality') | ||
const FilterString = require('../filter-string') | ||
@@ -86,10 +84,8 @@ tap.test('Construct args', async t => { | ||
t.test('parses buffer', async t => { | ||
const input = Buffer.from([ | ||
0xa2, 0x0c, 0xa3, 0x0a, // not tag, length, eq tag, length | ||
0x04, 0x03, 0x66, 0x6f, 0x6f, // OctetString "foo" | ||
0x04, 0x03, 0x62, 0x61, 0x72 // OctetString "bar" | ||
]) | ||
const f = NotFilter.parse(input) | ||
t.equal(f.filter instanceof FilterString, true) | ||
t.equal(f.toString(), '(!())') | ||
const input = new NotFilter({ | ||
filter: new EqualityFilter({ attribute: 'cn', value: 'foo' }) | ||
}) | ||
const f = NotFilter.parse(input.toBer().buffer) | ||
t.equal(f.clauses.length, 1) | ||
t.equal(f.toString(), '(!(cn=foo))') | ||
}) | ||
@@ -105,3 +101,3 @@ | ||
() => NotFilter.parse(input), | ||
Error('expected not filter sequence 0xa2, got 0xa3') | ||
Error('expected filter tag 0xa2, got 0xa3') | ||
) | ||
@@ -108,0 +104,0 @@ }) |
'use strict' | ||
const FilterString = require('../filter-string') | ||
const { BerReader } = require('@ldapjs/asn1') | ||
const { search } = require('@ldapjs/protocol') | ||
@@ -107,19 +106,8 @@ | ||
static parse (buffer) { | ||
const reader = new BerReader(buffer) | ||
const seq = reader.readSequence() | ||
if (seq !== search.FILTER_OR) { | ||
const expected = '0x' + search.FILTER_OR.toString(16).padStart(2, '0') | ||
const found = '0x' + seq.toString(16).padStart(2, '0') | ||
throw Error(`expected or filter sequence ${expected}, got ${found}`) | ||
} | ||
// TODO: in order to parse a OR filter, we need to read the lenght | ||
// and the next tag. We must then parse the filter represented by | ||
// that tag and pass sub-buffer (of the read length) to the associated | ||
// filter's parse method. Which means we need to first finish all other | ||
// filter implementations. ~ 2022-06-19 | ||
const filter = new FilterString() | ||
return new OrFilter({ filters: [filter] }) | ||
const parseNestedFilter = require('./utils/parse-nested-filter') | ||
return parseNestedFilter({ | ||
buffer, | ||
constructor: OrFilter, | ||
startTag: search.FILTER_OR | ||
}) | ||
} | ||
@@ -126,0 +114,0 @@ } |
@@ -5,2 +5,3 @@ 'use strict' | ||
const EqualityFilter = require('./equality') | ||
const SubstringFilter = require('./substring') | ||
const OrFilter = require('./or') | ||
@@ -64,12 +65,40 @@ | ||
tap.test('encodes to BER correctly', async t => { | ||
const expected = Buffer.from([ | ||
0xa1, 0x0c, 0xa3, 0x0a, // or tag, length, eq tag, length | ||
0x04, 0x03, 0x66, 0x6f, 0x6f, // OctetString "foo" | ||
0x04, 0x03, 0x62, 0x61, 0x72 // OctetString "bar" | ||
]) | ||
const eqFilter = new EqualityFilter({ attribute: 'foo', value: 'bar' }) | ||
const f = new OrFilter({ filters: [eqFilter] }) | ||
const ber = f.toBer() | ||
t.equal(expected.compare(ber.buffer), 0) | ||
tap.test('toBer', t => { | ||
t.test('encodes to BER correctly', async t => { | ||
const expected = Buffer.from([ | ||
0xa1, 0x0c, 0xa3, 0x0a, // or tag, length, eq tag, length | ||
0x04, 0x03, 0x66, 0x6f, 0x6f, // OctetString "foo" | ||
0x04, 0x03, 0x62, 0x61, 0x72 // OctetString "bar" | ||
]) | ||
const eqFilter = new EqualityFilter({ | ||
attribute: 'foo', | ||
value: 'bar' | ||
}) | ||
const f = new OrFilter({ filters: [eqFilter] }) | ||
const ber = f.toBer() | ||
t.equal(expected.compare(ber.buffer), 0) | ||
}) | ||
t.test('encodes substring filters', async t => { | ||
const expected = Buffer.from([ | ||
0xa1, 0x0d, // or tag, 13 bytes | ||
0xa4, 0x0b, // sequence (substring tag), 11 bytes | ||
0x04, 0x02, // string, 2 bytes | ||
// "cn" | ||
0x63, 0x6e, | ||
0x30, 0x05, // sequence, 5 bytes | ||
0x80, 0x03, // string (subinitial tag), 3 bytes | ||
// "foo" | ||
0x66, 0x6f, 0x6f | ||
]) | ||
const subFilter = new SubstringFilter({ | ||
attribute: 'cn', | ||
subInitial: 'foo' | ||
}) | ||
const f = new OrFilter({ filters: [subFilter] }) | ||
const ber = f.toBer() | ||
t.equal(expected.compare(ber.buffer), 0) | ||
}) | ||
t.end() | ||
}) | ||
@@ -86,3 +115,3 @@ | ||
t.equal(f.clauses.length, 1) | ||
t.equal(f.toString(), '(|())') | ||
t.equal(f.toString(), '(|(foo=bar))') | ||
}) | ||
@@ -98,7 +127,33 @@ | ||
() => OrFilter.parse(input), | ||
Error('expected or filter sequence 0xa1, got 0xa3') | ||
Error('expected filter tag 0xa1, got 0xa3') | ||
) | ||
}) | ||
t.test('parses a set of substring filters', async t => { | ||
const input = Buffer.from([ | ||
0xa1, 0x1a, // or tag, 26 bytes | ||
0xa4, 0x0b, // sequence (substring tag), 11 bytes | ||
0x04, 0x02, // string, 2 bytes | ||
// "cn" | ||
0x63, 0x6e, | ||
0x30, 0x05, // sequence, 5 bytes | ||
0x80, 0x03, // string (subinitial tag), 3 bytes | ||
// "foo" | ||
0x66, 0x6f, 0x6f, | ||
0xa4, 0x0b, // sequence (substring tag), 11 bytes | ||
0x04, 0x02, // string, 2 bytes | ||
// "sn" | ||
0x73, 0x6e, | ||
0x30, 0x05, // sequence, 5 bytes | ||
0x80, 0x03, // string (subinitial tag), 3 bytes | ||
0x66, 0x6f, 0x6f | ||
]) | ||
const filter = OrFilter.parse(input) | ||
t.equal(filter.toString(), '(|(cn=foo*)(sn=foo*))') | ||
}) | ||
t.end() | ||
}) |
@@ -142,2 +142,4 @@ 'use strict' | ||
_toBer (ber) { | ||
// Tag sequence as already been started via FilterString.toBer, so | ||
// start by writing the "type" field. | ||
ber.writeString(this.attribute) | ||
@@ -144,0 +146,0 @@ ber.startSequence() |
@@ -45,9 +45,13 @@ 'use strict' | ||
cur++ | ||
do { | ||
res = parseFilter(inputString, cur) | ||
children.push(res.filter) | ||
cur = res.end + 1 | ||
} while (cur < len && inputString[cur] !== ')') | ||
if (inputString[cur] === ')') { | ||
output = new AndFilter({}) | ||
} else { | ||
do { | ||
res = parseFilter(inputString, cur) | ||
children.push(res.filter) | ||
cur = res.end + 1 | ||
} while (cur < len && inputString[cur] !== ')') | ||
output = new AndFilter({ filters: children }) | ||
output = new AndFilter({ filters: children }) | ||
} | ||
} else if (inputString[cur] === '|') { | ||
@@ -54,0 +58,0 @@ cur++ |
@@ -26,2 +26,9 @@ 'use strict' | ||
tap.test('AndFilter', t => { | ||
t.test('match all', async t => { | ||
const result = parse('(&)') | ||
t.equal(result.end, 2) | ||
t.type(result.filter, AndFilter) | ||
t.equal(result.filter.toString(), '(&)') | ||
}) | ||
t.test('simple', async t => { | ||
@@ -28,0 +35,0 @@ const result = parse('(&(cn=foo))') |
@@ -10,3 +10,3 @@ { | ||
"description": "API for handling LDAP-style filters", | ||
"version": "2.0.0-rc.2", | ||
"version": "2.0.0-rc.3", | ||
"license": "MIT", | ||
@@ -22,3 +22,3 @@ "repository": { | ||
"dependencies": { | ||
"@ldapjs/asn1": "2.0.0-rc.2", | ||
"@ldapjs/asn1": "2.0.0-rc.3", | ||
"@ldapjs/protocol": "^1.2.1", | ||
@@ -25,0 +25,0 @@ "process-warning": "^2.1.0" |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
169443
56
5191
1
+ Added@ldapjs/asn1@2.0.0-rc.3(transitive)
- Removed@ldapjs/asn1@2.0.0-rc.2(transitive)
Updated@ldapjs/asn1@2.0.0-rc.3