diff --git a/.travis.yml b/.travis.yml index 1b53d51..53706b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,14 @@ cache: npm: true stages: + - lint - test jobs: include: - # - stage: lint ✨ - # script: npm run lint - # node_js: lts/* + - stage: lint ✨ + script: npm run lint:ci + node_js: lts/* - stage: test 👩🏽‍💻 script: npm run test:cov diff --git a/examples/inmemory.js b/examples/inmemory.js index db3523c..3937379 100644 --- a/examples/inmemory.js +++ b/examples/inmemory.js @@ -1,199 +1,177 @@ -var ldap = require('../lib/index'); +var ldap = require('../lib/index') +/// --- Shared handlers -///--- Shared handlers - -function authorize(req, res, next) { +function authorize (req, res, next) { /* Any user may search after bind, only cn=root has full power */ - var isSearch = (req instanceof ldap.SearchRequest); - if (!req.connection.ldap.bindDN.equals('cn=root') && !isSearch) - return next(new ldap.InsufficientAccessRightsError()); + var isSearch = (req instanceof ldap.SearchRequest) + if (!req.connection.ldap.bindDN.equals('cn=root') && !isSearch) { return next(new ldap.InsufficientAccessRightsError()) } - return next(); + return next() } +/// --- Globals -///--- Globals - -var SUFFIX = 'o=smartdc'; -var db = {}; -var server = ldap.createServer(); - - +var SUFFIX = 'o=smartdc' +var db = {} +var server = ldap.createServer() server.bind('cn=root', function (req, res, next) { - if (req.dn.toString() !== 'cn=root' || req.credentials !== 'secret') - return next(new ldap.InvalidCredentialsError()); + if (req.dn.toString() !== 'cn=root' || req.credentials !== 'secret') { return next(new ldap.InvalidCredentialsError()) } - res.end(); - return next(); -}); + res.end() + return next() +}) server.add(SUFFIX, authorize, function (req, res, next) { - var dn = req.dn.toString(); + var dn = req.dn.toString() - if (db[dn]) - return next(new ldap.EntryAlreadyExistsError(dn)); + if (db[dn]) { return next(new ldap.EntryAlreadyExistsError(dn)) } - db[dn] = req.toObject().attributes; - res.end(); - return next(); -}); + db[dn] = req.toObject().attributes + res.end() + return next() +}) server.bind(SUFFIX, function (req, res, next) { - var dn = req.dn.toString(); - if (!db[dn]) - return next(new ldap.NoSuchObjectError(dn)); + var dn = req.dn.toString() + if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) } - if (!db[dn].userpassword) - return next(new ldap.NoSuchAttributeError('userPassword')); + if (!db[dn].userpassword) { return next(new ldap.NoSuchAttributeError('userPassword')) } - if (db[dn].userpassword.indexOf(req.credentials) === -1) - return next(new ldap.InvalidCredentialsError()); + if (db[dn].userpassword.indexOf(req.credentials) === -1) { return next(new ldap.InvalidCredentialsError()) } - res.end(); - return next(); -}); + res.end() + return next() +}) server.compare(SUFFIX, authorize, function (req, res, next) { - var dn = req.dn.toString(); - if (!db[dn]) - return next(new ldap.NoSuchObjectError(dn)); + var dn = req.dn.toString() + if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) } - if (!db[dn][req.attribute]) - return next(new ldap.NoSuchAttributeError(req.attribute)); + if (!db[dn][req.attribute]) { return next(new ldap.NoSuchAttributeError(req.attribute)) } - var matches = false; - var vals = db[dn][req.attribute]; + var matches = false + var vals = db[dn][req.attribute] for (var i = 0; i < vals.length; i++) { if (vals[i] === req.value) { - matches = true; - break; + matches = true + break } } - res.end(matches); - return next(); -}); + res.end(matches) + return next() +}) server.del(SUFFIX, authorize, function (req, res, next) { - var dn = req.dn.toString(); - if (!db[dn]) - return next(new ldap.NoSuchObjectError(dn)); + var dn = req.dn.toString() + if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) } - delete db[dn]; + delete db[dn] - res.end(); - return next(); -}); + res.end() + return next() +}) server.modify(SUFFIX, authorize, function (req, res, next) { - var dn = req.dn.toString(); - if (!req.changes.length) - return next(new ldap.ProtocolError('changes required')); - if (!db[dn]) - return next(new ldap.NoSuchObjectError(dn)); + var dn = req.dn.toString() + if (!req.changes.length) { return next(new ldap.ProtocolError('changes required')) } + if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) } - var entry = db[dn]; + var entry = db[dn] + let mod for (var i = 0; i < req.changes.length; i++) { - mod = req.changes[i].modification; + mod = req.changes[i].modification switch (req.changes[i].operation) { - case 'replace': - if (!entry[mod.type]) - return next(new ldap.NoSuchAttributeError(mod.type)); + case 'replace': + if (!entry[mod.type]) { return next(new ldap.NoSuchAttributeError(mod.type)) } - if (!mod.vals || !mod.vals.length) { - delete entry[mod.type]; - } else { - entry[mod.type] = mod.vals; - } + if (!mod.vals || !mod.vals.length) { + delete entry[mod.type] + } else { + entry[mod.type] = mod.vals + } - break; + break - case 'add': - if (!entry[mod.type]) { - entry[mod.type] = mod.vals; - } else { - mod.vals.forEach(function (v) { - if (entry[mod.type].indexOf(v) === -1) - entry[mod.type].push(v); - }); - } + case 'add': + if (!entry[mod.type]) { + entry[mod.type] = mod.vals + } else { + mod.vals.forEach(function (v) { + if (entry[mod.type].indexOf(v) === -1) { entry[mod.type].push(v) } + }) + } - break; + break - case 'delete': - if (!entry[mod.type]) - return next(new ldap.NoSuchAttributeError(mod.type)); + case 'delete': + if (!entry[mod.type]) { return next(new ldap.NoSuchAttributeError(mod.type)) } - delete entry[mod.type]; + delete entry[mod.type] - break; + break } } - res.end(); - return next(); -}); + res.end() + return next() +}) server.search(SUFFIX, authorize, function (req, res, next) { - var dn = req.dn.toString(); - if (!db[dn]) - return next(new ldap.NoSuchObjectError(dn)); + var dn = req.dn.toString() + if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) } - var scopeCheck; + var scopeCheck switch (req.scope) { - case 'base': - if (req.filter.matches(db[dn])) { - res.send({ - dn: dn, - attributes: db[dn] - }); - } + case 'base': + if (req.filter.matches(db[dn])) { + res.send({ + dn: dn, + attributes: db[dn] + }) + } - res.end(); - return next(); + res.end() + return next() - case 'one': - scopeCheck = function (k) { - if (req.dn.equals(k)) - return true; + case 'one': + scopeCheck = function (k) { + if (req.dn.equals(k)) { return true } - var parent = ldap.parseDN(k).parent(); - return (parent ? parent.equals(req.dn) : false); - }; - break; + var parent = ldap.parseDN(k).parent() + return (parent ? parent.equals(req.dn) : false) + } + break - case 'sub': - scopeCheck = function (k) { - return (req.dn.equals(k) || req.dn.parentOf(k)); - }; + case 'sub': + scopeCheck = function (k) { + return (req.dn.equals(k) || req.dn.parentOf(k)) + } - break; + break } Object.keys(db).forEach(function (key) { - if (!scopeCheck(key)) - return; + if (!scopeCheck(key)) { return } if (req.filter.matches(db[key])) { res.send({ dn: key, attributes: db[key] - }); + }) } - }); + }) - res.end(); - return next(); -}); + res.end() + return next() +}) - - -///--- Fire it up +/// --- Fire it up server.listen(1389, function () { - console.log('LDAP server up at: %s', server.url); -}); + console.log('LDAP server up at: %s', server.url) +}) diff --git a/lib/assert.js b/lib/assert.js index 2dc693b..a757e84 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -1,61 +1,54 @@ // Copyright 2015 Joyent, Inc. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var isDN = require('./dn').DN.isDN; -var isAttribute = require('./attribute').isAttribute; +var isDN = require('./dn').DN.isDN +var isAttribute = require('./attribute').isAttribute - -///--- Helpers +/// --- Helpers // Copied from mcavage/node-assert-plus -function _assert(arg, type, name) { - name = name || type; +function _assert (arg, type, name) { + name = name || type throw new assert.AssertionError({ message: util.format('%s (%s) required', name, type), actual: typeof (arg), expected: type, operator: '===', stackStartFunction: _assert.caller - }); + }) } +/// --- API -///--- API - -function stringDN(input, name) { - if (isDN(input) || typeof (input) === 'string') - return; - _assert(input, 'DN or string', name); +function stringDN (input, name) { + if (isDN(input) || typeof (input) === 'string') { return } + _assert(input, 'DN or string', name) } -function optionalStringDN(input, name) { - if (input === undefined || isDN(input) || typeof (input) === 'string') - return; - _assert(input, 'DN or string', name); +function optionalStringDN (input, name) { + if (input === undefined || isDN(input) || typeof (input) === 'string') { return } + _assert(input, 'DN or string', name) } -function optionalDN(input, name) { - if (input !== undefined && !isDN(input)) - _assert(input, 'DN', name); +function optionalDN (input, name) { + if (input !== undefined && !isDN(input)) { _assert(input, 'DN', name) } } -function optionalArrayOfAttribute(input, name) { - if (input === undefined) - return; +function optionalArrayOfAttribute (input, name) { + if (input === undefined) { return } if (!Array.isArray(input) || - input.some(function (v) { return !isAttribute(v); })) { - _assert(input, 'array of Attribute', name); + input.some(function (v) { return !isAttribute(v) })) { + _assert(input, 'array of Attribute', name) } } - -///--- Exports +/// --- Exports module.exports = { stringDN: stringDN, optionalStringDN: optionalStringDN, optionalDN: optionalDN, optionalArrayOfAttribute: optionalArrayOfAttribute -}; +} diff --git a/lib/attribute.js b/lib/attribute.js index 4eed475..6f41a23 100644 --- a/lib/attribute.js +++ b/lib/attribute.js @@ -1,174 +1,160 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); +var assert = require('assert') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var Protocol = require('./protocol'); +var Protocol = require('./protocol') +/// --- API -///--- API - -function Attribute(options) { +function Attribute (options) { if (options) { - if (typeof (options) !== 'object') - throw new TypeError('options must be an object'); - if (options.type && typeof (options.type) !== 'string') - throw new TypeError('options.type must be a string'); + if (typeof (options) !== 'object') { throw new TypeError('options must be an object') } + if (options.type && typeof (options.type) !== 'string') { throw new TypeError('options.type must be a string') } } else { - options = {}; + options = {} } - this.type = options.type || ''; - this._vals = []; + this.type = options.type || '' + this._vals = [] - if (options.vals !== undefined && options.vals !== null) - this.vals = options.vals; + if (options.vals !== undefined && options.vals !== null) { this.vals = options.vals } } -module.exports = Attribute; +module.exports = Attribute Object.defineProperties(Attribute.prototype, { buffers: { - get: function getBuffers() { - return this._vals; + get: function getBuffers () { + return this._vals }, configurable: false }, json: { - get: function getJson() { + get: function getJson () { return { type: this.type, vals: this.vals - }; + } }, configurable: false }, vals: { - get: function getVals() { - var eType = _bufferEncoding(this.type); + get: function getVals () { + var eType = _bufferEncoding(this.type) return this._vals.map(function (v) { - return v.toString(eType); - }); + return v.toString(eType) + }) }, - set: function setVals(vals) { - var self = this; - this._vals = []; + set: function setVals (vals) { + var self = this + this._vals = [] if (Array.isArray(vals)) { vals.forEach(function (v) { - self.addValue(v); - }); + self.addValue(v) + }) } else { - self.addValue(vals); + self.addValue(vals) } }, configurable: false } -}); +}) - -Attribute.prototype.addValue = function addValue(val) { +Attribute.prototype.addValue = function addValue (val) { if (Buffer.isBuffer(val)) { - this._vals.push(val); + this._vals.push(val) } else { - this._vals.push(Buffer.from(val + '', _bufferEncoding(this.type))); + this._vals.push(Buffer.from(val + '', _bufferEncoding(this.type))) } -}; - +} /* BEGIN JSSTYLED */ -Attribute.compare = function compare(a, b) { +Attribute.compare = function compare (a, b) { if (!(Attribute.isAttribute(a)) || !(Attribute.isAttribute(b))) { - throw new TypeError('can only compare Attributes'); + throw new TypeError('can only compare Attributes') } - if (a.type < b.type) return -1; - if (a.type > b.type) return 1; - if (a.vals.length < b.vals.length) return -1; - if (a.vals.length > b.vals.length) return 1; + if (a.type < b.type) return -1 + if (a.type > b.type) return 1 + if (a.vals.length < b.vals.length) return -1 + if (a.vals.length > b.vals.length) return 1 for (var i = 0; i < a.vals.length; i++) { - if (a.vals[i] < b.vals[i]) return -1; - if (a.vals[i] > b.vals[i]) return 1; + if (a.vals[i] < b.vals[i]) return -1 + if (a.vals[i] > b.vals[i]) return 1 } - return 0; -}; + return 0 +} /* END JSSTYLED */ +Attribute.prototype.parse = function parse (ber) { + assert.ok(ber) -Attribute.prototype.parse = function parse(ber) { - assert.ok(ber); - - ber.readSequence(); - this.type = ber.readString(); + ber.readSequence() + this.type = ber.readString() if (ber.peek() === Protocol.LBER_SET) { if (ber.readSequence(Protocol.LBER_SET)) { - var end = ber.offset + ber.length; - while (ber.offset < end) - this._vals.push(ber.readString(asn1.Ber.OctetString, true)); + var end = ber.offset + ber.length + while (ber.offset < end) { this._vals.push(ber.readString(asn1.Ber.OctetString, true)) } } } - return true; -}; + return true +} +Attribute.prototype.toBer = function toBer (ber) { + assert.ok(ber) -Attribute.prototype.toBer = function toBer(ber) { - assert.ok(ber); - - ber.startSequence(); - ber.writeString(this.type); - ber.startSequence(Protocol.LBER_SET); + ber.startSequence() + ber.writeString(this.type) + ber.startSequence(Protocol.LBER_SET) if (this._vals.length) { this._vals.forEach(function (b) { - ber.writeByte(asn1.Ber.OctetString); - ber.writeLength(b.length); - for (var i = 0; i < b.length; i++) - ber.writeByte(b[i]); - }); + ber.writeByte(asn1.Ber.OctetString) + ber.writeLength(b.length) + for (var i = 0; i < b.length; i++) { ber.writeByte(b[i]) } + }) } else { - ber.writeStringArray([]); + ber.writeStringArray([]) } - ber.endSequence(); - ber.endSequence(); - - return ber; -}; + ber.endSequence() + ber.endSequence() + return ber +} Attribute.prototype.toString = function () { - return JSON.stringify(this.json); -}; - + return JSON.stringify(this.json) +} Attribute.toBer = function (attr, ber) { - return Attribute.prototype.toBer.call(attr, ber); -}; + return Attribute.prototype.toBer.call(attr, ber) +} - -Attribute.isAttribute = function isAttribute(attr) { +Attribute.isAttribute = function isAttribute (attr) { if (!attr || typeof (attr) !== 'object') { - return false; + return false } if (attr instanceof Attribute) { - return true; + return true } if ((typeof (attr.toBer) === 'function') && (typeof (attr.type) === 'string') && (Array.isArray(attr.vals)) && (attr.vals.filter(function (item) { - return (typeof (item) === 'string' || - Buffer.isBuffer(item)); - }).length === attr.vals.length)) { - return true; + return (typeof (item) === 'string' || + Buffer.isBuffer(item)) + }).length === attr.vals.length)) { + return true } - return false; -}; - - -function _bufferEncoding(type) { - /* JSSTYLED */ - return /;binary$/.test(type) ? 'base64' : 'utf8'; + return false +} + +function _bufferEncoding (type) { + /* JSSTYLED */ + return /;binary$/.test(type) ? 'base64' : 'utf8' } diff --git a/lib/change.js b/lib/change.js index c5fac30..1805b4d 100644 --- a/lib/change.js +++ b/lib/change.js @@ -1,129 +1,125 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); +var assert = require('assert-plus') -var Attribute = require('./attribute'); -var Protocol = require('./protocol'); +var Attribute = require('./attribute') +// var Protocol = require('./protocol') +/// --- API -///--- API - -function Change(options) { +function Change (options) { if (options) { - assert.object(options); - assert.optionalString(options.operation); + assert.object(options) + assert.optionalString(options.operation) } else { - options = {}; + options = {} } - this._modification = false; - this.operation = options.operation || options.type || 'add'; - this.modification = options.modification || {}; + this._modification = false + this.operation = options.operation || options.type || 'add' + this.modification = options.modification || {} } Object.defineProperties(Change.prototype, { operation: { - get: function getOperation() { + get: function getOperation () { switch (this._operation) { - case 0x00: return 'add'; - case 0x01: return 'delete'; - case 0x02: return 'replace'; - default: - throw new Error('0x' + this._operation.toString(16) + ' is invalid'); + case 0x00: return 'add' + case 0x01: return 'delete' + case 0x02: return 'replace' + default: + throw new Error('0x' + this._operation.toString(16) + ' is invalid') } }, - set: function setOperation(val) { - assert.string(val); + set: function setOperation (val) { + assert.string(val) switch (val.toLowerCase()) { - case 'add': - this._operation = 0x00; - break; - case 'delete': - this._operation = 0x01; - break; - case 'replace': - this._operation = 0x02; - break; - default: - throw new Error('Invalid operation type: 0x' + val.toString(16)); + case 'add': + this._operation = 0x00 + break + case 'delete': + this._operation = 0x01 + break + case 'replace': + this._operation = 0x02 + break + default: + throw new Error('Invalid operation type: 0x' + val.toString(16)) } }, configurable: false }, modification: { - get: function getModification() { - return this._modification; + get: function getModification () { + return this._modification }, - set: function setModification(val) { + set: function setModification (val) { if (Attribute.isAttribute(val)) { - this._modification = val; - return; + this._modification = val + return } // Does it have an attribute-like structure - if (Object.keys(val).length == 2 && + if (Object.keys(val).length === 2 && typeof (val.type) === 'string' && Array.isArray(val.vals)) { this._modification = new Attribute({ type: val.type, vals: val.vals - }); - return; + }) + return } - var keys = Object.keys(val); + var keys = Object.keys(val) if (keys.length > 1) { - throw new Error('Only one attribute per Change allowed'); + throw new Error('Only one attribute per Change allowed') } else if (keys.length === 0) { - return; + return } - var k = keys[0]; - var _attr = new Attribute({type: k}); + var k = keys[0] + var _attr = new Attribute({ type: k }) if (Array.isArray(val[k])) { val[k].forEach(function (v) { - _attr.addValue(v.toString()); - }); + _attr.addValue(v.toString()) + }) } else if (val[k] !== undefined && val[k] !== null) { - _attr.addValue(val[k].toString()); + _attr.addValue(val[k].toString()) } - this._modification = _attr; + this._modification = _attr }, configurable: false }, json: { - get: function getJSON() { + get: function getJSON () { return { operation: this.operation, modification: this._modification ? this._modification.json : {} - }; + } }, configurable: false } -}); +}) -Change.isChange = function isChange(change) { +Change.isChange = function isChange (change) { if (!change || typeof (change) !== 'object') { - return false; + return false } if ((change instanceof Change) || ((typeof (change.toBer) === 'function') && (change.modification !== undefined) && (change.operation !== undefined))) { - return true; + return true } - return false; -}; + return false +} Change.compare = function (a, b) { - if (!Change.isChange(a) || !Change.isChange(b)) - throw new TypeError('can only compare Changes'); + if (!Change.isChange(a) || !Change.isChange(b)) { throw new TypeError('can only compare Changes') } - if (a.operation < b.operation) - return -1; - if (a.operation > b.operation) - return 1; + if (a.operation < b.operation) { return -1 } + if (a.operation > b.operation) { return 1 } - return Attribute.compare(a.modification, b.modification); -}; + return Attribute.compare(a.modification, b.modification) +} /** * Apply a Change to properties of an object. @@ -132,86 +128,83 @@ Change.compare = function (a, b) { * @param {Object} obj the object to apply it to. * @param {Boolean} scalar convert single-item arrays to scalars. Default: false */ -Change.apply = function apply(change, obj, scalar) { - assert.string(change.operation); - assert.string(change.modification.type); - assert.ok(Array.isArray(change.modification.vals)); - assert.object(obj); +Change.apply = function apply (change, obj, scalar) { + assert.string(change.operation) + assert.string(change.modification.type) + assert.ok(Array.isArray(change.modification.vals)) + assert.object(obj) - var type = change.modification.type; - var vals = change.modification.vals; - var data = obj[type]; + var type = change.modification.type + var vals = change.modification.vals + var data = obj[type] if (data !== undefined) { if (!Array.isArray(data)) { - data = [data]; + data = [data] } } else { - data = []; + data = [] } switch (change.operation) { - case 'replace': - if (vals.length === 0) { + case 'replace': + if (vals.length === 0) { // replace empty is a delete - delete obj[type]; - return obj; - } else { - data = vals; - } - break; - case 'add': + delete obj[type] + return obj + } else { + data = vals + } + break + case 'add': // add only new unique entries - var newValues = vals.filter(function (entry) { - return (data.indexOf(entry) === -1); - }); - data = data.concat(newValues); - break; - case 'delete': - data = data.filter(function (entry) { - return (vals.indexOf(entry) === -1); - }); - if (data.length === 0) { + var newValues = vals.filter(function (entry) { + return (data.indexOf(entry) === -1) + }) + data = data.concat(newValues) + break + case 'delete': + data = data.filter(function (entry) { + return (vals.indexOf(entry) === -1) + }) + if (data.length === 0) { // Erase the attribute if empty - delete obj[type]; - return obj; - } - break; - default: - break; + delete obj[type] + return obj + } + break + default: + break } if (scalar && data.length === 1) { // store single-value outputs as scalars, if requested - obj[type] = data[0]; + obj[type] = data[0] } else { - obj[type] = data; + obj[type] = data } - return obj; -}; - + return obj +} Change.prototype.parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.readSequence(); - this._operation = ber.readEnumeration(); - this._modification = new Attribute(); - this._modification.parse(ber); - - return true; -}; + ber.readSequence() + this._operation = ber.readEnumeration() + this._modification = new Attribute() + this._modification.parse(ber) + return true +} Change.prototype.toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.startSequence(); - ber.writeEnumeration(this._operation); - ber = this._modification.toBer(ber); - ber.endSequence(); + ber.startSequence() + ber.writeEnumeration(this._operation) + ber = this._modification.toBer(ber) + ber.endSequence() - return ber; -}; + return ber +} +/// --- Exports -///--- Exports - -module.exports = Change; +module.exports = Change diff --git a/lib/client/client.js b/lib/client/client.js index c1b8c8e..cf668e5 100644 --- a/lib/client/client.js +++ b/lib/client/client.js @@ -1,94 +1,88 @@ -// Copyright 2011 Mark Cavage, Inc. All rights reserved. +'use strict' -var EventEmitter = require('events').EventEmitter; -var net = require('net'); -var tls = require('tls'); -var util = require('util'); +var EventEmitter = require('events').EventEmitter +var net = require('net') +var tls = require('tls') +var util = require('util') -var once = require('once'); -var backoff = require('backoff'); -var vasync = require('vasync'); -var assert = require('assert-plus'); -var VError = require('verror').VError; +var once = require('once') +var backoff = require('backoff') +var vasync = require('vasync') +var assert = require('assert-plus') +var VError = require('verror').VError -var Attribute = require('../attribute'); -var Change = require('../change'); -var Control = require('../controls/index').Control; -var SearchPager = require('./search_pager'); -var Protocol = require('../protocol'); -var dn = require('../dn'); -var errors = require('../errors'); -var filters = require('../filters'); -var messages = require('../messages'); -var url = require('../url'); +var Attribute = require('../attribute') +var Change = require('../change') +var Control = require('../controls/index').Control +var SearchPager = require('./search_pager') +var Protocol = require('../protocol') +var dn = require('../dn') +var errors = require('../errors') +var filters = require('../filters') +var messages = require('../messages') +var url = require('../url') +/// --- Globals +var AbandonRequest = messages.AbandonRequest +var AddRequest = messages.AddRequest +var BindRequest = messages.BindRequest +var CompareRequest = messages.CompareRequest +var DeleteRequest = messages.DeleteRequest +var ExtendedRequest = messages.ExtendedRequest +var ModifyRequest = messages.ModifyRequest +var ModifyDNRequest = messages.ModifyDNRequest +var SearchRequest = messages.SearchRequest +var UnbindRequest = messages.UnbindRequest +var UnbindResponse = messages.UnbindResponse -///--- Globals +var LDAPResult = messages.LDAPResult +var SearchEntry = messages.SearchEntry +var SearchReference = messages.SearchReference +// var SearchResponse = messages.SearchResponse +var Parser = messages.Parser -var AbandonRequest = messages.AbandonRequest; -var AddRequest = messages.AddRequest; -var BindRequest = messages.BindRequest; -var CompareRequest = messages.CompareRequest; -var DeleteRequest = messages.DeleteRequest; -var ExtendedRequest = messages.ExtendedRequest; -var ModifyRequest = messages.ModifyRequest; -var ModifyDNRequest = messages.ModifyDNRequest; -var SearchRequest = messages.SearchRequest; -var UnbindRequest = messages.UnbindRequest; -var UnbindResponse = messages.UnbindResponse; +var PresenceFilter = filters.PresenceFilter -var LDAPResult = messages.LDAPResult; -var SearchEntry = messages.SearchEntry; -var SearchReference = messages.SearchReference; -var SearchResponse = messages.SearchResponse; -var Parser = messages.Parser; +var ConnectionError = errors.ConnectionError -var PresenceFilter = filters.PresenceFilter; - -var ConnectionError = errors.ConnectionError; - -var CMP_EXPECT = [errors.LDAP_COMPARE_TRUE, errors.LDAP_COMPARE_FALSE]; -var MAX_MSGID = Math.pow(2, 31) - 1; +var CMP_EXPECT = [errors.LDAP_COMPARE_TRUE, errors.LDAP_COMPARE_FALSE] +var MAX_MSGID = Math.pow(2, 31) - 1 // node 0.6 got rid of FDs, so make up a client id for logging -var CLIENT_ID = 0; +var CLIENT_ID = 0 +/// --- Internal Helpers +function nextClientId () { + if (++CLIENT_ID === MAX_MSGID) { return 1 } -///--- Internal Helpers - -function nextClientId() { - if (++CLIENT_ID === MAX_MSGID) - return 1; - - return CLIENT_ID; + return CLIENT_ID } -function validateControls(controls) { +function validateControls (controls) { if (Array.isArray(controls)) { controls.forEach(function (c) { - if (!(c instanceof Control)) - throw new TypeError('controls must be [Control]'); - }); + if (!(c instanceof Control)) { throw new TypeError('controls must be [Control]') } + }) } else if (controls instanceof Control) { - controls = [controls]; + controls = [controls] } else { - throw new TypeError('controls must be [Control]'); + throw new TypeError('controls must be [Control]') } - return controls; + return controls } -function ensureDN(input, strict) { +function ensureDN (input, strict) { if (dn.DN.isDN(input)) { - return dn; + return dn } else if (strict) { - return dn.parse(input); + return dn.parse(input) } else if (typeof (input) === 'string') { - return input; + return input } else { - throw new Error('invalid DN'); + throw new Error('invalid DN') } } @@ -101,167 +95,166 @@ function ensureDN(input, strict) { * - size: Maximum queue size * - timeout: Set timeout between first queue insertion and queue flush. */ -function RequestQueue(opts) { +function RequestQueue (opts) { if (!opts || typeof (opts) !== 'object') { - opts = {}; + opts = {} } - this.size = (opts.size > 0) ? opts.size : Infinity; - this.timeout = (opts.timeout > 0) ? opts.timeout : 0; - this._queue = []; - this._timer = null; - this._frozen = false; + this.size = (opts.size > 0) ? opts.size : Infinity + this.timeout = (opts.timeout > 0) ? opts.timeout : 0 + this._queue = [] + this._timer = null + this._frozen = false } /** * Insert request into queue. * */ -RequestQueue.prototype.enqueue = function enqueue(msg, expect, emitter, cb) { +RequestQueue.prototype.enqueue = function enqueue (msg, expect, emitter, cb) { if (this._queue.length >= this.size || this._frozen) { - return false; + return false } - var self = this; - this._queue.push([msg, expect, emitter, cb]); + var self = this + this._queue.push([msg, expect, emitter, cb]) if (this.timeout > 0) { if (this._timer !== null) { this._timer = setTimeout(function () { - // If queue times out, don't allow new entries until thawed - self.freeze(); - self.purge(); - }, this.timeout); + // If queue times out, don't allow new entries until thawed + self.freeze() + self.purge() + }, this.timeout) } } - return true; -}; + return true +} /** * Process all queued requests with callback. */ -RequestQueue.prototype.flush = function flush(cb) { +RequestQueue.prototype.flush = function flush (cb) { if (this._timer) { - clearTimeout(this._timer); - this._timer = null; + clearTimeout(this._timer) + this._timer = null } - var items = this._queue; - this._queue = []; + var items = this._queue + this._queue = [] items.forEach(function (req) { - cb(req[0], req[1], req[2], req[3]); - }); -}; + cb(req[0], req[1], req[2], req[3]) + }) +} /** * Purge all queued requests with an error. */ -RequestQueue.prototype.purge = function purge() { +RequestQueue.prototype.purge = function purge () { this.flush(function (msg, expect, emitter, cb) { - cb(new errors.TimeoutError('request queue timeout')); - }); -}; + cb(new errors.TimeoutError('request queue timeout')) + }) +} /** * Freeze queue, refusing any new entries. */ -RequestQueue.prototype.freeze = function freeze() { - this._frozen = true; -}; +RequestQueue.prototype.freeze = function freeze () { + this._frozen = true +} /** * Thaw queue, allowing new entries again. */ -RequestQueue.prototype.thaw = function thaw() { - this._frozen = false; -}; - +RequestQueue.prototype.thaw = function thaw () { + this._frozen = false +} /** * Track message callback by messageID. */ -function MessageTracker(opts) { - assert.object(opts); - assert.string(opts.id); - assert.object(opts.parser); +function MessageTracker (opts) { + assert.object(opts) + assert.string(opts.id) + assert.object(opts.parser) - this.id = opts.id; - this._msgid = 0; - this._messages = {}; - this._abandoned = {}; - this.parser = opts.parser; + this.id = opts.id + this._msgid = 0 + this._messages = {} + this._abandoned = {} + this.parser = opts.parser - var self = this; + var self = this this.__defineGetter__('pending', function () { - return Object.keys(self._messages); - }); + return Object.keys(self._messages) + }) } /** * Record a messageID and callback. */ -MessageTracker.prototype.track = function track(message, callback) { - var msgid = this._nextID(); - message.messageID = msgid; - this._messages[msgid] = callback; - return msgid; -}; +MessageTracker.prototype.track = function track (message, callback) { + var msgid = this._nextID() + message.messageID = msgid + this._messages[msgid] = callback + return msgid +} /** * Fetch callback based on messageID. */ -MessageTracker.prototype.fetch = function fetch(msgid) { - var msg = this._messages[msgid]; +MessageTracker.prototype.fetch = function fetch (msgid) { + var msg = this._messages[msgid] if (msg) { - this._purgeAbandoned(msgid); - return msg; + this._purgeAbandoned(msgid) + return msg } // It's possible that the server has not received the abandon request yet. // While waiting for evidence that the abandon has been received, incoming // messages that match the abandoned msgid will be handled as normal. - msg = this._abandoned[msgid]; + msg = this._abandoned[msgid] if (msg) { - return msg.cb; + return msg.cb } - return null; -}; + return null +} /** * Cease tracking for a given messageID. */ -MessageTracker.prototype.remove = function remove(msgid) { +MessageTracker.prototype.remove = function remove (msgid) { if (this._messages[msgid]) { - delete this._messages[msgid]; + delete this._messages[msgid] } else if (this._abandoned[msgid]) { - delete this._abandoned[msgid]; + delete this._abandoned[msgid] } -}; +} /** * Mark a messageID as abandoned. */ -MessageTracker.prototype.abandon = function abandonMsg(msgid) { +MessageTracker.prototype.abandon = function abandonMsg (msgid) { if (this._messages[msgid]) { // Keep track of "when" the message was abandoned this._abandoned[msgid] = { age: this._msgid, cb: this._messages[msgid] - }; - delete this._messages[msgid]; + } + delete this._messages[msgid] } -}; +} /** * Purge old items from abandoned list. */ -MessageTracker.prototype._purgeAbandoned = function _purgeAbandoned(msgid) { - var self = this; +MessageTracker.prototype._purgeAbandoned = function _purgeAbandoned (msgid) { + var self = this // Is (comp >= ref) according to sliding window - function geWindow(ref, comp) { - var max = ref + (MAX_MSGID/2); - var min = ref; + function geWindow (ref, comp) { + var max = ref + (MAX_MSGID / 2) + var min = ref if (max >= MAX_MSGID) { // Handle roll-over - max = max - MAX_MSGID - 1; - return ((comp <= max) || (comp >= min)); + max = max - MAX_MSGID - 1 + return ((comp <= max) || (comp >= min)) } else { - return ((comp <= max) && (comp >= min)); + return ((comp <= max) && (comp >= min)) } } @@ -269,23 +262,22 @@ MessageTracker.prototype._purgeAbandoned = function _purgeAbandoned(msgid) { // Abandoned messageIDs can be forgotten if a received messageID is "newer" if (geWindow(self._abandoned[id].age, msgid)) { self._abandoned[id].cb(new errors.AbandonedError( - 'client request abandoned')); - delete self._abandoned[id]; + 'client request abandoned')) + delete self._abandoned[id] } - }); -}; + }) +} /** * Allocate the next messageID according to a sliding window. */ -MessageTracker.prototype._nextID = function _nextID() { - if (++this._msgid >= MAX_MSGID) - this._msgid = 1; +MessageTracker.prototype._nextID = function _nextID () { + if (++this._msgid >= MAX_MSGID) { this._msgid = 1 } - return this._msgid; -}; + return this._msgid +} -///--- API +/// --- API /** * Constructs a new client. @@ -299,45 +291,44 @@ MessageTracker.prototype._nextID = function _nextID() { * @param {Object} options must have either url or socketPath. * @throws {TypeError} on bad input. */ -function Client(options) { - assert.ok(options); +function Client (options) { + assert.ok(options) - EventEmitter.call(this, options); + EventEmitter.call(this, options) - var self = this; - var _url; - if (options.url) - _url = url.parse(options.url); - this.host = _url ? _url.hostname : undefined; - this.port = _url ? _url.port : false; - this.secure = _url ? _url.secure : false; - this.url = _url; - this.tlsOptions = options.tlsOptions; - this.socketPath = options.socketPath || false; + var self = this + var _url + if (options.url) { _url = url.parse(options.url) } + this.host = _url ? _url.hostname : undefined + this.port = _url ? _url.port : false + this.secure = _url ? _url.secure : false + this.url = _url + this.tlsOptions = options.tlsOptions + this.socketPath = options.socketPath || false - this.log = options.log.child({clazz: 'Client'}, true); + this.log = options.log.child({ clazz: 'Client' }, true) - this.timeout = parseInt((options.timeout || 0), 10); - this.connectTimeout = parseInt((options.connectTimeout || 0), 10); - this.idleTimeout = parseInt((options.idleTimeout || 0), 10); + this.timeout = parseInt((options.timeout || 0), 10) + this.connectTimeout = parseInt((options.connectTimeout || 0), 10) + this.idleTimeout = parseInt((options.idleTimeout || 0), 10) if (options.reconnect) { // Fall back to defaults if options.reconnect === true - var rOpts = (typeof (options.reconnect) === 'object') ? - options.reconnect : {}; + var rOpts = (typeof (options.reconnect) === 'object') + ? options.reconnect : {} this.reconnect = { initialDelay: parseInt(rOpts.initialDelay || 100, 10), maxDelay: parseInt(rOpts.maxDelay || 10000, 10), failAfter: parseInt(rOpts.failAfter, 10) || Infinity - }; + } } - this.strictDN = (options.strictDN !== undefined) ? options.strictDN : true; + this.strictDN = (options.strictDN !== undefined) ? options.strictDN : true this.queue = new RequestQueue({ size: parseInt((options.queueSize || 0), 10), timeout: parseInt((options.queueTimeout || 0), 10) - }); + }) if (options.queueDisable) { - this.queue.freeze(); + this.queue.freeze() } // Implicitly configure setup action to bind the client if bindDN and @@ -351,20 +342,19 @@ function Client(options) { if (self._socket) { self._socket.destroy() } - self.emit('error', err); + self.emit('error', err) } - cb(err); - }); - }); + cb(err) + }) + }) } - this._socket = null; - this.connected = false; - this.connect(); + this._socket = null + this.connected = false + this.connect() } -util.inherits(Client, EventEmitter); -module.exports = Client; - +util.inherits(Client, EventEmitter) +module.exports = Client /** * Sends an abandon request to the LDAP server. @@ -377,24 +367,23 @@ module.exports = Client; * @param {Function} callback of the form f(err). * @throws {TypeError} on invalid input. */ -Client.prototype.abandon = function abandon(messageID, controls, callback) { - assert.number(messageID, 'messageID'); +Client.prototype.abandon = function abandon (messageID, controls, callback) { + assert.number(messageID, 'messageID') if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback, 'callback'); + assert.func(callback, 'callback') var req = new AbandonRequest({ abandonID: messageID, controls: controls - }); - - return this._send(req, 'abandon', null, callback); -}; + }) + return this._send(req, 'abandon', null, callback) +} /** * Adds an entry to the LDAP server. @@ -409,48 +398,46 @@ Client.prototype.abandon = function abandon(messageID, controls, callback) { * @param {Function} callback of the form f(err, res). * @throws {TypeError} on invalid input. */ -Client.prototype.add = function add(name, entry, controls, callback) { - assert.ok(name !== undefined, 'name'); - assert.object(entry, 'entry'); +Client.prototype.add = function add (name, entry, controls, callback) { + assert.ok(name !== undefined, 'name') + assert.object(entry, 'entry') if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback, 'callback'); + assert.func(callback, 'callback') if (Array.isArray(entry)) { entry.forEach(function (a) { - if (!Attribute.isAttribute(a)) - throw new TypeError('entry must be an Array of Attributes'); - }); + if (!Attribute.isAttribute(a)) { throw new TypeError('entry must be an Array of Attributes') } + }) } else { - var save = entry; + var save = entry - entry = []; + entry = [] Object.keys(save).forEach(function (k) { - var attr = new Attribute({type: k}); + var attr = new Attribute({ type: k }) if (Array.isArray(save[k])) { save[k].forEach(function (v) { - attr.addValue(v.toString()); - }); + attr.addValue(v.toString()) + }) } else { - attr.addValue(save[k].toString()); + attr.addValue(save[k].toString()) } - entry.push(attr); - }); + entry.push(attr) + }) } var req = new AddRequest({ entry: ensureDN(name, this.strictDN), attributes: entry, controls: controls - }); - - return this._send(req, [errors.LDAP_SUCCESS], null, callback); -}; + }) + return this._send(req, [errors.LDAP_SUCCESS], null, callback) +} /** * Performs a simple authentication against the server. @@ -461,32 +448,30 @@ Client.prototype.add = function add(name, entry, controls, callback) { * @param {Function} callback of the form f(err, res). * @throws {TypeError} on invalid input. */ -Client.prototype.bind = function bind(name, - credentials, - controls, - callback, - _bypass) { - if (typeof (name) !== 'string' && !(name instanceof dn.DN)) - throw new TypeError('name (string) required'); - assert.optionalString(credentials, 'credentials'); +Client.prototype.bind = function bind (name, + credentials, + controls, + callback, + _bypass) { + if (typeof (name) !== 'string' && !(name instanceof dn.DN)) { throw new TypeError('name (string) required') } + assert.optionalString(credentials, 'credentials') if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback, 'callback'); + assert.func(callback, 'callback') var req = new BindRequest({ name: name || '', authentication: 'Simple', credentials: credentials || '', controls: controls - }); - - return this._send(req, [errors.LDAP_SUCCESS], null, callback, _bypass); -}; + }) + return this._send(req, [errors.LDAP_SUCCESS], null, callback, _bypass) +} /** * Compares an attribute/value pair with an entry on the LDAP server. @@ -498,37 +483,35 @@ Client.prototype.bind = function bind(name, * @param {Function} callback of the form f(err, boolean, res). * @throws {TypeError} on invalid input. */ -Client.prototype.compare = function compare(name, - attr, - value, - controls, - callback) { - assert.ok(name !== undefined, 'name'); - assert.string(attr, 'attr'); - assert.string(value, 'value'); +Client.prototype.compare = function compare (name, + attr, + value, + controls, + callback) { + assert.ok(name !== undefined, 'name') + assert.string(attr, 'attr') + assert.string(value, 'value') if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback, 'callback'); + assert.func(callback, 'callback') var req = new CompareRequest({ entry: ensureDN(name, this.strictDN), attribute: attr, value: value, controls: controls - }); + }) return this._send(req, CMP_EXPECT, null, function (err, res) { - if (err) - return callback(err); - - return callback(null, (res.status === errors.LDAP_COMPARE_TRUE), res); - }); -}; + if (err) { return callback(err) } + return callback(null, (res.status === errors.LDAP_COMPARE_TRUE), res) + }) +} /** * Deletes an entry from the LDAP server. @@ -538,24 +521,23 @@ Client.prototype.compare = function compare(name, * @param {Function} callback of the form f(err, res). * @throws {TypeError} on invalid input. */ -Client.prototype.del = function del(name, controls, callback) { - assert.ok(name !== undefined, 'name'); +Client.prototype.del = function del (name, controls, callback) { + assert.ok(name !== undefined, 'name') if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback, 'callback'); + assert.func(callback, 'callback') var req = new DeleteRequest({ entry: ensureDN(name, this.strictDN), controls: controls - }); - - return this._send(req, [errors.LDAP_SUCCESS], null, callback); -}; + }) + return this._send(req, [errors.LDAP_SUCCESS], null, callback) +} /** * Performs an extended operation on the LDAP server. @@ -570,37 +552,34 @@ Client.prototype.del = function del(name, controls, callback) { * @param {Function} callback of the form f(err, value, res). * @throws {TypeError} on invalid input. */ -Client.prototype.exop = function exop(name, value, controls, callback) { - assert.string(name, 'name'); +Client.prototype.exop = function exop (name, value, controls, callback) { + assert.string(name, 'name') if (typeof (value) === 'function') { - callback = value; - controls = []; - value = ''; + callback = value + controls = [] + value = '' } - if (!(Buffer.isBuffer(value) || typeof (value) === 'string')) - throw new TypeError('value (Buffer || string) required'); + if (!(Buffer.isBuffer(value) || typeof (value) === 'string')) { throw new TypeError('value (Buffer || string) required') } if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback, 'callback'); + assert.func(callback, 'callback') var req = new ExtendedRequest({ requestName: name, requestValue: value, controls: controls - }); + }) return this._send(req, [errors.LDAP_SUCCESS], null, function (err, res) { - if (err) - return callback(err); - - return callback(null, res.responseValue || '', res); - }); -}; + if (err) { return callback(err) } + return callback(null, res.responseValue || '', res) + }) +} /** * Performs an LDAP modify against the server. @@ -611,70 +590,67 @@ Client.prototype.exop = function exop(name, value, controls, callback) { * @param {Function} callback of the form f(err, res). * @throws {TypeError} on invalid input. */ -Client.prototype.modify = function modify(name, change, controls, callback) { - assert.ok(name !== undefined, 'name'); - assert.object(change, 'change'); +Client.prototype.modify = function modify (name, change, controls, callback) { + assert.ok(name !== undefined, 'name') + assert.object(change, 'change') - var changes = []; + var changes = [] - function changeFromObject(change) { - if (!change.operation && !change.type) - throw new Error('change.operation required'); - if (typeof (change.modification) !== 'object') - throw new Error('change.modification (object) required'); + function changeFromObject (change) { + if (!change.operation && !change.type) { throw new Error('change.operation required') } + if (typeof (change.modification) !== 'object') { throw new Error('change.modification (object) required') } - if (Object.keys(change.modification).length == 2 && + if (Object.keys(change.modification).length === 2 && typeof (change.modification.type) === 'string' && Array.isArray(change.modification.vals)) { // Use modification directly if it's already normalized: changes.push(new Change({ operation: change.operation || change.type, modification: change.modification - })); + })) } else { // Normalize the modification object Object.keys(change.modification).forEach(function (k) { - var mod = {}; - mod[k] = change.modification[k]; + var mod = {} + mod[k] = change.modification[k] changes.push(new Change({ operation: change.operation || change.type, modification: mod - })); - }); + })) + }) } } if (Change.isChange(change)) { - changes.push(change); + changes.push(change) } else if (Array.isArray(change)) { change.forEach(function (c) { if (Change.isChange(c)) { - changes.push(c); + changes.push(c) } else { - changeFromObject(c); + changeFromObject(c) } - }); + }) } else { - changeFromObject(change); + changeFromObject(change) } if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback, 'callback'); + assert.func(callback, 'callback') var req = new ModifyRequest({ object: ensureDN(name, this.strictDN), changes: changes, controls: controls - }); - - return this._send(req, [errors.LDAP_SUCCESS], null, callback); -}; + }) + return this._send(req, [errors.LDAP_SUCCESS], null, callback) +} /** * Performs an LDAP modifyDN against the server. @@ -690,40 +666,39 @@ Client.prototype.modify = function modify(name, change, controls, callback) { * @param {Function} callback of the form f(err, res). * @throws {TypeError} on invalid input. */ -Client.prototype.modifyDN = function modifyDN(name, - newName, - controls, - callback) { - assert.ok(name !== undefined, 'name'); - assert.string(newName, 'newName'); +Client.prototype.modifyDN = function modifyDN (name, + newName, + controls, + callback) { + assert.ok(name !== undefined, 'name') + assert.string(newName, 'newName') if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback); + assert.func(callback) - var DN = ensureDN(name); + var DN = ensureDN(name) // TODO: is non-strict handling desired here? - var newDN = dn.parse(newName); + var newDN = dn.parse(newName) var req = new ModifyDNRequest({ entry: DN, deleteOldRdn: true, controls: controls - }); + }) if (newDN.length !== 1) { - req.newRdn = dn.parse(newDN.rdns.shift().toString()); - req.newSuperior = newDN; + req.newRdn = dn.parse(newDN.rdns.shift().toString()) + req.newSuperior = newDN } else { - req.newRdn = newDN; + req.newRdn = newDN } - return this._send(req, [errors.LDAP_SUCCESS], null, callback); -}; - + return this._send(req, [errors.LDAP_SUCCESS], null, callback) +} /** * Performs an LDAP search against the server. @@ -748,55 +723,55 @@ Client.prototype.modifyDN = function modifyDN(name, * @param {Function} callback of the form f(err, res). * @throws {TypeError} on invalid input. */ -Client.prototype.search = function search(base, - options, - controls, - callback, - _bypass) { - assert.ok(base !== undefined, 'search base'); +Client.prototype.search = function search (base, + options, + controls, + callback, + _bypass) { + assert.ok(base !== undefined, 'search base') if (Array.isArray(options) || (options instanceof Control)) { - controls = options; - options = {}; + controls = options + options = {} } else if (typeof (options) === 'function') { - callback = options; - controls = []; + callback = options + controls = [] options = { - filter: new PresenceFilter({attribute: 'objectclass'}) - }; + filter: new PresenceFilter({ attribute: 'objectclass' }) + } } else if (typeof (options) === 'string') { - options = {filter: filters.parseString(options)}; + options = { filter: filters.parseString(options) } } else if (typeof (options) !== 'object') { - throw new TypeError('options (object) required'); + throw new TypeError('options (object) required') } if (typeof (options.filter) === 'string') { - options.filter = filters.parseString(options.filter); + options.filter = filters.parseString(options.filter) } else if (!options.filter) { - options.filter = new PresenceFilter({attribute: 'objectclass'}); + options.filter = new PresenceFilter({ attribute: 'objectclass' }) } else if (!filters.isFilter(options.filter)) { - throw new TypeError('options.filter (Filter) required'); + throw new TypeError('options.filter (Filter) required') } if (typeof (controls) === 'function') { - callback = controls; - controls = []; + callback = controls + controls = [] } else { - controls = validateControls(controls); + controls = validateControls(controls) } - assert.func(callback, 'callback'); + assert.func(callback, 'callback') if (options.attributes) { if (!Array.isArray(options.attributes)) { if (typeof (options.attributes) === 'string') { - options.attributes = [options.attributes]; + options.attributes = [options.attributes] } else { - throw new TypeError('options.attributes must be an Array of Strings'); + throw new TypeError('options.attributes must be an Array of Strings') } } } - var self = this; - var baseDN = ensureDN(base, this.strictDN); + var self = this + var baseDN = ensureDN(base, this.strictDN) - function sendRequest(ctrls, emitter, cb) { + function sendRequest (ctrls, emitter, cb) { var req = new SearchRequest({ baseObject: baseDN, scope: options.scope || 'base', @@ -807,26 +782,26 @@ Client.prototype.search = function search(base, typesOnly: options.typesOnly || false, attributes: options.attributes || [], controls: ctrls - }); + }) return self._send(req, - [errors.LDAP_SUCCESS], - emitter, - cb, - _bypass); + [errors.LDAP_SUCCESS], + emitter, + cb, + _bypass) } if (options.paged) { // Perform automated search paging - var pageOpts = typeof (options.paged) === 'object' ? options.paged : {}; - var size = 100; // Default page size + var pageOpts = typeof (options.paged) === 'object' ? options.paged : {} + var size = 100 // Default page size if (pageOpts.pageSize > 0) { - size = pageOpts.pageSize; - } else if (options.sizeLimit > 1) { + size = pageOpts.pageSize + } else if (options.sizeLimit > 1) { // According to the RFC, servers should ignore the paging control if // pageSize >= sizelimit. Some might still send results, but it's safer // to stay under that figure when assigning a default value. - size = options.sizeLimit - 1; + size = options.sizeLimit - 1 } var pager = new SearchPager({ @@ -834,14 +809,13 @@ Client.prototype.search = function search(base, controls: controls, pageSize: size, pagePause: pageOpts.pagePause - }); - pager.on('search', sendRequest); - pager.begin(); + }) + pager.on('search', sendRequest) + pager.begin() } else { - sendRequest(controls, new EventEmitter(), callback); + sendRequest(controls, new EventEmitter(), callback) } -}; - +} /** * Unbinds this client from the LDAP server. @@ -852,45 +826,41 @@ Client.prototype.search = function search(base, * @param {Function} callback of the form f(err). * @throws {TypeError} if you pass in callback as not a function. */ -Client.prototype.unbind = function unbind(callback) { - if (!callback) - callback = function () {}; +Client.prototype.unbind = function unbind (callback) { + if (!callback) { callback = function () {} } - if (typeof (callback) !== 'function') - throw new TypeError('callback must be a function'); + if (typeof (callback) !== 'function') { throw new TypeError('callback must be a function') } // When the socket closes, it is useful to know whether it was due to a // user-initiated unbind or something else. - this.unbound = true; + this.unbound = true - if (!this._socket) - return callback(); - - var req = new UnbindRequest(); - return this._send(req, 'unbind', null, callback); -}; + if (!this._socket) { return callback() } + var req = new UnbindRequest() + return this._send(req, 'unbind', null, callback) +} /** * Attempt to secure connection with StartTLS. */ -Client.prototype.starttls = function starttls(options, - controls, - callback, - _bypass) { - assert.optionalObject(options); - options = options || {}; - callback = once(callback); - var self = this; +Client.prototype.starttls = function starttls (options, + controls, + callback, + _bypass) { + assert.optionalObject(options) + options = options || {} + callback = once(callback) + var self = this if (this._starttls) { - return callback(new Error('STARTTLS already in progress or active')); + return callback(new Error('STARTTLS already in progress or active')) } - function onSend(err, emitter) { + function onSend (err, emitter) { if (err) { - callback(err); - return; + callback(err) + return } /* * Now that the request has been sent, block all outgoing messages @@ -899,69 +869,66 @@ Client.prototype.starttls = function starttls(options, // TODO: block traffic self._starttls = { started: true - }; + } emitter.on('error', function (err) { - self._starttls = null; - callback(err); - }); + self._starttls = null + callback(err) + }) emitter.on('end', function (res) { - var sock = self._socket; + var sock = self._socket /* * Unplumb socket data during SSL negotiation. * This will prevent the LDAP parser from stumbling over the TLS * handshake and raising a ruckus. */ - sock.removeAllListeners('data'); + sock.removeAllListeners('data') - options.socket = sock; - var secure = tls.connect(options); + options.socket = sock + var secure = tls.connect(options) secure.once('secureConnect', function () { /* * Wire up 'data' and 'error' handlers like the normal socket. * Handling 'end' events isn't necessary since the underlying socket * will handle those. */ - secure.removeAllListeners('error'); - secure.on('data', function onData(data) { - if (self.log.trace()) - self.log.trace('data event: %s', util.inspect(data)); + secure.removeAllListeners('error') + secure.on('data', function onData (data) { + if (self.log.trace()) { self.log.trace('data event: %s', util.inspect(data)) } - self._tracker.parser.write(data); - }); - secure.on('error', function (err) { - if (self.log.trace()) - self.log.trace({err: err}, 'error event: %s', new Error().stack); + self._tracker.parser.write(data) + }) + secure.on('error', function (err) { + if (self.log.trace()) { self.log.trace({ err: err }, 'error event: %s', new Error().stack) } - self.emit('error', err); - sock.destroy(); - }); - callback(null); - }); + self.emit('error', err) + sock.destroy() + }) + callback(null) + }) secure.once('error', function (err) { // If the SSL negotiation failed, to back to plain mode. - self._starttls = null; - secure.removeAllListeners(); - callback(err); - }); - self._starttls.success = true; - self._socket = secure; - }); + self._starttls = null + secure.removeAllListeners() + callback(err) + }) + self._starttls.success = true + self._socket = secure + }) } var req = new ExtendedRequest({ requestName: '1.3.6.1.4.1.1466.20037', requestValue: null, controls: controls - }); + }) return this._send(req, - [errors.LDAP_SUCCESS], - new EventEmitter(), - onSend, - _bypass); -}; - + [errors.LDAP_SUCCESS], + new EventEmitter(), + onSend, + _bypass) +} /** * Disconnect from the LDAP server and do not allow reconnection. @@ -974,155 +941,153 @@ Client.prototype.starttls = function starttls(options, * * @param {Object} err (Optional) error that was cause of client destruction */ -Client.prototype.destroy = function destroy(err) { - this.destroyed = true; - this.queue.freeze(); +Client.prototype.destroy = function destroy (err) { + this.destroyed = true + this.queue.freeze() // Purge any queued requests which are now meaningless this.queue.flush(function (msg, expect, emitter, cb) { if (typeof (cb) === 'function') { - cb(new Error('client destroyed')); - } - }); + cb(new Error('client destroyed')) + } + }) if (this.connected) { - this.unbind(); + this.unbind() } else if (this._socket) { - this._socket.destroy(); + this._socket.destroy() } - this.emit('destroy', err); -}; - + this.emit('destroy', err) +} /** * Initiate LDAP connection. */ -Client.prototype.connect = function connect() { +Client.prototype.connect = function connect () { if (this.connecting || this.connected) { - return; + return } - var self = this; - var log = this.log; - var socket; - var tracker; + var self = this + var log = this.log + var socket + var tracker // Establish basic socket connection - function connectSocket(cb) { - cb = once(cb); + function connectSocket (cb) { + cb = once(cb) - function onResult(err, res) { + function onResult (err, res) { if (err) { if (self.connectTimer) { - clearTimeout(self.connectTimer); - self.connectTimer = null; + clearTimeout(self.connectTimer) + self.connectTimer = null } - self.emit('connectError', err); + self.emit('connectError', err) } - cb(err, res); + cb(err, res) } - function onConnect() { + function onConnect () { if (self.connectTimer) { - clearTimeout(self.connectTimer); - self.connectTimer = null; + clearTimeout(self.connectTimer) + self.connectTimer = null } socket.removeAllListeners('error') .removeAllListeners('connect') - .removeAllListeners('secureConnect'); + .removeAllListeners('secureConnect') - tracker.id = nextClientId() + '__' + tracker.id; - self.log = self.log.child({ldap_id: tracker.id}, true); + tracker.id = nextClientId() + '__' + tracker.id + self.log = self.log.child({ ldap_id: tracker.id }, true) // Move on to client setup - setupClient(cb); + setupClient(cb) } - var port = (self.port || self.socketPath); + var port = (self.port || self.socketPath) if (self.secure) { - socket = tls.connect(port, self.host, self.tlsOptions); - socket.once('secureConnect', onConnect); + socket = tls.connect(port, self.host, self.tlsOptions) + socket.once('secureConnect', onConnect) } else { - socket = net.connect(port, self.host); - socket.once('connect', onConnect); + socket = net.connect(port, self.host) + socket.once('connect', onConnect) } - socket.once('error', onResult); - initSocket(); + socket.once('error', onResult) + initSocket() // Setup connection timeout handling, if desired if (self.connectTimeout) { - self.connectTimer = setTimeout(function onConnectTimeout() { + self.connectTimer = setTimeout(function onConnectTimeout () { if (!socket || !socket.readable || !socket.writeable) { - socket.destroy(); - self._socket = null; - onResult(new ConnectionError('connection timeout')); + socket.destroy() + self._socket = null + onResult(new ConnectionError('connection timeout')) } - }, self.connectTimeout); + }, self.connectTimeout) } } // Initialize socket events and LDAP parser. - function initSocket() { + function initSocket () { tracker = new MessageTracker({ id: self.url ? self.url.href : self.socketPath, - parser: new Parser({log: log}) - }); + parser: new Parser({ log: log }) + }) // This won't be set on TLS. So. Very. Annoying. if (typeof (socket.setKeepAlive) !== 'function') { - socket.setKeepAlive = function setKeepAlive(enable, delay) { - return socket.socket ? - socket.socket.setKeepAlive(enable, delay) : false; - }; + socket.setKeepAlive = function setKeepAlive (enable, delay) { + return socket.socket + ? socket.socket.setKeepAlive(enable, delay) : false + } } - socket.on('data', function onData(data) { - if (log.trace()) - log.trace('data event: %s', util.inspect(data)); + socket.on('data', function onData (data) { + if (log.trace) { log.trace('data event: %s', util.inspect(data)) } - tracker.parser.write(data); - }); + tracker.parser.write(data) + }) // The "router" - tracker.parser.on('message', function onMessage(message) { - message.connection = self._socket; - var callback = tracker.fetch(message.messageID); + tracker.parser.on('message', function onMessage (message) { + message.connection = self._socket + var callback = tracker.fetch(message.messageID) if (!callback) { - log.error({message: message.json}, 'unsolicited message'); - return false; + log.error({ message: message.json }, 'unsolicited message') + return false } - return callback(message); - }); + return callback(message) + }) - tracker.parser.on('error', function onParseError(err) { + tracker.parser.on('error', function onParseError (err) { self.emit('error', new VError(err, 'Parser error for %s', - tracker.id)); - self.connected = false; - socket.end(); - }); + tracker.id)) + self.connected = false + socket.end() + }) } // After connect, register socket event handlers and run any setup actions - function setupClient(cb) { - cb = once(cb); + function setupClient (cb) { + cb = once(cb) // Indicate failure if anything goes awry during setup - function bail(err) { - socket.destroy(); - cb(err || new Error('client error during setup')); + function bail (err) { + socket.destroy() + cb(err || new Error('client error during setup')) } // Work around lack of close event on tls.socket in node < 0.11 - ((socket.socket) ? socket.socket : socket).once('close', bail); - socket.once('error', bail); - socket.once('end', bail); - socket.once('timeout', bail); - socket.once('cleanupSetupListeners', function onCleanup() { + ((socket.socket) ? socket.socket : socket).once('close', bail) + socket.once('error', bail) + socket.once('end', bail) + socket.once('timeout', bail) + socket.once('cleanupSetupListeners', function onCleanup () { socket.removeListener('error', bail) .removeListener('close', bail) .removeListener('end', bail) - .removeListener('timeout', bail); - }); + .removeListener('timeout', bail) + }) - self._socket = socket; - self._tracker = tracker; + self._socket = socket + self._tracker = tracker // Run any requested setup (such as automatically performing a bind) on // socket before signalling successful connection. @@ -1130,178 +1095,172 @@ Client.prototype.connect = function connect() { // blocked until the connection is considered fully established post-setup. // Only allow bind/search/starttls for now. var basicClient = { - bind: function bindBypass(name, credentials, controls, callback) { - return self.bind(name, credentials, controls, callback, true); + bind: function bindBypass (name, credentials, controls, callback) { + return self.bind(name, credentials, controls, callback, true) }, - search: function searchBypass(base, options, controls, callback) { - return self.search(base, options, controls, callback, true); + search: function searchBypass (base, options, controls, callback) { + return self.search(base, options, controls, callback, true) }, - starttls: function starttlsBypass(options, controls, callback) { - return self.starttls(options, controls, callback, true); + starttls: function starttlsBypass (options, controls, callback) { + return self.starttls(options, controls, callback, true) }, unbind: self.unbind.bind(self) - }; + } vasync.forEachPipeline({ func: function (f, callback) { - f(basicClient, callback); + f(basicClient, callback) }, inputs: self.listeners('setup') }, function (err, res) { if (err) { - self.emit('setupError', err); + self.emit('setupError', err) } - cb(err); - }); + cb(err) + }) } // Wire up "official" event handlers after successful connect/setup - function postSetup() { + function postSetup () { // cleanup the listeners we attached in setup phrase. socket.emit('cleanupSetupListeners'); // Work around lack of close event on tls.socket in node < 0.11 ((socket.socket) ? socket.socket : socket).once('close', - self._onClose.bind(self)); - socket.on('end', function onEnd() { - if (log.trace()) - log.trace('end event'); + self._onClose.bind(self)) + socket.on('end', function onEnd () { + if (log.trace()) { log.trace('end event') } - self.emit('end'); - socket.end(); - }); - socket.on('error', function onSocketError(err) { - if (log.trace()) - log.trace({err: err}, 'error event: %s', new Error().stack); + self.emit('end') + socket.end() + }) + socket.on('error', function onSocketError (err) { + if (log.trace()) { log.trace({ err: err }, 'error event: %s', new Error().stack) } - self.emit('error', err); - socket.destroy(); - }); - socket.on('timeout', function onTimeout() { - if (log.trace()) - log.trace('timeout event'); + self.emit('error', err) + socket.destroy() + }) + socket.on('timeout', function onTimeout () { + if (log.trace()) { log.trace('timeout event') } - self.emit('socketTimeout'); - socket.end(); - }); + self.emit('socketTimeout') + socket.end() + }) } - var retry; - var failAfter; + var retry + var failAfter if (this.reconnect) { retry = backoff.exponential({ initialDelay: this.reconnect.initialDelay, maxDelay: this.reconnect.maxDelay - }); - failAfter = this.reconnect.failAfter; + }) + failAfter = this.reconnect.failAfter } else { retry = backoff.exponential({ initialDelay: 1, maxDelay: 2 - }); - failAfter = 1; + }) + failAfter = 1 } - retry.failAfter(failAfter); + retry.failAfter(failAfter) retry.on('ready', function (num, delay) { if (self.destroyed) { // Cease connection attempts if destroyed - return; + return } connectSocket(function (err) { if (!err) { - postSetup(); - self.connecting = false; - self.connected = true; - self.emit('connect', socket); - self.log.debug('connected after %d attempt(s)', num+1); + postSetup() + self.connecting = false + self.connected = true + self.emit('connect', socket) + self.log.debug('connected after %d attempt(s)', num + 1) // Flush any queued requests - self._flushQueue(); - self._connectRetry = null; + self._flushQueue() + self._connectRetry = null } else { - retry.backoff(err); + retry.backoff(err) } - }); - }); + }) + }) retry.on('fail', function (err) { if (self.destroyed) { // Silence any connect/setup errors if destroyed - return; + return } - self.log.debug('failed to connect after %d attempts', failAfter); + self.log.debug('failed to connect after %d attempts', failAfter) // Communicate the last-encountered error if (err instanceof ConnectionError) { - self.emit('connectTimeout', err); + self.emit('connectTimeout', err) } else { - self.emit('error', err); + self.emit('error', err) } - }); + }) - this._connectRetry = retry; - this.connecting = true; - retry.backoff(); -}; + this._connectRetry = retry + this.connecting = true + retry.backoff() +} - - -///--- Private API +/// --- Private API /** * Flush queued requests out to the socket. */ -Client.prototype._flushQueue = function _flushQueue() { +Client.prototype._flushQueue = function _flushQueue () { // Pull items we're about to process out of the queue. - this.queue.flush(this._send.bind(this)); -}; + this.queue.flush(this._send.bind(this)) +} /** * Clean up socket/parser resources after socket close. */ -Client.prototype._onClose = function _onClose(had_err) { - var socket = this._socket; - var tracker = this._tracker; +Client.prototype._onClose = function _onClose (closeError) { + var socket = this._socket + var tracker = this._tracker socket.removeAllListeners('connect') .removeAllListeners('data') .removeAllListeners('drain') .removeAllListeners('end') .removeAllListeners('error') - .removeAllListeners('timeout'); - this._socket = null; + .removeAllListeners('timeout') + this._socket = null this.connected = false; - ((socket.socket) ? socket.socket : socket).removeAllListeners('close'); + ((socket.socket) ? socket.socket : socket).removeAllListeners('close') - if (this.log.trace()) - this.log.trace('close event had_err=%s', had_err ? 'yes' : 'no'); + if (this.log.trace()) { this.log.trace('close event had_err=%s', closeError ? 'yes' : 'no') } - this.emit('close', had_err); + this.emit('close', closeError) // On close we have to walk the outstanding messages and go invoke their // callback with an error. tracker.pending.forEach(function (msgid) { - var cb = tracker.fetch(msgid); - tracker.remove(msgid); + var cb = tracker.fetch(msgid) + tracker.remove(msgid) if (socket.unbindMessageID !== parseInt(msgid, 10)) { - return cb(new ConnectionError(tracker.id + ' closed')); + return cb(new ConnectionError(tracker.id + ' closed')) } else { // Unbinds will be communicated as a success since we're closed - var unbind = new UnbindResponse({messageID: msgid}); - unbind.status = 'unbind'; - return cb(unbind); + var unbind = new UnbindResponse({ messageID: msgid }) + unbind.status = 'unbind' + return cb(unbind) } - }); + }) // Trash any parser or starttls state - this._tracker = null; - delete this._starttls; + this._tracker = null + delete this._starttls // Automatically fire reconnect logic if the socket was closed for any reason // other than a user-initiated unbind. if (this.reconnect && !this.unbound) { - this.connect(); + this.connect() } - this.unbound = false; - return false; -}; + this.unbound = false + return false +} /** * Maintain idle timer for client. @@ -1311,181 +1270,174 @@ Client.prototype._onClose = function _onClose(had_err) { * * @param {Boolean} override explicitly disable timer. */ -Client.prototype._updateIdle = function _updateIdle(override) { +Client.prototype._updateIdle = function _updateIdle (override) { if (this.idleTimeout === 0) { - return; + return } // Client must be connected but not waiting on any request data - var self = this; - function isIdle(disable) { + var self = this + function isIdle (disable) { return ((disable !== true) && (self._socket && self.connected) && - (self._tracker.pending.length === 0)); + (self._tracker.pending.length === 0)) } if (isIdle(override)) { if (!this._idleTimer) { this._idleTimer = setTimeout(function () { // Double-check idleness in case socket was torn down if (isIdle()) { - self.emit('idle'); + self.emit('idle') } - }, this.idleTimeout); + }, this.idleTimeout) } } else { if (this._idleTimer) { - clearTimeout(this._idleTimer); - this._idleTimer = null; + clearTimeout(this._idleTimer) + this._idleTimer = null } } -}; +} /** * Attempt to send an LDAP request. */ -Client.prototype._send = function _send(message, - expect, - emitter, - callback, - _bypass) { - assert.ok(message); - assert.ok(expect); - assert.optionalObject(emitter); - assert.ok(callback); +Client.prototype._send = function _send (message, + expect, + emitter, + callback, + _bypass) { + assert.ok(message) + assert.ok(expect) + assert.optionalObject(emitter) + assert.ok(callback) // Allow connect setup traffic to bypass checks if (_bypass && this._socket && this._socket.writable) { - return this._sendSocket(message, expect, emitter, callback); + return this._sendSocket(message, expect, emitter, callback) } if (!this._socket || !this.connected) { if (!this.queue.enqueue(message, expect, emitter, callback)) { - callback(new ConnectionError('connection unavailable')); + callback(new ConnectionError('connection unavailable')) } // Initiate reconnect if needed if (this.reconnect) { - this.connect(); + this.connect() } - return false; + return false } else { - this._flushQueue(); - return this._sendSocket(message, expect, emitter, callback); + this._flushQueue() + return this._sendSocket(message, expect, emitter, callback) } -}; +} -Client.prototype._sendSocket = function _sendSocket(message, - expect, - emitter, - callback) { - var conn = this._socket; - var tracker = this._tracker; - var log = this.log; - var self = this; - var timer = false; - var sentEmitter = false; +Client.prototype._sendSocket = function _sendSocket (message, + expect, + emitter, + callback) { + var conn = this._socket + var tracker = this._tracker + var log = this.log + var self = this + var timer = false + var sentEmitter = false - function sendResult(event, obj) { + function sendResult (event, obj) { if (event === 'error' && self.listeners('resultError')) { - self.emit('resultError', obj); + self.emit('resultError', obj) } if (emitter) { if (event === 'error') { // Error will go unhandled if emitter hasn't been sent via callback. // Execute callback with the error instead. - if (!sentEmitter) - return callback(obj); + if (!sentEmitter) { return callback(obj) } } - return emitter.emit(event, obj); + return emitter.emit(event, obj) } - if (event === 'error') - return callback(obj); + if (event === 'error') { return callback(obj) } - return callback(null, obj); + return callback(null, obj) } - function messageCallback(msg) { - if (timer) - clearTimeout(timer); + function messageCallback (msg) { + if (timer) { clearTimeout(timer) } - if (log.trace()) - log.trace({msg: msg ? msg.json : null}, 'response received'); + if (log.trace()) { log.trace({ msg: msg ? msg.json : null }, 'response received') } - if (expect === 'abandon') - return sendResult('end', null); + if (expect === 'abandon') { return sendResult('end', null) } if (msg instanceof SearchEntry || msg instanceof SearchReference) { - var event = msg.constructor.name; - event = event[0].toLowerCase() + event.slice(1); - return sendResult(event, msg); + var event = msg.constructor.name + event = event[0].toLowerCase() + event.slice(1) + return sendResult(event, msg) } else { - tracker.remove(message.messageID); + tracker.remove(message.messageID) // Potentially mark client as idle - self._updateIdle(); + self._updateIdle() if (msg instanceof LDAPResult) { if (expect.indexOf(msg.status) === -1) { - return sendResult('error', errors.getError(msg)); + return sendResult('error', errors.getError(msg)) } - return sendResult('end', msg); + return sendResult('end', msg) } else if (msg instanceof Error) { - return sendResult('error', msg); + return sendResult('error', msg) } else { - return sendResult('error', new errors.ProtocolError(msg.type)); + return sendResult('error', new errors.ProtocolError(msg.type)) } } } - function onRequestTimeout() { - self.emit('timeout', message); - var cb = tracker.fetch(message.messageID); + function onRequestTimeout () { + self.emit('timeout', message) + var cb = tracker.fetch(message.messageID) if (cb) { - //FIXME: the timed-out request should be abandoned - cb(new errors.TimeoutError('request timeout (client interrupt)')); + // FIXME: the timed-out request should be abandoned + cb(new errors.TimeoutError('request timeout (client interrupt)')) } } - function writeCallback() { + function writeCallback () { if (expect === 'abandon') { // Mark the messageID specified as abandoned - tracker.abandon(message.abandonID); + tracker.abandon(message.abandonID) // No need to track the abandon request itself - tracker.remove(message.id); - return callback(null); + tracker.remove(message.id) + return callback(null) } else if (expect === 'unbind') { - conn.unbindMessageID = message.id; + conn.unbindMessageID = message.id // Mark client as disconnected once unbind clears the socket - self.connected = false; + self.connected = false // Some servers will RST the connection after receiving an unbind. // Socket errors are blackholed since the connection is being closed. - conn.removeAllListeners('error'); - conn.on('error', function () {}); - conn.end(); + conn.removeAllListeners('error') + conn.on('error', function () {}) + conn.end() } else if (emitter) { - sentEmitter = true; - return callback(null, emitter); + sentEmitter = true + return callback(null, emitter) } - return false; + return false } // Start actually doing something... - tracker.track(message, messageCallback); + tracker.track(message, messageCallback) // Mark client as active - this._updateIdle(true); + this._updateIdle(true) if (self.timeout) { - log.trace('Setting timeout to %d', self.timeout); - timer = setTimeout(onRequestTimeout, self.timeout); + log.trace('Setting timeout to %d', self.timeout) + timer = setTimeout(onRequestTimeout, self.timeout) } - if (log.trace()) - log.trace('sending request %j', message.json); + if (log.trace()) { log.trace('sending request %j', message.json) } try { - return conn.write(message.toBer(), writeCallback); + return conn.write(message.toBer(), writeCallback) } catch (e) { - if (timer) - clearTimeout(timer); + if (timer) { clearTimeout(timer) } - log.trace({err: e}, 'Error writing message to socket'); - return callback(e); + log.trace({ err: e }, 'Error writing message to socket') + return callback(e) } -}; +} diff --git a/lib/client/index.js b/lib/client/index.js index c3f4e73..40f53cc 100644 --- a/lib/client/index.js +++ b/lib/client/index.js @@ -1,46 +1,35 @@ // Copyright 2012 Mark Cavage, Inc. All rights reserved. -const logger = require('../logger'); -const Client = require('./client'); +const logger = require('../logger') +const Client = require('./client') +/// --- Functions - -///--- Functions - -function xor() { - var b = false; +function xor () { + var b = false for (var i = 0; i < arguments.length; i++) { if (arguments[i] && !b) { - b = true; + b = true } else if (arguments[i] && b) { - return false; + return false } } - return b; + return b } - - -///--- Exports +/// --- Exports module.exports = { Client: Client, - createClient: function createClient(options) { - if (typeof (options) !== 'object') - throw new TypeError('options (object) required'); - if (options.url && typeof (options.url) !== 'string') - throw new TypeError('options.url (string) required'); - if (options.socketPath && typeof (options.socketPath) !== 'string') - throw new TypeError('options.socketPath must be a string'); - if (!xor(options.url, options.socketPath)) - throw new TypeError('options.url ^ options.socketPath (String) required'); - if (!options.log) - options.log = logger; - if (!options.log.child) - options.log.child = function () { return options.log; } - if (typeof (options.log) !== 'object') - throw new TypeError('options.log must be an object'); + createClient: function createClient (options) { + if (typeof (options) !== 'object') { throw new TypeError('options (object) required') } + if (options.url && typeof (options.url) !== 'string') { throw new TypeError('options.url (string) required') } + if (options.socketPath && typeof (options.socketPath) !== 'string') { throw new TypeError('options.socketPath must be a string') } + if (!xor(options.url, options.socketPath)) { throw new TypeError('options.url ^ options.socketPath (String) required') } + if (!options.log) { options.log = logger } + if (!options.log.child) { options.log.child = function () { return options.log } } + if (typeof (options.log) !== 'object') { throw new TypeError('options.log must be an object') } - return new Client(options); + return new Client(options) } -}; +} diff --git a/lib/client/search_pager.js b/lib/client/search_pager.js index 2e1088f..ef249dc 100644 --- a/lib/client/search_pager.js +++ b/lib/client/search_pager.js @@ -1,18 +1,16 @@ -// Copyright 2014 Joyent, Inc. All rights reserved. +'use strict' -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +var EventEmitter = require('events').EventEmitter +var util = require('util') -var assert = require('assert-plus'); +var assert = require('assert-plus') -var dn = require('../dn'); -var messages = require('../messages/index'); -var Protocol = require('../protocol'); -var PagedControl = require('../controls/paged_results_control.js'); - - -///--- API +// var dn = require('../dn') +// var messages = require('../messages/index') +// var Protocol = require('../protocol') +var PagedControl = require('../controls/paged_results_control.js') +/// --- API /** * Handler object for paged search operations. @@ -33,140 +31,140 @@ var PagedControl = require('../controls/paged_results_control.js'); * able to emit 'end'. * 3. search - Emitted as an internal event to trigger another client search. */ -function SearchPager(opts) { - assert.object(opts); - assert.func(opts.callback); - assert.number(opts.pageSize); +function SearchPager (opts) { + assert.object(opts) + assert.func(opts.callback) + assert.number(opts.pageSize) - EventEmitter.call(this, {}); + EventEmitter.call(this, {}) - this.callback = opts.callback; - this.controls = opts.controls; - this.pageSize = opts.pageSize; - this.pagePause = opts.pagePause; + this.callback = opts.callback + this.controls = opts.controls + this.pageSize = opts.pageSize + this.pagePause = opts.pagePause this.controls.forEach(function (control) { if (control.type === PagedControl.OID) { // The point of using SearchPager is not having to do this. // Toss an error if the pagedResultsControl is present - throw new Error('redundant pagedResultControl'); + throw new Error('redundant pagedResultControl') } - }); + }) - this.finished = false; - this.started = false; + this.finished = false + this.started = false - var emitter = new EventEmitter(); - emitter.on('searchEntry', this.emit.bind(this, 'searchEntry')); - emitter.on('end', this._onEnd.bind(this)); - emitter.on('error', this._onError.bind(this)); - this.childEmitter = emitter; + var emitter = new EventEmitter() + emitter.on('searchEntry', this.emit.bind(this, 'searchEntry')) + emitter.on('end', this._onEnd.bind(this)) + emitter.on('error', this._onError.bind(this)) + this.childEmitter = emitter } -util.inherits(SearchPager, EventEmitter); -module.exports = SearchPager; +util.inherits(SearchPager, EventEmitter) +module.exports = SearchPager /** * Start the paged search. */ -SearchPager.prototype.begin = function begin() { +SearchPager.prototype.begin = function begin () { // Starting first page - this._nextPage(null); -}; + this._nextPage(null) +} -SearchPager.prototype._onEnd = function _onEnd(res) { - var self = this; - var cookie = null; +SearchPager.prototype._onEnd = function _onEnd (res) { + var self = this + var cookie = null res.controls.forEach(function (control) { if (control.type === PagedControl.OID) { - cookie = control.value.cookie; + cookie = control.value.cookie } - }); + }) // Pass a noop callback by default for page events - var nullCb = function () { }; + var nullCb = function () { } if (cookie === null) { // paged search not supported - this.finished = true; - this.emit('page', res, nullCb); - var err = new Error('missing paged control'); - err.name = 'PagedError'; + this.finished = true + this.emit('page', res, nullCb) + var err = new Error('missing paged control') + err.name = 'PagedError' if (this.listeners('pageError').length > 0) { - this.emit('pageError', err); + this.emit('pageError', err) // If the consumer as subscribed to pageError, SearchPager is absolved // from deliverying the fault via the 'error' event. Emitting an 'end' // event after 'error' breaks the contract that the standard client // provides, so it's only a possibility if 'pageError' is used instead. - this.emit('end', res); + this.emit('end', res) } else { - this.emit('error', err); + this.emit('error', err) // No end event possible per explaination above. } - return; + return } if (cookie.length === 0) { // end of paged results - this.finished = true; - this.emit('page', nullCb); - this.emit('end', res); + this.finished = true + this.emit('page', nullCb) + this.emit('end', res) } else { if (this.pagePause) { // Wait to fetch next page until callback is invoked // Halt page fetching if called with error this.emit('page', res, function (err) { if (!err) { - self._nextPage(cookie); + self._nextPage(cookie) } else { // the paged search has been canceled so emit an end - self.emit('end', res); + self.emit('end', res) } - }); + }) } else { - this.emit('page', res, nullCb); - this._nextPage(cookie); + this.emit('page', res, nullCb) + this._nextPage(cookie) } } -}; +} -SearchPager.prototype._onError = function _onError(err) { - this.finished = true; - this.emit('error', err); -}; +SearchPager.prototype._onError = function _onError (err) { + this.finished = true + this.emit('error', err) +} /** * Initiate a search for the next page using the returned cookie value. */ -SearchPager.prototype._nextPage = function _nextPage(cookie) { - var controls = this.controls.slice(0); +SearchPager.prototype._nextPage = function _nextPage (cookie) { + var controls = this.controls.slice(0) controls.push(new PagedControl({ value: { size: this.pageSize, cookie: cookie } - })); + })) this.emit('search', controls, this.childEmitter, - this._sendCallback.bind(this)); -}; + this._sendCallback.bind(this)) +} /** * Callback provided to the client API for successful transmission. */ -SearchPager.prototype._sendCallback = function _sendCallback(err, res) { +SearchPager.prototype._sendCallback = function _sendCallback (err, res) { if (err) { - this.finished = true; + this.finished = true if (!this.started) { // EmitSend error during the first page, bail via callback - this.callback(err, null); + this.callback(err, null) } else { - this.emit('error', err); + this.emit('error', err) } } else { // search successfully send if (!this.started) { - this.started = true; + this.started = true // send self as emitter as the client would - this.callback(null, this); + this.callback(null, this) } } -}; +} diff --git a/lib/controls/control.js b/lib/controls/control.js index 100b8c9..57b9ccd 100644 --- a/lib/controls/control.js +++ b/lib/controls/control.js @@ -1,67 +1,61 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') -var asn1 = require('asn1'); +// var asn1 = require('asn1') -var Protocol = require('../protocol'); +// var Protocol = require('../protocol') +/// --- Globals -///--- Globals +// var Ber = asn1.Ber -var Ber = asn1.Ber; +/// --- API - -///--- API - -function Control(options) { - assert.optionalObject(options); - options = options || {}; - assert.optionalString(options.type); - assert.optionalBool(options.criticality); +function Control (options) { + assert.optionalObject(options) + options = options || {} + assert.optionalString(options.type) + assert.optionalBool(options.criticality) if (options.value) { - assert.buffer(options.value); + assert.buffer(options.value) } - this.type = options.type || ''; - this.criticality = options.critical || options.criticality || false; - this.value = options.value || null; + this.type = options.type || '' + this.criticality = options.critical || options.criticality || false + this.value = options.value || null } Object.defineProperties(Control.prototype, { json: { - get: function getJson() { + get: function getJson () { var obj = { controlType: this.type, criticality: this.criticality, controlValue: this.value - }; - return (typeof (this._json) === 'function' ? this._json(obj) : obj); + } + return (typeof (this._json) === 'function' ? this._json(obj) : obj) } } -}); +}) -Control.prototype.toBer = function toBer(ber) { - assert.ok(ber); +Control.prototype.toBer = function toBer (ber) { + assert.ok(ber) - ber.startSequence(); - ber.writeString(this.type || ''); - ber.writeBoolean(this.criticality); + ber.startSequence() + ber.writeString(this.type || '') + ber.writeBoolean(this.criticality) if (typeof (this._toBer) === 'function') { - this._toBer(ber); + this._toBer(ber) } else { - if (this.value) - ber.writeString(this.value); + if (this.value) { ber.writeString(this.value) } } - ber.endSequence(); - return; -}; + ber.endSequence() +} -Control.prototype.toString = function toString() { - return this.json; -}; +Control.prototype.toString = function toString () { + return this.json +} - -///--- Exports -module.exports = Control; +/// --- Exports +module.exports = Control diff --git a/lib/controls/entry_change_notification_control.js b/lib/controls/entry_change_notification_control.js index 11e3b69..9ed92ad 100644 --- a/lib/controls/entry_change_notification_control.js +++ b/lib/controls/entry_change_notification_control.js @@ -1,89 +1,83 @@ -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var Control = require('./control'); +var Control = require('./control') +/// --- Globals -///--- Globals +var BerReader = asn1.BerReader +var BerWriter = asn1.BerWriter -var BerReader = asn1.BerReader; -var BerWriter = asn1.BerWriter; +/// --- API - -///--- API - -function EntryChangeNotificationControl(options) { - assert.optionalObject(options); - options = options || {}; - options.type = EntryChangeNotificationControl.OID; +function EntryChangeNotificationControl (options) { + assert.optionalObject(options) + options = options || {} + options.type = EntryChangeNotificationControl.OID if (options.value) { if (Buffer.isBuffer(options.value)) { - this.parse(options.value); + this.parse(options.value) } else if (typeof (options.value) === 'object') { - this._value = options.value; + this._value = options.value } else { - throw new TypeError('options.value must be a Buffer or Object'); + throw new TypeError('options.value must be a Buffer or Object') } - options.value = null; + options.value = null } - Control.call(this, options); + Control.call(this, options) } -util.inherits(EntryChangeNotificationControl, Control); +util.inherits(EntryChangeNotificationControl, Control) Object.defineProperties(EntryChangeNotificationControl.prototype, { value: { - get: function () { return this._value || {}; }, + get: function () { return this._value || {} }, configurable: false } -}); +}) -EntryChangeNotificationControl.prototype.parse = function parse(buffer) { - assert.ok(buffer); +EntryChangeNotificationControl.prototype.parse = function parse (buffer) { + assert.ok(buffer) - var ber = new BerReader(buffer); + var ber = new BerReader(buffer) if (ber.readSequence()) { this._value = { changeType: ber.readInt() - }; + } // if the operation was moddn, then parse the optional previousDN attr - if (this._value.changeType === 8) - this._value.previousDN = ber.readString(); + if (this._value.changeType === 8) { this._value.previousDN = ber.readString() } - this._value.changeNumber = ber.readInt(); + this._value.changeNumber = ber.readInt() - return true; + return true } - return false; -}; + return false +} EntryChangeNotificationControl.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (!this._value) - return; + if (!this._value) { return } - var writer = new BerWriter(); - writer.startSequence(); - writer.writeInt(this.value.changeType); - if (this.value.previousDN) - writer.writeString(this.value.previousDN); + var writer = new BerWriter() + writer.startSequence() + writer.writeInt(this.value.changeType) + if (this.value.previousDN) { writer.writeString(this.value.previousDN) } - writer.writeInt(parseInt(this.value.changeNumber, 10)); - writer.endSequence(); + writer.writeInt(parseInt(this.value.changeNumber, 10)) + writer.endSequence() - ber.writeBuffer(writer.buffer, 0x04); -}; + ber.writeBuffer(writer.buffer, 0x04) +} EntryChangeNotificationControl.prototype._json = function (obj) { - obj.controlValue = this.value; - return obj; -}; + obj.controlValue = this.value + return obj +} -EntryChangeNotificationControl.OID = '2.16.840.1.113730.3.4.7'; +EntryChangeNotificationControl.OID = '2.16.840.1.113730.3.4.7' - -///--- Exports -module.exports = EntryChangeNotificationControl; +/// --- Exports +module.exports = EntryChangeNotificationControl diff --git a/lib/controls/index.js b/lib/controls/index.js index f53b7f6..3ac11b2 100644 --- a/lib/controls/index.js +++ b/lib/controls/index.js @@ -1,73 +1,68 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var Ber = require('asn1').Ber; +var assert = require('assert') +var Ber = require('asn1').Ber -var Control = require('./control'); +var Control = require('./control') var EntryChangeNotificationControl = - require('./entry_change_notification_control'); -var PersistentSearchControl = require('./persistent_search_control'); -var PagedResultsControl = require('./paged_results_control'); + require('./entry_change_notification_control') +var PersistentSearchControl = require('./persistent_search_control') +var PagedResultsControl = require('./paged_results_control') var ServerSideSortingRequestControl = - require('./server_side_sorting_request_control.js'); + require('./server_side_sorting_request_control.js') var ServerSideSortingResponseControl = - require('./server_side_sorting_response_control.js'); + require('./server_side_sorting_response_control.js') - - -///--- API +/// --- API module.exports = { - getControl: function getControl(ber) { - assert.ok(ber); + getControl: function getControl (ber) { + assert.ok(ber) - if (ber.readSequence() === null) - return null; + if (ber.readSequence() === null) { return null } - var type; + var type var opts = { criticality: false, value: null - }; + } if (ber.length) { - var end = ber.offset + ber.length; + var end = ber.offset + ber.length - type = ber.readString(); + type = ber.readString() if (ber.offset < end) { - if (ber.peek() === Ber.Boolean) - opts.criticality = ber.readBoolean(); + if (ber.peek() === Ber.Boolean) { opts.criticality = ber.readBoolean() } } - if (ber.offset < end) - opts.value = ber.readString(Ber.OctetString, true); + if (ber.offset < end) { opts.value = ber.readString(Ber.OctetString, true) } } - var control; + var control switch (type) { - case PersistentSearchControl.OID: - control = new PersistentSearchControl(opts); - break; - case EntryChangeNotificationControl.OID: - control = new EntryChangeNotificationControl(opts); - break; - case PagedResultsControl.OID: - control = new PagedResultsControl(opts); - break; - case ServerSideSortingRequestControl.OID: - control = new ServerSideSortingRequestControl(opts); - break; - case ServerSideSortingResponseControl.OID: - control = new ServerSideSortingResponseControl(opts); - break; - default: - opts.type = type; - control = new Control(opts); - break; + case PersistentSearchControl.OID: + control = new PersistentSearchControl(opts) + break + case EntryChangeNotificationControl.OID: + control = new EntryChangeNotificationControl(opts) + break + case PagedResultsControl.OID: + control = new PagedResultsControl(opts) + break + case ServerSideSortingRequestControl.OID: + control = new ServerSideSortingRequestControl(opts) + break + case ServerSideSortingResponseControl.OID: + control = new ServerSideSortingResponseControl(opts) + break + default: + opts.type = type + control = new Control(opts) + break } - return control; + return control }, Control: Control, @@ -76,4 +71,4 @@ module.exports = { PersistentSearchControl: PersistentSearchControl, ServerSideSortingRequestControl: ServerSideSortingRequestControl, ServerSideSortingResponseControl: ServerSideSortingResponseControl -}; +} diff --git a/lib/controls/paged_results_control.js b/lib/controls/paged_results_control.js index fcfe468..de6b23b 100644 --- a/lib/controls/paged_results_control.js +++ b/lib/controls/paged_results_control.js @@ -1,87 +1,82 @@ -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var Control = require('./control'); +var Control = require('./control') +/// --- Globals -///--- Globals +var BerReader = asn1.BerReader +var BerWriter = asn1.BerWriter -var BerReader = asn1.BerReader; -var BerWriter = asn1.BerWriter; +/// --- API - -///--- API - -function PagedResultsControl(options) { - assert.optionalObject(options); - options = options || {}; - options.type = PagedResultsControl.OID; +function PagedResultsControl (options) { + assert.optionalObject(options) + options = options || {} + options.type = PagedResultsControl.OID if (options.value) { if (Buffer.isBuffer(options.value)) { - this.parse(options.value); + this.parse(options.value) } else if (typeof (options.value) === 'object') { - this._value = options.value; + this._value = options.value } else { - throw new TypeError('options.value must be a Buffer or Object'); + throw new TypeError('options.value must be a Buffer or Object') } - options.value = null; + options.value = null } - Control.call(this, options); + Control.call(this, options) } -util.inherits(PagedResultsControl, Control); +util.inherits(PagedResultsControl, Control) Object.defineProperties(PagedResultsControl.prototype, { value: { - get: function () { return this._value || {}; }, + get: function () { return this._value || {} }, configurable: false } -}); +}) -PagedResultsControl.prototype.parse = function parse(buffer) { - assert.ok(buffer); +PagedResultsControl.prototype.parse = function parse (buffer) { + assert.ok(buffer) - var ber = new BerReader(buffer); + var ber = new BerReader(buffer) if (ber.readSequence()) { - this._value = {}; - this._value.size = ber.readInt(); - this._value.cookie = ber.readString(asn1.Ber.OctetString, true); - //readString returns '' instead of a zero-length buffer - if (!this._value.cookie) - this._value.cookie = Buffer.alloc(0); + this._value = {} + this._value.size = ber.readInt() + this._value.cookie = ber.readString(asn1.Ber.OctetString, true) + // readString returns '' instead of a zero-length buffer + if (!this._value.cookie) { this._value.cookie = Buffer.alloc(0) } - return true; + return true } - return false; -}; + return false +} PagedResultsControl.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (!this._value) - return; + if (!this._value) { return } - var writer = new BerWriter(); - writer.startSequence(); - writer.writeInt(this.value.size); + var writer = new BerWriter() + writer.startSequence() + writer.writeInt(this.value.size) if (this.value.cookie && this.value.cookie.length > 0) { - writer.writeBuffer(this.value.cookie, asn1.Ber.OctetString); + writer.writeBuffer(this.value.cookie, asn1.Ber.OctetString) } else { - writer.writeString(''); //writeBuffer rejects zero-length buffers + writer.writeString('') // writeBuffer rejects zero-length buffers } - writer.endSequence(); + writer.endSequence() - ber.writeBuffer(writer.buffer, 0x04); -}; + ber.writeBuffer(writer.buffer, 0x04) +} PagedResultsControl.prototype._json = function (obj) { - obj.controlValue = this.value; - return obj; -}; + obj.controlValue = this.value + return obj +} -PagedResultsControl.OID = '1.2.840.113556.1.4.319'; +PagedResultsControl.OID = '1.2.840.113556.1.4.319' - -///--- Exports -module.exports = PagedResultsControl; +/// --- Exports +module.exports = PagedResultsControl diff --git a/lib/controls/persistent_search_control.js b/lib/controls/persistent_search_control.js index ee3a7b1..bf5695f 100644 --- a/lib/controls/persistent_search_control.js +++ b/lib/controls/persistent_search_control.js @@ -1,85 +1,82 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var Control = require('./control'); +var Control = require('./control') +/// --- Globals -///--- Globals +var BerReader = asn1.BerReader +var BerWriter = asn1.BerWriter -var BerReader = asn1.BerReader; -var BerWriter = asn1.BerWriter; +/// --- API - -///--- API - -function PersistentSearchControl(options) { - assert.optionalObject(options); - options = options || {}; - options.type = PersistentSearchControl.OID; +function PersistentSearchControl (options) { + assert.optionalObject(options) + options = options || {} + options.type = PersistentSearchControl.OID if (options.value) { if (Buffer.isBuffer(options.value)) { - this.parse(options.value); + this.parse(options.value) } else if (typeof (options.value) === 'object') { - this._value = options.value; + this._value = options.value } else { - throw new TypeError('options.value must be a Buffer or Object'); + throw new TypeError('options.value must be a Buffer or Object') } - options.value = null; + options.value = null } - Control.call(this, options); + Control.call(this, options) } -util.inherits(PersistentSearchControl, Control); +util.inherits(PersistentSearchControl, Control) Object.defineProperties(PersistentSearchControl.prototype, { value: { - get: function () { return this._value || {}; }, + get: function () { return this._value || {} }, configurable: false } -}); +}) -PersistentSearchControl.prototype.parse = function parse(buffer) { - assert.ok(buffer); +PersistentSearchControl.prototype.parse = function parse (buffer) { + assert.ok(buffer) - var ber = new BerReader(buffer); + var ber = new BerReader(buffer) if (ber.readSequence()) { this._value = { changeTypes: ber.readInt(), changesOnly: ber.readBoolean(), returnECs: ber.readBoolean() - }; + } - return true; + return true } - return false; -}; + return false +} PersistentSearchControl.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (!this._value) - return; + if (!this._value) { return } - var writer = new BerWriter(); - writer.startSequence(); - writer.writeInt(this.value.changeTypes); - writer.writeBoolean(this.value.changesOnly); - writer.writeBoolean(this.value.returnECs); - writer.endSequence(); + var writer = new BerWriter() + writer.startSequence() + writer.writeInt(this.value.changeTypes) + writer.writeBoolean(this.value.changesOnly) + writer.writeBoolean(this.value.returnECs) + writer.endSequence() - ber.writeBuffer(writer.buffer, 0x04); -}; + ber.writeBuffer(writer.buffer, 0x04) +} PersistentSearchControl.prototype._json = function (obj) { - obj.controlValue = this.value; - return obj; -}; + obj.controlValue = this.value + return obj +} -PersistentSearchControl.OID = '2.16.840.1.113730.3.4.3'; +PersistentSearchControl.OID = '2.16.840.1.113730.3.4.3' -///--- Exports -module.exports = PersistentSearchControl; +/// --- Exports +module.exports = PersistentSearchControl diff --git a/lib/controls/server_side_sorting_request_control.js b/lib/controls/server_side_sorting_request_control.js index 8daf76f..2bf8baf 100644 --- a/lib/controls/server_side_sorting_request_control.js +++ b/lib/controls/server_side_sorting_request_control.js @@ -1,112 +1,108 @@ -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var Control = require('./control'); +var Control = require('./control') +/// --- Globals -///--- Globals +var BerReader = asn1.BerReader +var BerWriter = asn1.BerWriter -var BerReader = asn1.BerReader; -var BerWriter = asn1.BerWriter; +/// --- API - -///--- API - -function ServerSideSortingRequestControl(options) { - assert.optionalObject(options); - options = options || {}; - options.type = ServerSideSortingRequestControl.OID; +function ServerSideSortingRequestControl (options) { + assert.optionalObject(options) + options = options || {} + options.type = ServerSideSortingRequestControl.OID if (options.value) { if (Buffer.isBuffer(options.value)) { - this.parse(options.value); + this.parse(options.value) } else if (Array.isArray(options.value)) { - assert.arrayOfObject(options.value, 'options.value must be Objects'); + assert.arrayOfObject(options.value, 'options.value must be Objects') for (var i = 0; i < options.value.length; i++) { - if (!options.value[i].hasOwnProperty('attributeType')) { - throw new Error('Missing required key: attributeType'); + if (Object.prototype.hasOwnProperty.call(options.value[i], 'attributeType') === false) { + throw new Error('Missing required key: attributeType') } } - this._value = options.value; + this._value = options.value } else if (typeof (options.value) === 'object') { - if (!options.value.hasOwnProperty('attributeType')) { - throw new Error('Missing required key: attributeType'); + if (Object.prototype.hasOwnProperty.call(options.value, 'attributeType') === false) { + throw new Error('Missing required key: attributeType') } - this._value = [options.value]; + this._value = [options.value] } else { - throw new TypeError('options.value must be a Buffer, Array or Object'); + throw new TypeError('options.value must be a Buffer, Array or Object') } - options.value = null; + options.value = null } - Control.call(this, options); + Control.call(this, options) } -util.inherits(ServerSideSortingRequestControl, Control); +util.inherits(ServerSideSortingRequestControl, Control) Object.defineProperties(ServerSideSortingRequestControl.prototype, { value: { - get: function () { return this._value || []; }, + get: function () { return this._value || [] }, configurable: false } -}); +}) -ServerSideSortingRequestControl.prototype.parse = function parse(buffer) { - assert.ok(buffer); +ServerSideSortingRequestControl.prototype.parse = function parse (buffer) { + assert.ok(buffer) - var ber = new BerReader(buffer); - var item; + var ber = new BerReader(buffer) + var item if (ber.readSequence(0x30)) { - this._value = []; + this._value = [] while (ber.readSequence(0x30)) { - item = {}; - item.attributeType = ber.readString(asn1.Ber.OctetString); - if (ber.peek() == 0x80) { - item.orderingRule = ber.readString(0x80); + item = {} + item.attributeType = ber.readString(asn1.Ber.OctetString) + if (ber.peek() === 0x80) { + item.orderingRule = ber.readString(0x80) } - if (ber.peek() == 0x81) { - item.reverseOrder = (ber._readTag(0x81) === 0 ? false : true); + if (ber.peek() === 0x81) { + item.reverseOrder = (ber._readTag(0x81) !== 0) } - this._value.push(item); + this._value.push(item) } - return true; + return true } - return false; -}; + return false +} ServerSideSortingRequestControl.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (!this._value || this.value.length === 0) - return; + if (!this._value || this.value.length === 0) { return } - var writer = new BerWriter(); - writer.startSequence(0x30); + var writer = new BerWriter() + writer.startSequence(0x30) for (var i = 0; i < this.value.length; i++) { - var item = this.value[i]; - writer.startSequence(0x30); + var item = this.value[i] + writer.startSequence(0x30) if (item.attributeType) { - writer.writeString(item.attributeType, asn1.Ber.OctetString); + writer.writeString(item.attributeType, asn1.Ber.OctetString) } if (item.orderingRule) { - writer.writeString(item.orderingRule, 0x80); + writer.writeString(item.orderingRule, 0x80) } if (item.reverseOrder) { - writer.writeBoolean(item.reverseOrder, 0x81); + writer.writeBoolean(item.reverseOrder, 0x81) } - writer.endSequence(); + writer.endSequence() } - writer.endSequence(); - ber.writeBuffer(writer.buffer, 0x04); -}; + writer.endSequence() + ber.writeBuffer(writer.buffer, 0x04) +} ServerSideSortingRequestControl.prototype._json = function (obj) { - obj.controlValue = this.value; - return obj; -}; + obj.controlValue = this.value + return obj +} -ServerSideSortingRequestControl.OID = '1.2.840.113556.1.4.473'; +ServerSideSortingRequestControl.OID = '1.2.840.113556.1.4.473' +/// ---Exports -///---Exports - -module.exports = ServerSideSortingRequestControl; +module.exports = ServerSideSortingRequestControl diff --git a/lib/controls/server_side_sorting_response_control.js b/lib/controls/server_side_sorting_response_control.js index c82e60a..8d2d20c 100644 --- a/lib/controls/server_side_sorting_response_control.js +++ b/lib/controls/server_side_sorting_response_control.js @@ -1,16 +1,15 @@ -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var Control = require('./control'); -var CODES = require('../errors/codes'); +var Control = require('./control') +var CODES = require('../errors/codes') +/// --- Globals -///--- Globals - -var BerReader = asn1.BerReader; -var BerWriter = asn1.BerWriter; +var BerReader = asn1.BerReader +var BerWriter = asn1.BerWriter var VALID_CODES = [ CODES.LDAP_SUCCESS, @@ -24,80 +23,78 @@ var VALID_CODES = [ CODES.LDAP_BUSY, CODES.LDAP_UNWILLING_TO_PERFORM, CODES.LDAP_OTHER -]; +] -function ServerSideSortingResponseControl(options) { - assert.optionalObject(options); - options = options || {}; - options.type = ServerSideSortingResponseControl.OID; - options.criticality = false; +function ServerSideSortingResponseControl (options) { + assert.optionalObject(options) + options = options || {} + options.type = ServerSideSortingResponseControl.OID + options.criticality = false if (options.value) { if (Buffer.isBuffer(options.value)) { - this.parse(options.value); + this.parse(options.value) } else if (typeof (options.value) === 'object') { if (VALID_CODES.indexOf(options.value.result) === -1) { - throw new Error('Invalid result code'); + throw new Error('Invalid result code') } if (options.value.failedAttribute && typeof (options.value.failedAttribute) !== 'string') { - throw new Error('failedAttribute must be String'); + throw new Error('failedAttribute must be String') } - this._value = options.value; + this._value = options.value } else { - throw new TypeError('options.value must be a Buffer or Object'); + throw new TypeError('options.value must be a Buffer or Object') } - options.value = null; + options.value = null } - Control.call(this, options); + Control.call(this, options) } -util.inherits(ServerSideSortingResponseControl, Control); +util.inherits(ServerSideSortingResponseControl, Control) Object.defineProperties(ServerSideSortingResponseControl.prototype, { value: { - get: function () { return this._value || {}; }, + get: function () { return this._value || {} }, configurable: false } -}); +}) -ServerSideSortingResponseControl.prototype.parse = function parse(buffer) { - assert.ok(buffer); +ServerSideSortingResponseControl.prototype.parse = function parse (buffer) { + assert.ok(buffer) - var ber = new BerReader(buffer); + var ber = new BerReader(buffer) if (ber.readSequence(0x30)) { - this._value = {}; - this._value.result = ber.readEnumeration(); - if (ber.peek() == 0x80) { - this._value.failedAttribute = ber.readString(0x80); + this._value = {} + this._value.result = ber.readEnumeration() + if (ber.peek() === 0x80) { + this._value.failedAttribute = ber.readString(0x80) } - return true; + return true } - return false; -}; + return false +} ServerSideSortingResponseControl.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (!this._value || this.value.length === 0) - return; + if (!this._value || this.value.length === 0) { return } - var writer = new BerWriter(); - writer.startSequence(0x30); - writer.writeEnumeration(this.value.result); + var writer = new BerWriter() + writer.startSequence(0x30) + writer.writeEnumeration(this.value.result) if (this.value.result !== CODES.LDAP_SUCCESS && this.value.failedAttribute) { - writer.writeString(this.value.failedAttribute, 0x80); + writer.writeString(this.value.failedAttribute, 0x80) } - writer.endSequence(); - ber.writeBuffer(writer.buffer, 0x04); -}; + writer.endSequence() + ber.writeBuffer(writer.buffer, 0x04) +} ServerSideSortingResponseControl.prototype._json = function (obj) { - obj.controlValue = this.value; - return obj; -}; + obj.controlValue = this.value + return obj +} -ServerSideSortingResponseControl.OID = '1.2.840.113556.1.4.474'; +ServerSideSortingResponseControl.OID = '1.2.840.113556.1.4.474' - -///--- Exports -module.exports = ServerSideSortingResponseControl; +/// --- Exports +module.exports = ServerSideSortingResponseControl diff --git a/lib/dn.js b/lib/dn.js index b03ce15..2d93738 100644 --- a/lib/dn.js +++ b/lib/dn.js @@ -1,336 +1,317 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. +var assert = require('assert-plus') -var assert = require('assert-plus'); +/// --- Helpers - -///--- Helpers - -function invalidDN(name) { - var e = new Error(); - e.name = 'InvalidDistinguishedNameError'; - e.message = name; - return e; +function invalidDN (name) { + var e = new Error() + e.name = 'InvalidDistinguishedNameError' + e.message = name + return e } -function isAlphaNumeric(c) { - var re = /[A-Za-z0-9]/; - return re.test(c); +function isAlphaNumeric (c) { + var re = /[A-Za-z0-9]/ + return re.test(c) } -function isWhitespace(c) { - var re = /\s/; - return re.test(c); +function isWhitespace (c) { + var re = /\s/ + return re.test(c) } -function repeatChar(c, n) { - var out = ''; - var max = n ? n : 0; - for (var i = 0; i < max; i++) - out += c; - return out; +function repeatChar (c, n) { + var out = '' + var max = n || 0 + for (var i = 0; i < max; i++) { out += c } + return out } -///--- API +/// --- API -function RDN(obj) { - var self = this; - this.attrs = {}; +function RDN (obj) { + var self = this + this.attrs = {} if (obj) { Object.keys(obj).forEach(function (k) { - self.set(k, obj[k]); - }); + self.set(k, obj[k]) + }) } } -RDN.prototype.set = function rdnSet(name, value, opts) { - assert.string(name, 'name (string) required'); - assert.string(value, 'value (string) required'); +RDN.prototype.set = function rdnSet (name, value, opts) { + assert.string(name, 'name (string) required') + assert.string(value, 'value (string) required') - var self = this; - var lname = name.toLowerCase(); + var self = this + var lname = name.toLowerCase() this.attrs[lname] = { value: value, name: name - }; + } if (opts && typeof (opts) === 'object') { Object.keys(opts).forEach(function (k) { - if (k !== 'value') - self.attrs[lname][k] = opts[k]; - }); + if (k !== 'value') { self.attrs[lname][k] = opts[k] } + }) } -}; +} -RDN.prototype.equals = function rdnEquals(rdn) { - if (typeof (rdn) !== 'object') - return false; +RDN.prototype.equals = function rdnEquals (rdn) { + if (typeof (rdn) !== 'object') { return false } - var ourKeys = Object.keys(this.attrs); - var theirKeys = Object.keys(rdn.attrs); - if (ourKeys.length !== theirKeys.length) - return false; + var ourKeys = Object.keys(this.attrs) + var theirKeys = Object.keys(rdn.attrs) + if (ourKeys.length !== theirKeys.length) { return false } - ourKeys.sort(); - theirKeys.sort(); + ourKeys.sort() + theirKeys.sort() for (var i = 0; i < ourKeys.length; i++) { - if (ourKeys[i] !== theirKeys[i]) - return false; - if (this.attrs[ourKeys[i]].value !== rdn.attrs[ourKeys[i]].value) - return false; + if (ourKeys[i] !== theirKeys[i]) { return false } + if (this.attrs[ourKeys[i]].value !== rdn.attrs[ourKeys[i]].value) { return false } } - return true; -}; - + return true +} /** * Convert RDN to string according to specified formatting options. * (see: DN.format for option details) */ -RDN.prototype.format = function rdnFormat(options) { - assert.optionalObject(options, 'options must be an object'); - options = options || {}; +RDN.prototype.format = function rdnFormat (options) { + assert.optionalObject(options, 'options must be an object') + options = options || {} - var self = this; - var str = ''; + var self = this + var str = '' - function escapeValue(val, forceQuote) { - var out = ''; - var cur = 0; - var len = val.length; - var quoted = false; + function escapeValue (val, forceQuote) { + var out = '' + var cur = 0 + var len = val.length + var quoted = false /* BEGIN JSSTYLED */ - var escaped = /[\\\"]/; - var special = /[,=+<>#;]/; + // TODO: figure out what this regex is actually trying to test for and + // fix it to appease the linter. + /* eslint-disable-next-line no-useless-escape */ + var escaped = /[\\\"]/ + var special = /[,=+<>#;]/ /* END JSSTYLED */ if (len > 0) { // Wrap strings with trailing or leading spaces in quotes - quoted = forceQuote || (val[0] == ' ' || val[len-1] == ' '); + quoted = forceQuote || (val[0] === ' ' || val[len - 1] === ' ') } while (cur < len) { if (escaped.test(val[cur]) || (!quoted && special.test(val[cur]))) { - out += '\\'; + out += '\\' } - out += val[cur++]; + out += val[cur++] } - if (quoted) - out = '"' + out + '"'; - return out; + if (quoted) { out = '"' + out + '"' } + return out } - function sortParsed(a, b) { - return self.attrs[a].order - self.attrs[b].order; + function sortParsed (a, b) { + return self.attrs[a].order - self.attrs[b].order } - function sortStandard(a, b) { - var nameCompare = a.localeCompare(b); + function sortStandard (a, b) { + var nameCompare = a.localeCompare(b) if (nameCompare === 0) { // TODO: Handle binary values - return self.attrs[a].value.localeCompare(self.attrs[b].value); + return self.attrs[a].value.localeCompare(self.attrs[b].value) } else { - return nameCompare; + return nameCompare } } - var keys = Object.keys(this.attrs); + var keys = Object.keys(this.attrs) if (options.keepOrder) { - keys.sort(sortParsed); + keys.sort(sortParsed) } else { - keys.sort(sortStandard); + keys.sort(sortStandard) } keys.forEach(function (key) { - var attr = self.attrs[key]; - if (str.length) - str += '+'; + var attr = self.attrs[key] + if (str.length) { str += '+' } if (options.keepCase) { - str += attr.name; + str += attr.name } else { - if (options.upperName) - str += key.toUpperCase(); - else - str += key; + if (options.upperName) { str += key.toUpperCase() } else { str += key } } - str += '=' + escapeValue(attr.value, (options.keepQuote && attr.quoted)); - }); + str += '=' + escapeValue(attr.value, (options.keepQuote && attr.quoted)) + }) - return str; -}; - -RDN.prototype.toString = function rdnToString() { - return this.format(); -}; + return str +} +RDN.prototype.toString = function rdnToString () { + return this.format() +} // Thank you OpenJDK! -function parse(name) { - if (typeof (name) !== 'string') - throw new TypeError('name (string) required'); +function parse (name) { + if (typeof (name) !== 'string') { throw new TypeError('name (string) required') } - var cur = 0; - var len = name.length; + var cur = 0 + var len = name.length - function parseRdn() { - var rdn = new RDN(); - var order = 0; - rdn.spLead = trim(); + function parseRdn () { + var rdn = new RDN() + var order = 0 + rdn.spLead = trim() while (cur < len) { var opts = { order: order - }; - var attr = parseAttrType(); - trim(); - if (cur >= len || name[cur++] !== '=') - throw invalidDN(name); + } + var attr = parseAttrType() + trim() + if (cur >= len || name[cur++] !== '=') { throw invalidDN(name) } - trim(); + trim() // Parameters about RDN value are set in 'opts' by parseAttrValue - var value = parseAttrValue(opts); - rdn.set(attr, value, opts); - rdn.spTrail = trim(); - if (cur >= len || name[cur] !== '+') - break; - ++cur; - ++order; + var value = parseAttrValue(opts) + rdn.set(attr, value, opts) + rdn.spTrail = trim() + if (cur >= len || name[cur] !== '+') { break } + ++cur + ++order } - return rdn; + return rdn } - - function trim() { - var count = 0; + function trim () { + var count = 0 while ((cur < len) && isWhitespace(name[cur])) { - ++cur; - count++; + ++cur + count++ } - return count; + return count } - function parseAttrType() { - var beg = cur; + function parseAttrType () { + var beg = cur while (cur < len) { - var c = name[cur]; + var c = name[cur] if (isAlphaNumeric(c) || - c == '.' || - c == '-' || - c == ' ') { - ++cur; + c === '.' || + c === '-' || + c === ' ') { + ++cur } else { - break; + break } } // Back out any trailing spaces. - while ((cur > beg) && (name[cur - 1] == ' ')) - --cur; + while ((cur > beg) && (name[cur - 1] === ' ')) { --cur } - if (beg == cur) - throw invalidDN(name); + if (beg === cur) { throw invalidDN(name) } - return name.slice(beg, cur); + return name.slice(beg, cur) } - function parseAttrValue(opts) { - if (cur < len && name[cur] == '#') { - opts.binary = true; - return parseBinaryAttrValue(); - } else if (cur < len && name[cur] == '"') { - opts.quoted = true; - return parseQuotedAttrValue(); + function parseAttrValue (opts) { + if (cur < len && name[cur] === '#') { + opts.binary = true + return parseBinaryAttrValue() + } else if (cur < len && name[cur] === '"') { + opts.quoted = true + return parseQuotedAttrValue() } else { - return parseStringAttrValue(); + return parseStringAttrValue() } } - function parseBinaryAttrValue() { - var beg = cur++; - while (cur < len && isAlphaNumeric(name[cur])) - ++cur; + function parseBinaryAttrValue () { + var beg = cur++ + while (cur < len && isAlphaNumeric(name[cur])) { ++cur } - return name.slice(beg, cur); + return name.slice(beg, cur) } - function parseQuotedAttrValue() { - var str = ''; - ++cur; // Consume the first quote + function parseQuotedAttrValue () { + var str = '' + ++cur // Consume the first quote - while ((cur < len) && name[cur] != '"') { - if (name[cur] === '\\') - cur++; - str += name[cur++]; + while ((cur < len) && name[cur] !== '"') { + if (name[cur] === '\\') { cur++ } + str += name[cur++] + } + if (cur++ >= len) { + // no closing quote + throw invalidDN(name) } - if (cur++ >= len) // no closing quote - throw invalidDN(name); - return str; + return str } - function parseStringAttrValue() { - var beg = cur; - var str = ''; - var esc = -1; + function parseStringAttrValue () { + var beg = cur + var str = '' + var esc = -1 while ((cur < len) && !atTerminator()) { if (name[cur] === '\\') { // Consume the backslash and mark its place just in case it's escaping // whitespace which needs to be preserved. - esc = cur++; + esc = cur++ } - if (cur === len) // backslash followed by nothing - throw invalidDN(name); - str += name[cur++]; + if (cur === len) { + // backslash followed by nothing + throw invalidDN(name) + } + str += name[cur++] } // Trim off (unescaped) trailing whitespace and rewind cursor to the end of // the AttrValue to record whitespace length. for (; cur > beg; cur--) { - if (!isWhitespace(name[cur - 1]) || (esc === (cur - 1))) - break; + if (!isWhitespace(name[cur - 1]) || (esc === (cur - 1))) { break } } - return str.slice(0, cur - beg); + return str.slice(0, cur - beg) } - function atTerminator() { + function atTerminator () { return (cur < len && (name[cur] === ',' || name[cur] === ';' || - name[cur] === '+')); + name[cur] === '+')) } - var rdns = []; + var rdns = [] // Short-circuit for empty DNs - if (len === 0) - return new DN(rdns); + if (len === 0) { return new DN(rdns) } - rdns.push(parseRdn()); + rdns.push(parseRdn()) while (cur < len) { if (name[cur] === ',' || name[cur] === ';') { - ++cur; - rdns.push(parseRdn()); + ++cur + rdns.push(parseRdn()) } else { - throw invalidDN(name); + throw invalidDN(name) } } - return new DN(rdns); + return new DN(rdns) } +function DN (rdns) { + assert.optionalArrayOfObject(rdns, '[object] required') -function DN(rdns) { - assert.optionalArrayOfObject(rdns, '[object] required'); - - this.rdns = rdns ? rdns.slice() : []; - this._format = {}; + this.rdns = rdns ? rdns.slice() : [] + this._format = {} } Object.defineProperties(DN.prototype, { length: { - get: function getLength() { return this.rdns.length; }, + get: function getLength () { return this.rdns.length }, configurable: false } -}); +}) /** * Convert DN to string according to specified formatting options. @@ -355,146 +336,138 @@ Object.defineProperties(DN.prototype, { * - upperName: RDN names will be uppercased instead of lowercased. * - skipSpace: Disable trailing space after RDN separators */ -DN.prototype.format = function dnFormat(options) { - assert.optionalObject(options, 'options must be an object'); - options = options || this._format; +DN.prototype.format = function dnFormat (options) { + assert.optionalObject(options, 'options must be an object') + options = options || this._format - var str = ''; + var str = '' this.rdns.forEach(function (rdn) { - var rdnString = rdn.format(options); + var rdnString = rdn.format(options) if (str.length !== 0) { - str += ','; + str += ',' } if (options.keepSpace) { str += (repeatChar(' ', rdn.spLead) + - rdnString + repeatChar(' ', rdn.spTrail)); + rdnString + repeatChar(' ', rdn.spTrail)) } else if (options.skipSpace === true || str.length === 0) { - str += rdnString; + str += rdnString } else { - str += ' ' + rdnString; + str += ' ' + rdnString } - }); - return str; -}; + }) + return str +} /** * Set default string formatting options. */ -DN.prototype.setFormat = function setFormat(options) { - assert.object(options, 'options must be an object'); +DN.prototype.setFormat = function setFormat (options) { + assert.object(options, 'options must be an object') - this._format = options; -}; + this._format = options +} -DN.prototype.toString = function dnToString() { - return this.format(); -}; +DN.prototype.toString = function dnToString () { + return this.format() +} -DN.prototype.parentOf = function parentOf(dn) { - if (typeof (dn) !== 'object') - dn = parse(dn); +DN.prototype.parentOf = function parentOf (dn) { + if (typeof (dn) !== 'object') { dn = parse(dn) } - if (this.rdns.length >= dn.rdns.length) - return false; + if (this.rdns.length >= dn.rdns.length) { return false } - var diff = dn.rdns.length - this.rdns.length; + var diff = dn.rdns.length - this.rdns.length for (var i = this.rdns.length - 1; i >= 0; i--) { - var myRDN = this.rdns[i]; - var theirRDN = dn.rdns[i + diff]; + var myRDN = this.rdns[i] + var theirRDN = dn.rdns[i + diff] - if (!myRDN.equals(theirRDN)) - return false; + if (!myRDN.equals(theirRDN)) { return false } } - return true; -}; + return true +} -DN.prototype.childOf = function childOf(dn) { - if (typeof (dn) !== 'object') - dn = parse(dn); - return dn.parentOf(this); -}; +DN.prototype.childOf = function childOf (dn) { + if (typeof (dn) !== 'object') { dn = parse(dn) } + return dn.parentOf(this) +} -DN.prototype.isEmpty = function isEmpty() { - return (this.rdns.length === 0); -}; +DN.prototype.isEmpty = function isEmpty () { + return (this.rdns.length === 0) +} -DN.prototype.equals = function dnEquals(dn) { - if (typeof (dn) !== 'object') - dn = parse(dn); +DN.prototype.equals = function dnEquals (dn) { + if (typeof (dn) !== 'object') { dn = parse(dn) } - if (this.rdns.length !== dn.rdns.length) - return false; + if (this.rdns.length !== dn.rdns.length) { return false } for (var i = 0; i < this.rdns.length; i++) { - if (!this.rdns[i].equals(dn.rdns[i])) - return false; + if (!this.rdns[i].equals(dn.rdns[i])) { return false } } - return true; -}; + return true +} -DN.prototype.parent = function dnParent() { +DN.prototype.parent = function dnParent () { if (this.rdns.length !== 0) { - var save = this.rdns.shift(); - var dn = new DN(this.rdns); - this.rdns.unshift(save); - return dn; + var save = this.rdns.shift() + var dn = new DN(this.rdns) + this.rdns.unshift(save) + return dn } - return null; -}; + return null +} -DN.prototype.clone = function dnClone() { - var dn = new DN(this.rdns); - dn._format = this._format; - return dn; -}; +DN.prototype.clone = function dnClone () { + var dn = new DN(this.rdns) + dn._format = this._format + return dn +} -DN.prototype.reverse = function dnReverse() { - this.rdns.reverse(); - return this; -}; +DN.prototype.reverse = function dnReverse () { + this.rdns.reverse() + return this +} -DN.prototype.pop = function dnPop() { - return this.rdns.pop(); -}; +DN.prototype.pop = function dnPop () { + return this.rdns.pop() +} -DN.prototype.push = function dnPush(rdn) { - assert.object(rdn, 'rdn (RDN) required'); +DN.prototype.push = function dnPush (rdn) { + assert.object(rdn, 'rdn (RDN) required') - return this.rdns.push(rdn); -}; + return this.rdns.push(rdn) +} -DN.prototype.shift = function dnShift() { - return this.rdns.shift(); -}; +DN.prototype.shift = function dnShift () { + return this.rdns.shift() +} -DN.prototype.unshift = function dnUnshift(rdn) { - assert.object(rdn, 'rdn (RDN) required'); +DN.prototype.unshift = function dnUnshift (rdn) { + assert.object(rdn, 'rdn (RDN) required') - return this.rdns.unshift(rdn); -}; + return this.rdns.unshift(rdn) +} -DN.isDN = function isDN(dn) { +DN.isDN = function isDN (dn) { if (!dn || typeof (dn) !== 'object') { - return false; + return false } if (dn instanceof DN) { - return true; + return true } if (Array.isArray(dn.rdns)) { // Really simple duck-typing for now - return true; + return true } - return false; -}; + return false +} - -///--- Exports +/// --- Exports module.exports = { parse: parse, DN: DN, RDN: RDN -}; +} diff --git a/lib/dtrace.js b/lib/dtrace.js index 1666d85..8c088bb 100644 --- a/lib/dtrace.js +++ b/lib/dtrace.js @@ -1,12 +1,10 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved.s +/// --- Globals - -///--- Globals - -var SERVER_PROVIDER; -var DTRACE_ID = 0; -var MAX_INT = 4294967295; +var SERVER_PROVIDER +var DTRACE_ID = 0 +var MAX_INT = 4294967295 /* * Args: @@ -37,7 +35,7 @@ var SERVER_PROBES = { // 4: attribute, 5: value 'server-compare-start': ['int', 'char *', 'char *', 'char *', - 'char *', 'char *'], + 'char *', 'char *'], 'server-compare-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'], 'server-delete-start': ['int', 'char *', 'char *', 'char *'], @@ -45,7 +43,7 @@ var SERVER_PROBES = { // 4: requestName, 5: requestValue 'server-exop-start': ['int', 'char *', 'char *', 'char *', 'char *', - 'char *'], + 'char *'], 'server-exop-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'], // 4: changes.length @@ -54,13 +52,13 @@ var SERVER_PROBES = { // 4: newRdn, 5: newSuperior 'server-modifydn-start': ['int', 'char *', 'char *', 'char *', 'char *', - 'char *'], + 'char *'], 'server-modifydn-done': ['int', 'char *', 'char *', 'char *', 'int', - 'char *'], + 'char *'], // 4: scope, 5: filter 'server-search-start': ['int', 'char *', 'char *', 'char *', 'char *', - 'char *'], + 'char *'], 'server-search-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'], // Last two are searchEntry.DN and seachEntry.attributes.length 'server-search-entry': ['int', 'char *', 'char *', 'char *', 'char *', 'int'], @@ -73,52 +71,50 @@ var SERVER_PROBES = { // remote IP 'server-connection': ['char *'] -}; +} +/// --- API -///--- API - -module.exports = function () { +module.exports = (function () { if (!SERVER_PROVIDER) { try { - var dtrace = require('dtrace-provider'); - SERVER_PROVIDER = dtrace.createDTraceProvider('ldapjs'); + var dtrace = require('dtrace-provider') + SERVER_PROVIDER = dtrace.createDTraceProvider('ldapjs') Object.keys(SERVER_PROBES).forEach(function (p) { - var args = SERVER_PROBES[p].splice(0); - args.unshift(p); + var args = SERVER_PROBES[p].splice(0) + args.unshift(p) - dtrace.DTraceProvider.prototype.addProbe.apply(SERVER_PROVIDER, args); - }); + dtrace.DTraceProvider.prototype.addProbe.apply(SERVER_PROVIDER, args) + }) } catch (e) { SERVER_PROVIDER = { - fire: function () { - }, - enable: function () { - }, - addProbe: function () { - var p = { - fire: function () { - } - }; - return (p); - }, - removeProbe: function () { - }, - disable: function () { + fire: function () { + }, + enable: function () { + }, + addProbe: function () { + var p = { + fire: function () { + } } - }; + return (p) + }, + removeProbe: function () { + }, + disable: function () { + } + } } - SERVER_PROVIDER.enable(); + SERVER_PROVIDER.enable() SERVER_PROVIDER._nextId = function () { - if (DTRACE_ID === MAX_INT) - DTRACE_ID = 0; + if (DTRACE_ID === MAX_INT) { DTRACE_ID = 0 } - return ++DTRACE_ID; - }; + return ++DTRACE_ID + } } - return SERVER_PROVIDER; -}(); + return SERVER_PROVIDER +}()) diff --git a/lib/errors/codes.js b/lib/errors/codes.js index 4021a42..c64b285 100644 --- a/lib/errors/codes.js +++ b/lib/errors/codes.js @@ -1,4 +1,4 @@ -// Copyright 2014 Joyent, Inc. All rights reserved. +'use strict' module.exports = { LDAP_SUCCESS: 0, @@ -41,4 +41,4 @@ module.exports = { LDAP_AFFECTS_MULTIPLE_DSAS: 71, LDAP_OTHER: 80, LDAP_PROXIED_AUTHORIZATION_DENIED: 123 -}; +} diff --git a/lib/errors/index.js b/lib/errors/index.js index 774cf44..015d435 100644 --- a/lib/errors/index.js +++ b/lib/errors/index.js @@ -1,151 +1,144 @@ -// Copyright 2011 Mark Cavage, Inc. All rights reserved. +'use strict' -var util = require('util'); -var assert = require('assert-plus'); +var util = require('util') +var assert = require('assert-plus') -var LDAPResult = require('../messages').LDAPResult; +var LDAPResult = require('../messages').LDAPResult +/// --- Globals -///--- Globals +var CODES = require('./codes') +var ERRORS = [] -var CODES = require('./codes'); -var ERRORS = []; +/// --- Error Base class +function LDAPError (message, dn, caller) { + if (Error.captureStackTrace) { Error.captureStackTrace(this, caller || LDAPError) } -///--- Error Base class - -function LDAPError(message, dn, caller) { - if (Error.captureStackTrace) - Error.captureStackTrace(this, caller || LDAPError); - - this.lde_message = message; - this.lde_dn = dn; + this.lde_message = message + this.lde_dn = dn } -util.inherits(LDAPError, Error); +util.inherits(LDAPError, Error) Object.defineProperties(LDAPError.prototype, { name: { - get: function getName() { return 'LDAPError'; }, + get: function getName () { return 'LDAPError' }, configurable: false }, code: { - get: function getCode() { return CODES.LDAP_OTHER; }, + get: function getCode () { return CODES.LDAP_OTHER }, configurable: false }, message: { - get: function getMessage() { - return this.lde_message || this.name; + get: function getMessage () { + return this.lde_message || this.name }, configurable: false }, dn: { - get: function getDN() { - return (this.lde_dn ? this.lde_dn.toString() : ''); + get: function getDN () { + return (this.lde_dn ? this.lde_dn.toString() : '') }, configurable: false } -}); +}) +/// --- Exported API -///--- Exported API - -module.exports = {}; -module.exports.LDAPError = LDAPError; +module.exports = {} +module.exports.LDAPError = LDAPError // Some whacky games here to make sure all the codes are exported Object.keys(CODES).forEach(function (code) { - module.exports[code] = CODES[code]; - if (code === 'LDAP_SUCCESS') - return; + module.exports[code] = CODES[code] + if (code === 'LDAP_SUCCESS') { return } - var err = ''; - var msg = ''; - var pieces = code.split('_').slice(1); + var err = '' + var msg = '' + var pieces = code.split('_').slice(1) for (var i = 0; i < pieces.length; i++) { - var lc = pieces[i].toLowerCase(); - var key = lc.charAt(0).toUpperCase() + lc.slice(1); - err += key; - msg += key + ((i + 1) < pieces.length ? ' ' : ''); + var lc = pieces[i].toLowerCase() + var key = lc.charAt(0).toUpperCase() + lc.slice(1) + err += key + msg += key + ((i + 1) < pieces.length ? ' ' : '') } - if (!/\w+Error$/.test(err)) - err += 'Error'; + if (!/\w+Error$/.test(err)) { err += 'Error' } // At this point LDAP_OPERATIONS_ERROR is now OperationsError in $err // and 'Operations Error' in $msg module.exports[err] = function (message, dn, caller) { - LDAPError.call(this, message, dn, caller || module.exports[err]); - }; - module.exports[err].constructor = module.exports[err]; - util.inherits(module.exports[err], LDAPError); + LDAPError.call(this, message, dn, caller || module.exports[err]) + } + module.exports[err].constructor = module.exports[err] + util.inherits(module.exports[err], LDAPError) Object.defineProperties(module.exports[err].prototype, { name: { - get: function getName() { return err; }, + get: function getName () { return err }, configurable: false }, code: { - get: function getCode() { return CODES[code]; }, + get: function getCode () { return CODES[code] }, configurable: false } - }); + }) ERRORS[CODES[code]] = { err: err, message: msg - }; -}); + } +}) module.exports.getError = function (res) { - assert.ok(res instanceof LDAPResult, 'res (LDAPResult) required'); + assert.ok(res instanceof LDAPResult, 'res (LDAPResult) required') - var errObj = ERRORS[res.status]; - var E = module.exports[errObj.err]; + var errObj = ERRORS[res.status] + var E = module.exports[errObj.err] return new E(res.errorMessage || errObj.message, - res.matchedDN || null, - module.exports.getError); -}; + res.matchedDN || null, + module.exports.getError) +} module.exports.getMessage = function (code) { - assert.number(code, 'code (number) required'); + assert.number(code, 'code (number) required') - var errObj = ERRORS[code]; - return (errObj && errObj.message ? errObj.message : ''); -}; - - -///--- Custom application errors - -function ConnectionError(message) { - LDAPError.call(this, message, null, ConnectionError); + var errObj = ERRORS[code] + return (errObj && errObj.message ? errObj.message : '') } -util.inherits(ConnectionError, LDAPError); -module.exports.ConnectionError = ConnectionError; + +/// --- Custom application errors + +function ConnectionError (message) { + LDAPError.call(this, message, null, ConnectionError) +} +util.inherits(ConnectionError, LDAPError) +module.exports.ConnectionError = ConnectionError Object.defineProperties(ConnectionError.prototype, { name: { - get: function () { return 'ConnectionError'; }, + get: function () { return 'ConnectionError' }, configurable: false } -}); +}) -function AbandonedError(message) { - LDAPError.call(this, message, null, AbandonedError); +function AbandonedError (message) { + LDAPError.call(this, message, null, AbandonedError) } -util.inherits(AbandonedError, LDAPError); -module.exports.AbandonedError = AbandonedError; +util.inherits(AbandonedError, LDAPError) +module.exports.AbandonedError = AbandonedError Object.defineProperties(AbandonedError.prototype, { name: { - get: function () { return 'AbandonedError'; }, + get: function () { return 'AbandonedError' }, configurable: false } -}); +}) -function TimeoutError(message) { - LDAPError.call(this, message, null, TimeoutError); +function TimeoutError (message) { + LDAPError.call(this, message, null, TimeoutError) } -util.inherits(TimeoutError, LDAPError); -module.exports.TimeoutError = TimeoutError; +util.inherits(TimeoutError, LDAPError) +module.exports.TimeoutError = TimeoutError Object.defineProperties(TimeoutError.prototype, { name: { - get: function () { return 'TimeoutError'; }, + get: function () { return 'TimeoutError' }, configurable: false } -}); +}) diff --git a/lib/filters/and_filter.js b/lib/filters/and_filter.js index 2b7e73c..9708af2 100644 --- a/lib/filters/and_filter.js +++ b/lib/filters/and_filter.js @@ -1,30 +1,27 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API - -///--- API - -function AndFilter(options) { - parents.AndFilter.call(this, options); +function AndFilter (options) { + parents.AndFilter.call(this, options) } -util.inherits(AndFilter, parents.AndFilter); -Filter.mixin(AndFilter); -module.exports = AndFilter; - +util.inherits(AndFilter, parents.AndFilter) +Filter.mixin(AndFilter) +module.exports = AndFilter AndFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) this.filters.forEach(function (f) { - ber = f.toBer(ber); - }); + ber = f.toBer(ber) + }) - return ber; -}; + return ber +} diff --git a/lib/filters/approx_filter.js b/lib/filters/approx_filter.js index 2a7a1f1..34fdbd2 100644 --- a/lib/filters/approx_filter.js +++ b/lib/filters/approx_filter.js @@ -1,39 +1,35 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API - -///--- API - -function ApproximateFilter(options) { - parents.ApproximateFilter.call(this, options); +function ApproximateFilter (options) { + parents.ApproximateFilter.call(this, options) } -util.inherits(ApproximateFilter, parents.ApproximateFilter); -Filter.mixin(ApproximateFilter); -module.exports = ApproximateFilter; - +util.inherits(ApproximateFilter, parents.ApproximateFilter) +Filter.mixin(ApproximateFilter) +module.exports = ApproximateFilter ApproximateFilter.prototype.parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.attribute = ber.readString().toLowerCase(); - this.value = ber.readString(); - - return true; -}; + this.attribute = ber.readString().toLowerCase() + this.value = ber.readString() + return true +} ApproximateFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.attribute); - ber.writeString(this.value); + ber.writeString(this.attribute) + ber.writeString(this.value) - return ber; -}; + return ber +} diff --git a/lib/filters/equality_filter.js b/lib/filters/equality_filter.js index dd5edea..09fb216 100644 --- a/lib/filters/equality_filter.js +++ b/lib/filters/equality_filter.js @@ -1,66 +1,60 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var ASN1 = require('asn1').Ber; -var parents = require('ldap-filter'); +var ASN1 = require('asn1').Ber +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API - -///--- API - -function EqualityFilter(options) { - parents.EqualityFilter.call(this, options); +function EqualityFilter (options) { + parents.EqualityFilter.call(this, options) } -util.inherits(EqualityFilter, parents.EqualityFilter); -Filter.mixin(EqualityFilter); -module.exports = EqualityFilter; - +util.inherits(EqualityFilter, parents.EqualityFilter) +Filter.mixin(EqualityFilter) +module.exports = EqualityFilter EqualityFilter.prototype.matches = function (target, strictAttrCase) { - assert.object(target, 'target'); + assert.object(target, 'target') - var tv = parents.getAttrValue(target, this.attribute, strictAttrCase); - var value = this.value; + var tv = parents.getAttrValue(target, this.attribute, strictAttrCase) + var value = this.value if (this.attribute.toLowerCase() === 'objectclass') { /* * Perform case-insensitive match for objectClass since nearly every LDAP * implementation behaves in this manner. */ - value = value.toLowerCase(); + value = value.toLowerCase() return parents.testValues(function (v) { - return value === v.toLowerCase(); - }, tv); + return value === v.toLowerCase() + }, tv) } else { return parents.testValues(function (v) { - return value === v; - }, tv); + return value === v + }, tv) } -}; - +} EqualityFilter.prototype.parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.attribute = ber.readString().toLowerCase(); - this.value = ber.readString(ASN1.OctetString, true); + this.attribute = ber.readString().toLowerCase() + this.value = ber.readString(ASN1.OctetString, true) - if (this.attribute === 'objectclass') - this.value = this.value.toLowerCase(); - - return true; -}; + if (this.attribute === 'objectclass') { this.value = this.value.toLowerCase() } + return true +} EqualityFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.attribute); - ber.writeBuffer(this.raw, ASN1.OctetString); + ber.writeString(this.attribute) + ber.writeBuffer(this.raw, ASN1.OctetString) - return ber; -}; + return ber +} diff --git a/lib/filters/escape.js b/lib/filters/escape.js index c9aea4e..2d4da3d 100644 --- a/lib/filters/escape.js +++ b/lib/filters/escape.js @@ -14,32 +14,31 @@ */ exports.escape = function (inp) { if (typeof (inp) === 'string') { - var esc = ''; + var esc = '' for (var i = 0; i < inp.length; i++) { switch (inp[i]) { case '*': - esc += '\\2a'; - break; + esc += '\\2a' + break case '(': - esc += '\\28'; - break; + esc += '\\28' + break case ')': - esc += '\\29'; - break; + esc += '\\29' + break case '\\': - esc += '\\5c'; - break; + esc += '\\5c' + break case '\0': - esc += '\\00'; - break; + esc += '\\00' + break default: - esc += inp[i]; - break; + esc += inp[i] + break } } - return esc; - + return esc } else { - return inp; + return inp } -}; +} diff --git a/lib/filters/ext_filter.js b/lib/filters/ext_filter.js index c3ffe7e..e96ebdd 100644 --- a/lib/filters/ext_filter.js +++ b/lib/filters/ext_filter.js @@ -1,66 +1,59 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); - -var parents = require('ldap-filter'); - -var Filter = require('./filter'); +var assert = require('assert') +var util = require('util') +var parents = require('ldap-filter') +var Filter = require('./filter') // THIS IS A STUB! // // ldapjs does not support server side extensible matching. // This class exists only for the client to send them. -///--- API +/// --- API -function ExtensibleFilter(options) { - parents.ExtensibleFilter.call(this, options); +function ExtensibleFilter (options) { + parents.ExtensibleFilter.call(this, options) } -util.inherits(ExtensibleFilter, parents.ExtensibleFilter); -Filter.mixin(ExtensibleFilter); -module.exports = ExtensibleFilter; - +util.inherits(ExtensibleFilter, parents.ExtensibleFilter) +Filter.mixin(ExtensibleFilter) +module.exports = ExtensibleFilter ExtensibleFilter.prototype.parse = function (ber) { - var end = ber.offset + ber.length; + var end = ber.offset + ber.length while (ber.offset < end) { - var tag = ber.peek(); + var tag = ber.peek() switch (tag) { - case 0x81: - this.rule = ber.readString(tag); - break; - case 0x82: - this.matchType = ber.readString(tag); - break; - case 0x83: - this.value = ber.readString(tag); - break; - case 0x84: - this.dnAttributes = ber.readBoolean(tag); - break; - default: - throw new Error('Invalid ext_match filter type: 0x' + tag.toString(16)); + case 0x81: + this.rule = ber.readString(tag) + break + case 0x82: + this.matchType = ber.readString(tag) + break + case 0x83: + this.value = ber.readString(tag) + break + case 0x84: + this.dnAttributes = ber.readBoolean(tag) + break + default: + throw new Error('Invalid ext_match filter type: 0x' + tag.toString(16)) } } - return true; -}; - + return true +} ExtensibleFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (this.rule) - ber.writeString(this.rule, 0x81); - if (this.matchType) - ber.writeString(this.matchType, 0x82); + if (this.rule) { ber.writeString(this.rule, 0x81) } + if (this.matchType) { ber.writeString(this.matchType, 0x82) } - ber.writeString(this.value, 0x83); - if (this.dnAttributes) - ber.writeBoolean(this.dnAttributes, 0x84); + ber.writeString(this.value, 0x83) + if (this.dnAttributes) { ber.writeBoolean(this.dnAttributes, 0x84) } - return ber; -}; + return ber +} diff --git a/lib/filters/filter.js b/lib/filters/filter.js index 60e2551..4c7e4ba 100644 --- a/lib/filters/filter.js +++ b/lib/filters/filter.js @@ -1,58 +1,55 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); +// var assert = require('assert') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var Protocol = require('../protocol'); +var Protocol = require('../protocol') +/// --- Globals -///--- Globals - -var BerWriter = asn1.BerWriter; +var BerWriter = asn1.BerWriter var TYPES = { - 'and': Protocol.FILTER_AND, - 'or': Protocol.FILTER_OR, - 'not': Protocol.FILTER_NOT, - 'equal': Protocol.FILTER_EQUALITY, - 'substring': Protocol.FILTER_SUBSTRINGS, - 'ge': Protocol.FILTER_GE, - 'le': Protocol.FILTER_LE, - 'present': Protocol.FILTER_PRESENT, - 'approx': Protocol.FILTER_APPROX, - 'ext': Protocol.FILTER_EXT -}; + and: Protocol.FILTER_AND, + or: Protocol.FILTER_OR, + not: Protocol.FILTER_NOT, + equal: Protocol.FILTER_EQUALITY, + substring: Protocol.FILTER_SUBSTRINGS, + ge: Protocol.FILTER_GE, + le: Protocol.FILTER_LE, + present: Protocol.FILTER_PRESENT, + approx: Protocol.FILTER_APPROX, + ext: Protocol.FILTER_EXT +} +/// --- API -///--- API - -function isFilter(filter) { +function isFilter (filter) { if (!filter || typeof (filter) !== 'object') { - return false; + return false } // Do our best to duck-type it if (typeof (filter.toBer) === 'function' && typeof (filter.matches) === 'function' && TYPES[filter.type] !== undefined) { - return true; + return true } - return false; + return false } -function mixin(target) { - target.prototype.toBer = function toBer(ber) { - if (!ber || !(ber instanceof BerWriter)) - throw new TypeError('ber (BerWriter) required'); +function mixin (target) { + target.prototype.toBer = function toBer (ber) { + if (!ber || !(ber instanceof BerWriter)) { throw new TypeError('ber (BerWriter) required') } - ber.startSequence(TYPES[this.type]); - ber = this._toBer(ber); - ber.endSequence(); - return ber; - }; + ber.startSequence(TYPES[this.type]) + ber = this._toBer(ber) + ber.endSequence() + return ber + } } module.exports = { isFilter: isFilter, mixin: mixin -}; +} diff --git a/lib/filters/ge_filter.js b/lib/filters/ge_filter.js index 6f10c70..324b856 100644 --- a/lib/filters/ge_filter.js +++ b/lib/filters/ge_filter.js @@ -1,38 +1,35 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API -///--- API - -function GreaterThanEqualsFilter(options) { - parents.GreaterThanEqualsFilter.call(this, options); +function GreaterThanEqualsFilter (options) { + parents.GreaterThanEqualsFilter.call(this, options) } -util.inherits(GreaterThanEqualsFilter, parents.GreaterThanEqualsFilter); -Filter.mixin(GreaterThanEqualsFilter); -module.exports = GreaterThanEqualsFilter; - +util.inherits(GreaterThanEqualsFilter, parents.GreaterThanEqualsFilter) +Filter.mixin(GreaterThanEqualsFilter) +module.exports = GreaterThanEqualsFilter GreaterThanEqualsFilter.prototype.parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.attribute = ber.readString().toLowerCase(); - this.value = ber.readString(); - - return true; -}; + this.attribute = ber.readString().toLowerCase() + this.value = ber.readString() + return true +} GreaterThanEqualsFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.attribute); - ber.writeString(this.value); + ber.writeString(this.attribute) + ber.writeString(this.value) - return ber; -}; + return ber +} diff --git a/lib/filters/index.js b/lib/filters/index.js index e44e305..75774e2 100644 --- a/lib/filters/index.js +++ b/lib/filters/index.js @@ -1,33 +1,30 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); +var assert = require('assert') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Protocol = require('../protocol'); +var Protocol = require('../protocol') -var Filter = require('./filter'); -var AndFilter = require('./and_filter'); -var ApproximateFilter = require('./approx_filter'); -var EqualityFilter = require('./equality_filter'); -var ExtensibleFilter = require('./ext_filter'); -var GreaterThanEqualsFilter = require('./ge_filter'); -var LessThanEqualsFilter = require('./le_filter'); -var NotFilter = require('./not_filter'); -var OrFilter = require('./or_filter'); -var PresenceFilter = require('./presence_filter'); -var SubstringFilter = require('./substr_filter'); +var Filter = require('./filter') +var AndFilter = require('./and_filter') +var ApproximateFilter = require('./approx_filter') +var EqualityFilter = require('./equality_filter') +var ExtensibleFilter = require('./ext_filter') +var GreaterThanEqualsFilter = require('./ge_filter') +var LessThanEqualsFilter = require('./le_filter') +var NotFilter = require('./not_filter') +var OrFilter = require('./or_filter') +var PresenceFilter = require('./presence_filter') +var SubstringFilter = require('./substr_filter') +/// --- Globals +var BerReader = asn1.BerReader -///--- Globals - -var BerReader = asn1.BerReader; - - -///--- Internal Parsers +/// --- Internal Parsers /* * A filter looks like this coming in: @@ -62,144 +59,138 @@ var BerReader = asn1.BerReader; * dnAttributes [4] BOOLEAN DEFAULT FALSE * } */ -function _parse(ber) { - assert.ok(ber); +function _parse (ber) { + assert.ok(ber) - function parseSet(f) { - var end = ber.offset + ber.length; - while (ber.offset < end) - f.addFilter(_parse(ber)); + function parseSet (f) { + var end = ber.offset + ber.length + while (ber.offset < end) { f.addFilter(_parse(ber)) } } - var f; + var f - var type = ber.readSequence(); + var type = ber.readSequence() switch (type) { + case Protocol.FILTER_AND: + f = new AndFilter() + parseSet(f) + break - case Protocol.FILTER_AND: - f = new AndFilter(); - parseSet(f); - break; + case Protocol.FILTER_APPROX: + f = new ApproximateFilter() + f.parse(ber) + break - case Protocol.FILTER_APPROX: - f = new ApproximateFilter(); - f.parse(ber); - break; + case Protocol.FILTER_EQUALITY: + f = new EqualityFilter() + f.parse(ber) + return f - case Protocol.FILTER_EQUALITY: - f = new EqualityFilter(); - f.parse(ber); - return f; + case Protocol.FILTER_EXT: + f = new ExtensibleFilter() + f.parse(ber) + return f - case Protocol.FILTER_EXT: - f = new ExtensibleFilter(); - f.parse(ber); - return f; + case Protocol.FILTER_GE: + f = new GreaterThanEqualsFilter() + f.parse(ber) + return f - case Protocol.FILTER_GE: - f = new GreaterThanEqualsFilter(); - f.parse(ber); - return f; + case Protocol.FILTER_LE: + f = new LessThanEqualsFilter() + f.parse(ber) + return f - case Protocol.FILTER_LE: - f = new LessThanEqualsFilter(); - f.parse(ber); - return f; + case Protocol.FILTER_NOT: + var _f = _parse(ber) + f = new NotFilter({ + filter: _f + }) + break - case Protocol.FILTER_NOT: - var _f = _parse(ber); - f = new NotFilter({ - filter: _f - }); - break; + case Protocol.FILTER_OR: + f = new OrFilter() + parseSet(f) + break - case Protocol.FILTER_OR: - f = new OrFilter(); - parseSet(f); - break; + case Protocol.FILTER_PRESENT: + f = new PresenceFilter() + f.parse(ber) + break - case Protocol.FILTER_PRESENT: - f = new PresenceFilter(); - f.parse(ber); - break; + case Protocol.FILTER_SUBSTRINGS: + f = new SubstringFilter() + f.parse(ber) + break - case Protocol.FILTER_SUBSTRINGS: - f = new SubstringFilter(); - f.parse(ber); - break; - - default: - throw new Error('Invalid search filter type: 0x' + type.toString(16)); + default: + throw new Error('Invalid search filter type: 0x' + type.toString(16)) } - - assert.ok(f); - return f; + assert.ok(f) + return f } - -function cloneFilter(input) { - var child; +function cloneFilter (input) { + var child if (input.type === 'and' || input.type === 'or') { - child = input.filters.map(cloneFilter); + child = input.filters.map(cloneFilter) } else if (input.type === 'not') { - child = cloneFilter(input.filter); + child = cloneFilter(input.filter) } switch (input.type) { - case 'and': - return new AndFilter({filters: child}); - case 'or': - return new OrFilter({filters: child}); - case 'not': - return new NotFilter({filter: child}); - case 'equal': - return new EqualityFilter(input); - case 'substring': - return new SubstringFilter(input); - case 'ge': - return new GreaterThanEqualsFilter(input); - case 'le': - return new LessThanEqualsFilter(input); - case 'present': - return new PresenceFilter(input); - case 'approx': - return new ApproximateFilter(input); - case 'ext': - return new ExtensibleFilter(input); - default: - throw new Error('invalid filter type:' + input.type); + case 'and': + return new AndFilter({ filters: child }) + case 'or': + return new OrFilter({ filters: child }) + case 'not': + return new NotFilter({ filter: child }) + case 'equal': + return new EqualityFilter(input) + case 'substring': + return new SubstringFilter(input) + case 'ge': + return new GreaterThanEqualsFilter(input) + case 'le': + return new LessThanEqualsFilter(input) + case 'present': + return new PresenceFilter(input) + case 'approx': + return new ApproximateFilter(input) + case 'ext': + return new ExtensibleFilter(input) + default: + throw new Error('invalid filter type:' + input.type) } } -function escapedToHex(str) { +function escapedToHex (str) { return str.replace(/\\([0-9a-f][^0-9a-f]|[0-9a-f]$|[^0-9a-f]|$)/gi, function (match, p1) { if (!p1) { - return '\\5c'; + return '\\5c' } - const hexCode = p1.charCodeAt(0).toString(16); - const rest = p1.substring(1); - return '\\' + hexCode + rest; - }); + const hexCode = p1.charCodeAt(0).toString(16) + const rest = p1.substring(1) + return '\\' + hexCode + rest + }) } -function parseString(str) { - const hexStr = escapedToHex(str); - const generic = parents.parse(hexStr); +function parseString (str) { + const hexStr = escapedToHex(str) + const generic = parents.parse(hexStr) // The filter object(s) return from ldap-filter.parse lack the toBer/parse // decoration that native ldapjs filter possess. cloneFilter adds that back. - return cloneFilter(generic); + return cloneFilter(generic) } - -///--- API +/// --- API module.exports = { parse: function (ber) { - if (!ber || !(ber instanceof BerReader)) - throw new TypeError('ber (BerReader) required'); + if (!ber || !(ber instanceof BerReader)) { throw new TypeError('ber (BerReader) required') } - return _parse(ber); + return _parse(ber) }, parseString: parseString, @@ -216,4 +207,4 @@ module.exports = { OrFilter: OrFilter, PresenceFilter: PresenceFilter, SubstringFilter: SubstringFilter -}; +} diff --git a/lib/filters/le_filter.js b/lib/filters/le_filter.js index f3b9b7b..0b98335 100644 --- a/lib/filters/le_filter.js +++ b/lib/filters/le_filter.js @@ -1,38 +1,35 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API -///--- API - -function LessThanEqualsFilter(options) { - parents.LessThanEqualsFilter.call(this, options); +function LessThanEqualsFilter (options) { + parents.LessThanEqualsFilter.call(this, options) } -util.inherits(LessThanEqualsFilter, parents.LessThanEqualsFilter); -Filter.mixin(LessThanEqualsFilter); -module.exports = LessThanEqualsFilter; - +util.inherits(LessThanEqualsFilter, parents.LessThanEqualsFilter) +Filter.mixin(LessThanEqualsFilter) +module.exports = LessThanEqualsFilter LessThanEqualsFilter.prototype.parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.attribute = ber.readString().toLowerCase(); - this.value = ber.readString(); - - return true; -}; + this.attribute = ber.readString().toLowerCase() + this.value = ber.readString() + return true +} LessThanEqualsFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.attribute); - ber.writeString(this.value); + ber.writeString(this.attribute) + ber.writeString(this.value) - return ber; -}; + return ber +} diff --git a/lib/filters/not_filter.js b/lib/filters/not_filter.js index 4656ca7..eee9519 100644 --- a/lib/filters/not_filter.js +++ b/lib/filters/not_filter.js @@ -1,25 +1,23 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API -///--- API - -function NotFilter(options) { - parents.NotFilter.call(this, options); +function NotFilter (options) { + parents.NotFilter.call(this, options) } -util.inherits(NotFilter, parents.NotFilter); -Filter.mixin(NotFilter); -module.exports = NotFilter; - +util.inherits(NotFilter, parents.NotFilter) +Filter.mixin(NotFilter) +module.exports = NotFilter NotFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - return this.filter.toBer(ber); -}; + return this.filter.toBer(ber) +} diff --git a/lib/filters/or_filter.js b/lib/filters/or_filter.js index 4218a7f..13a054e 100644 --- a/lib/filters/or_filter.js +++ b/lib/filters/or_filter.js @@ -1,29 +1,27 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API -///--- API - -function OrFilter(options) { - parents.OrFilter.call(this, options); +function OrFilter (options) { + parents.OrFilter.call(this, options) } -util.inherits(OrFilter, parents.OrFilter); -Filter.mixin(OrFilter); -module.exports = OrFilter; - +util.inherits(OrFilter, parents.OrFilter) +Filter.mixin(OrFilter) +module.exports = OrFilter OrFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) this.filters.forEach(function (f) { - ber = f.toBer(ber); - }); + ber = f.toBer(ber) + }) - return ber; -}; + return ber +} diff --git a/lib/filters/presence_filter.js b/lib/filters/presence_filter.js index cdd0a3f..3307f63 100644 --- a/lib/filters/presence_filter.js +++ b/lib/filters/presence_filter.js @@ -1,40 +1,36 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API -///--- API - -function PresenceFilter(options) { - parents.PresenceFilter.call(this, options); +function PresenceFilter (options) { + parents.PresenceFilter.call(this, options) } -util.inherits(PresenceFilter, parents.PresenceFilter); -Filter.mixin(PresenceFilter); -module.exports = PresenceFilter; - +util.inherits(PresenceFilter, parents.PresenceFilter) +Filter.mixin(PresenceFilter) +module.exports = PresenceFilter PresenceFilter.prototype.parse = function (ber) { - assert.ok(ber); + assert.ok(ber) this.attribute = - ber.buffer.slice(0, ber.length).toString('utf8').toLowerCase(); + ber.buffer.slice(0, ber.length).toString('utf8').toLowerCase() - ber._offset += ber.length; - - return true; -}; + ber._offset += ber.length + return true +} PresenceFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - for (var i = 0; i < this.attribute.length; i++) - ber.writeByte(this.attribute.charCodeAt(i)); + for (var i = 0; i < this.attribute.length; i++) { ber.writeByte(this.attribute.charCodeAt(i)) } - return ber; -}; + return ber +} diff --git a/lib/filters/substr_filter.js b/lib/filters/substr_filter.js index 04e5a7e..c926db4 100644 --- a/lib/filters/substr_filter.js +++ b/lib/filters/substr_filter.js @@ -1,76 +1,69 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var util = require('util'); +var assert = require('assert') +var util = require('util') -var parents = require('ldap-filter'); +var parents = require('ldap-filter') -var Filter = require('./filter'); +var Filter = require('./filter') +/// --- API -///--- API - -function SubstringFilter(options) { - parents.SubstringFilter.call(this, options); +function SubstringFilter (options) { + parents.SubstringFilter.call(this, options) } -util.inherits(SubstringFilter, parents.SubstringFilter); -Filter.mixin(SubstringFilter); -module.exports = SubstringFilter; - +util.inherits(SubstringFilter, parents.SubstringFilter) +Filter.mixin(SubstringFilter) +module.exports = SubstringFilter SubstringFilter.prototype.parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.attribute = ber.readString().toLowerCase(); - ber.readSequence(); - var end = ber.offset + ber.length; + this.attribute = ber.readString().toLowerCase() + ber.readSequence() + var end = ber.offset + ber.length while (ber.offset < end) { - var tag = ber.peek(); + var tag = ber.peek() switch (tag) { - case 0x80: // Initial - this.initial = ber.readString(tag); - if (this.attribute === 'objectclass') - this.initial = this.initial.toLowerCase(); - break; - case 0x81: // Any - var anyVal = ber.readString(tag); - if (this.attribute === 'objectclass') - anyVal = anyVal.toLowerCase(); - this.any.push(anyVal); - break; - case 0x82: // Final - this.final = ber.readString(tag); - if (this.attribute === 'objectclass') - this.final = this.final.toLowerCase(); - break; - default: - throw new Error('Invalid substrings filter type: 0x' + tag.toString(16)); + case 0x80: // Initial + this.initial = ber.readString(tag) + if (this.attribute === 'objectclass') { this.initial = this.initial.toLowerCase() } + break + case 0x81: // Any + var anyVal = ber.readString(tag) + if (this.attribute === 'objectclass') { anyVal = anyVal.toLowerCase() } + this.any.push(anyVal) + break + case 0x82: // Final + this.final = ber.readString(tag) + if (this.attribute === 'objectclass') { this.final = this.final.toLowerCase() } + break + default: + throw new Error('Invalid substrings filter type: 0x' + tag.toString(16)) } } - return true; -}; - + return true +} SubstringFilter.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.attribute); - ber.startSequence(); + ber.writeString(this.attribute) + ber.startSequence() - if (this.initial) - ber.writeString(this.initial, 0x80); + if (this.initial) { ber.writeString(this.initial, 0x80) } - if (this.any && this.any.length) + if (this.any && this.any.length) { this.any.forEach(function (s) { - ber.writeString(s, 0x81); - }); + ber.writeString(s, 0x81) + }) + } - if (this.final) - ber.writeString(this.final, 0x82); + if (this.final) { ber.writeString(this.final, 0x82) } - ber.endSequence(); + ber.endSequence() - return ber; -}; + return ber +} diff --git a/lib/index.js b/lib/index.js index 0beb8b4..b8ee53c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,23 +1,24 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var logger = require('./logger'); +var logger = require('./logger') -var client = require('./client'); -var Attribute = require('./attribute'); -var Change = require('./change'); -var Protocol = require('./protocol'); -var Server = require('./server'); +var client = require('./client') +var Attribute = require('./attribute') +var Change = require('./change') +var Protocol = require('./protocol') +var Server = require('./server') -var controls = require('./controls'); -var persistentSearch = require('./persistent_search'); -var dn = require('./dn'); -var errors = require('./errors'); -var filters = require('./filters'); -var messages = require('./messages'); -var url = require('./url'); +var controls = require('./controls') +var persistentSearch = require('./persistent_search') +var dn = require('./dn') +var errors = require('./errors') +var filters = require('./filters') +var messages = require('./messages') +var url = require('./url') +const hasOwnProperty = (target, val) => Object.prototype.hasOwnProperty.call(target, val) -///--- API +/// --- API module.exports = { Client: client.Client, @@ -25,17 +26,15 @@ module.exports = { Server: Server, createServer: function (options) { - if (options === undefined) - options = {}; + if (options === undefined) { options = {} } - if (typeof (options) !== 'object') - throw new TypeError('options (object) required'); + if (typeof (options) !== 'object') { throw new TypeError('options (object) required') } if (!options.log) { - options.log = logger; + options.log = logger } - return new Server(options); + return new Server(options) }, Attribute: Attribute, @@ -54,37 +53,32 @@ module.exports = { url: url, parseURL: url.parse -}; +} +/// --- Export all the childrenz -///--- Export all the childrenz - -var k; +var k for (k in Protocol) { - if (Protocol.hasOwnProperty(k)) - module.exports[k] = Protocol[k]; + if (hasOwnProperty(Protocol, k)) { module.exports[k] = Protocol[k] } } for (k in messages) { - if (messages.hasOwnProperty(k)) - module.exports[k] = messages[k]; + if (hasOwnProperty(messages, k)) { module.exports[k] = messages[k] } } for (k in controls) { - if (controls.hasOwnProperty(k)) - module.exports[k] = controls[k]; + if (hasOwnProperty(controls, k)) { module.exports[k] = controls[k] } } for (k in filters) { - if (filters.hasOwnProperty(k)) { - if (k !== 'parse' && k !== 'parseString') - module.exports[k] = filters[k]; + if (hasOwnProperty(filters, k)) { + if (k !== 'parse' && k !== 'parseString') { module.exports[k] = filters[k] } } } for (k in errors) { - if (errors.hasOwnProperty(k)) { - module.exports[k] = errors[k]; + if (hasOwnProperty(errors, k)) { + module.exports[k] = errors[k] } } diff --git a/lib/logger.js b/lib/logger.js index 239d393..ad96ba4 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' const logger = Object.create(require('abstract-logging')) logger.child = function () { return logger } diff --git a/lib/messages/abandon_request.js b/lib/messages/abandon_request.js index 461ce49..2a25aaf 100644 --- a/lib/messages/abandon_request.js +++ b/lib/messages/abandon_request.js @@ -1,90 +1,87 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./message'); -var Protocol = require('../protocol'); +var LDAPMessage = require('./message') +var Protocol = require('../protocol') +/// --- API -///--- API +function AbandonRequest (options) { + options = options || {} + assert.object(options) + assert.optionalNumber(options.abandonID) -function AbandonRequest(options) { - options = options || {}; - assert.object(options); - assert.optionalNumber(options.abandonID); + options.protocolOp = Protocol.LDAP_REQ_ABANDON + LDAPMessage.call(this, options) - options.protocolOp = Protocol.LDAP_REQ_ABANDON; - LDAPMessage.call(this, options); - - this.abandonID = options.abandonID || 0; + this.abandonID = options.abandonID || 0 } -util.inherits(AbandonRequest, LDAPMessage); +util.inherits(AbandonRequest, LDAPMessage) Object.defineProperties(AbandonRequest.prototype, { type: { - get: function getType() { return 'AbandonRequest'; }, + get: function getType () { return 'AbandonRequest' }, configurable: false } -}); +}) AbandonRequest.prototype._parse = function (ber, length) { - assert.ok(ber); - assert.ok(length); + assert.ok(ber) + assert.ok(length) // What a PITA - have to replicate ASN.1 integer logic to work around the // way abandon is encoded and the way ldapjs framework handles "normal" // messages - var buf = ber.buffer; - var offset = 0; - var value = 0; + var buf = ber.buffer + var offset = 0 + var value = 0 - var fb = buf[offset++]; - value = fb & 0x7F; + var fb = buf[offset++] + value = fb & 0x7F for (var i = 1; i < length; i++) { - value <<= 8; - value |= (buf[offset++] & 0xff); + value <<= 8 + value |= (buf[offset++] & 0xff) } - if ((fb & 0x80) == 0x80) - value = -value; + if ((fb & 0x80) === 0x80) { value = -value } - ber._offset += length; + ber._offset += length - this.abandonID = value; + this.abandonID = value - return true; -}; + return true +} AbandonRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - var i = this.abandonID; - var sz = 4; + var i = this.abandonID + var sz = 4 while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000)) && (sz > 1)) { - sz--; - i <<= 8; + sz-- + i <<= 8 } - assert.ok(sz <= 4); + assert.ok(sz <= 4) while (sz-- > 0) { - ber.writeByte((i & 0xff000000) >> 24); - i <<= 8; + ber.writeByte((i & 0xff000000) >> 24) + i <<= 8 } - return ber; -}; + return ber +} AbandonRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.abandonID = this.abandonID; + j.abandonID = this.abandonID - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = AbandonRequest; +module.exports = AbandonRequest diff --git a/lib/messages/abandon_response.js b/lib/messages/abandon_response.js index 534c218..7926ab7 100644 --- a/lib/messages/abandon_response.js +++ b/lib/messages/abandon_response.js @@ -1,36 +1,34 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./result'); -var Protocol = require('../protocol'); +var LDAPMessage = require('./result') +// var Protocol = require('../protocol') +/// --- API -///--- API +function AbandonResponse (options) { + options = options || {} + assert.object(options) -function AbandonResponse(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = 0; - LDAPMessage.call(this, options); + options.protocolOp = 0 + LDAPMessage.call(this, options) } -util.inherits(AbandonResponse, LDAPMessage); +util.inherits(AbandonResponse, LDAPMessage) Object.defineProperties(AbandonResponse.prototype, { type: { - get: function getType() { return 'AbandonResponse'; }, + get: function getType () { return 'AbandonResponse' }, configurable: false } -}); +}) -AbandonResponse.prototype.end = function (status) {}; +AbandonResponse.prototype.end = function (status) {} AbandonResponse.prototype._json = function (j) { - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = AbandonResponse; +module.exports = AbandonResponse diff --git a/lib/messages/add_request.js b/lib/messages/add_request.js index e1d4bdd..21eba1a 100644 --- a/lib/messages/add_request.js +++ b/lib/messages/add_request.js @@ -1,130 +1,122 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./message'); -var Attribute = require('../attribute'); -var Protocol = require('../protocol'); -var lassert = require('../assert'); +var LDAPMessage = require('./message') +var Attribute = require('../attribute') +var Protocol = require('../protocol') +var lassert = require('../assert') +/// --- API -///--- API +function AddRequest (options) { + options = options || {} + assert.object(options) + lassert.optionalStringDN(options.entry) + lassert.optionalArrayOfAttribute(options.attributes) -function AddRequest(options) { - options = options || {}; - assert.object(options); - lassert.optionalStringDN(options.entry); - lassert.optionalArrayOfAttribute(options.attributes); + options.protocolOp = Protocol.LDAP_REQ_ADD + LDAPMessage.call(this, options) - options.protocolOp = Protocol.LDAP_REQ_ADD; - LDAPMessage.call(this, options); - - this.entry = options.entry || null; - this.attributes = options.attributes ? options.attributes.slice(0) : []; + this.entry = options.entry || null + this.attributes = options.attributes ? options.attributes.slice(0) : [] } -util.inherits(AddRequest, LDAPMessage); +util.inherits(AddRequest, LDAPMessage) Object.defineProperties(AddRequest.prototype, { type: { - get: function getType() { return 'AddRequest'; }, + get: function getType () { return 'AddRequest' }, configurable: false }, _dn: { - get: function getDN() { return this.entry; }, + get: function getDN () { return this.entry }, configurable: false } -}); +}) AddRequest.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.entry = ber.readString(); + this.entry = ber.readString() - ber.readSequence(); + ber.readSequence() - var end = ber.offset + ber.length; + var end = ber.offset + ber.length while (ber.offset < end) { - var a = new Attribute(); - a.parse(ber); - a.type = a.type.toLowerCase(); + var a = new Attribute() + a.parse(ber) + a.type = a.type.toLowerCase() if (a.type === 'objectclass') { - for (var i = 0; i < a.vals.length; i++) - a.vals[i] = a.vals[i].toLowerCase(); + for (var i = 0; i < a.vals.length; i++) { a.vals[i] = a.vals[i].toLowerCase() } } - this.attributes.push(a); + this.attributes.push(a) } - this.attributes.sort(Attribute.compare); - return true; -}; + this.attributes.sort(Attribute.compare) + return true +} AddRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.entry.toString()); - ber.startSequence(); + ber.writeString(this.entry.toString()) + ber.startSequence() this.attributes.forEach(function (a) { - a.toBer(ber); - }); - ber.endSequence(); + a.toBer(ber) + }) + ber.endSequence() - return ber; -}; + return ber +} AddRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.entry = this.entry.toString(); - j.attributes = []; + j.entry = this.entry.toString() + j.attributes = [] this.attributes.forEach(function (a) { - j.attributes.push(a.json); - }); + j.attributes.push(a.json) + }) - return j; -}; + return j +} AddRequest.prototype.indexOf = function (attr) { - if (!attr || typeof (attr) !== 'string') - throw new TypeError('attr (string) required'); + if (!attr || typeof (attr) !== 'string') { throw new TypeError('attr (string) required') } for (var i = 0; i < this.attributes.length; i++) { - if (this.attributes[i].type === attr) - return i; + if (this.attributes[i].type === attr) { return i } } - return -1; -}; + return -1 +} AddRequest.prototype.attributeNames = function () { - var attrs = []; + var attrs = [] - for (var i = 0; i < this.attributes.length; i++) - attrs.push(this.attributes[i].type.toLowerCase()); + for (var i = 0; i < this.attributes.length; i++) { attrs.push(this.attributes[i].type.toLowerCase()) } - return attrs; -}; + return attrs +} AddRequest.prototype.getAttribute = function (name) { - if (!name || typeof (name) !== 'string') - throw new TypeError('attribute name (string) required'); + if (!name || typeof (name) !== 'string') { throw new TypeError('attribute name (string) required') } - name = name.toLowerCase(); + name = name.toLowerCase() for (var i = 0; i < this.attributes.length; i++) { - if (this.attributes[i].type === name) - return this.attributes[i]; + if (this.attributes[i].type === name) { return this.attributes[i] } } - return null; -}; + return null +} AddRequest.prototype.addAttribute = function (attr) { - if (!(attr instanceof Attribute)) - throw new TypeError('attribute (Attribute) required'); + if (!(attr instanceof Attribute)) { throw new TypeError('attribute (Attribute) required') } - return this.attributes.push(attr); -}; + return this.attributes.push(attr) +} /** * Returns a "pure" JS representation of this object. @@ -142,30 +134,26 @@ AddRequest.prototype.addAttribute = function (attr) { * @return {Object} that looks like the above. */ AddRequest.prototype.toObject = function () { - var self = this; + var self = this var obj = { dn: self.entry ? self.entry.toString() : '', attributes: {} - }; + } - if (!this.attributes || !this.attributes.length) - return obj; + if (!this.attributes || !this.attributes.length) { return obj } this.attributes.forEach(function (a) { - if (!obj.attributes[a.type]) - obj.attributes[a.type] = []; + if (!obj.attributes[a.type]) { obj.attributes[a.type] = [] } a.vals.forEach(function (v) { - if (obj.attributes[a.type].indexOf(v) === -1) - obj.attributes[a.type].push(v); - }); - }); + if (obj.attributes[a.type].indexOf(v) === -1) { obj.attributes[a.type].push(v) } + }) + }) - return obj; -}; + return obj +} +/// --- Exports -///--- Exports - -module.exports = AddRequest; +module.exports = AddRequest diff --git a/lib/messages/add_response.js b/lib/messages/add_response.js index 2163552..8520162 100644 --- a/lib/messages/add_response.js +++ b/lib/messages/add_response.js @@ -1,24 +1,22 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPResult = require('./result'); -var Protocol = require('../protocol'); +var LDAPResult = require('./result') +var Protocol = require('../protocol') +/// --- API -///--- API +function AddResponse (options) { + options = options || {} + assert.object(options) -function AddResponse(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REP_ADD; - LDAPResult.call(this, options); + options.protocolOp = Protocol.LDAP_REP_ADD + LDAPResult.call(this, options) } -util.inherits(AddResponse, LDAPResult); +util.inherits(AddResponse, LDAPResult) +/// --- Exports -///--- Exports - -module.exports = AddResponse; +module.exports = AddResponse diff --git a/lib/messages/bind_request.js b/lib/messages/bind_request.js index ca99ddf..a55b971 100644 --- a/lib/messages/bind_request.js +++ b/lib/messages/bind_request.js @@ -1,88 +1,84 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var LDAPMessage = require('./message'); -var Protocol = require('../protocol'); +var LDAPMessage = require('./message') +var Protocol = require('../protocol') +/// --- Globals -///--- Globals +var Ber = asn1.Ber +var LDAP_BIND_SIMPLE = 'simple' +// var LDAP_BIND_SASL = 'sasl' -var Ber = asn1.Ber; -var LDAP_BIND_SIMPLE = 'simple'; -var LDAP_BIND_SASL = 'sasl'; +/// --- API +function BindRequest (options) { + options = options || {} + assert.object(options) -///--- API + options.protocolOp = Protocol.LDAP_REQ_BIND + LDAPMessage.call(this, options) -function BindRequest(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REQ_BIND; - LDAPMessage.call(this, options); - - this.version = options.version || 0x03; - this.name = options.name || null; - this.authentication = options.authentication || LDAP_BIND_SIMPLE; - this.credentials = options.credentials || ''; + this.version = options.version || 0x03 + this.name = options.name || null + this.authentication = options.authentication || LDAP_BIND_SIMPLE + this.credentials = options.credentials || '' } -util.inherits(BindRequest, LDAPMessage); +util.inherits(BindRequest, LDAPMessage) Object.defineProperties(BindRequest.prototype, { type: { - get: function getType() { return 'BindRequest'; }, + get: function getType () { return 'BindRequest' }, configurable: false }, _dn: { - get: function getDN() { return this.name; }, + get: function getDN () { return this.name }, configurable: false } -}); +}) BindRequest.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.version = ber.readInt(); - this.name = ber.readString(); + this.version = ber.readInt() + this.name = ber.readString() - var t = ber.peek(); + var t = ber.peek() // TODO add support for SASL et al - if (t !== Ber.Context) - throw new Error('authentication 0x' + t.toString(16) + ' not supported'); + if (t !== Ber.Context) { throw new Error('authentication 0x' + t.toString(16) + ' not supported') } - this.authentication = LDAP_BIND_SIMPLE; - this.credentials = ber.readString(Ber.Context); + this.authentication = LDAP_BIND_SIMPLE + this.credentials = ber.readString(Ber.Context) - return true; -}; + return true +} BindRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeInt(this.version); - ber.writeString((this.name || '').toString()); + ber.writeInt(this.version) + ber.writeString((this.name || '').toString()) // TODO add support for SASL et al - ber.writeString((this.credentials || ''), Ber.Context); + ber.writeString((this.credentials || ''), Ber.Context) - return ber; -}; + return ber +} BindRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.version = this.version; - j.name = this.name; - j.authenticationType = this.authentication; - j.credentials = this.credentials; + j.version = this.version + j.name = this.name + j.authenticationType = this.authentication + j.credentials = this.credentials - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = BindRequest; +module.exports = BindRequest diff --git a/lib/messages/bind_response.js b/lib/messages/bind_response.js index 8542613..2b7813f 100644 --- a/lib/messages/bind_response.js +++ b/lib/messages/bind_response.js @@ -1,24 +1,22 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPResult = require('./result'); -var Protocol = require('../protocol'); +var LDAPResult = require('./result') +var Protocol = require('../protocol') +/// --- API -///--- API +function BindResponse (options) { + options = options || {} + assert.object(options) -function BindResponse(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REP_BIND; - LDAPResult.call(this, options); + options.protocolOp = Protocol.LDAP_REP_BIND + LDAPResult.call(this, options) } -util.inherits(BindResponse, LDAPResult); +util.inherits(BindResponse, LDAPResult) +/// --- Exports -///--- Exports - -module.exports = BindResponse; +module.exports = BindResponse diff --git a/lib/messages/compare_request.js b/lib/messages/compare_request.js index 9b7e2fe..5029546 100644 --- a/lib/messages/compare_request.js +++ b/lib/messages/compare_request.js @@ -1,76 +1,74 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./message'); -var Protocol = require('../protocol'); -var lassert = require('../assert'); +var LDAPMessage = require('./message') +var Protocol = require('../protocol') +var lassert = require('../assert') +/// --- API -///--- API +function CompareRequest (options) { + options = options || {} + assert.object(options) + assert.optionalString(options.attribute) + assert.optionalString(options.value) + lassert.optionalStringDN(options.entry) -function CompareRequest(options) { - options = options || {}; - assert.object(options); - assert.optionalString(options.attribute); - assert.optionalString(options.value); - lassert.optionalStringDN(options.entry); + options.protocolOp = Protocol.LDAP_REQ_COMPARE + LDAPMessage.call(this, options) - options.protocolOp = Protocol.LDAP_REQ_COMPARE; - LDAPMessage.call(this, options); - - this.entry = options.entry || null; - this.attribute = options.attribute || ''; - this.value = options.value || ''; + this.entry = options.entry || null + this.attribute = options.attribute || '' + this.value = options.value || '' } -util.inherits(CompareRequest, LDAPMessage); +util.inherits(CompareRequest, LDAPMessage) Object.defineProperties(CompareRequest.prototype, { type: { - get: function getType() { return 'CompareRequest'; }, + get: function getType () { return 'CompareRequest' }, configurable: false }, _dn: { - get: function getDN() { return this.entry; }, + get: function getDN () { return this.entry }, configurable: false } -}); +}) CompareRequest.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.entry = ber.readString(); + this.entry = ber.readString() - ber.readSequence(); - this.attribute = ber.readString().toLowerCase(); - this.value = ber.readString(); + ber.readSequence() + this.attribute = ber.readString().toLowerCase() + this.value = ber.readString() - return true; -}; + return true +} CompareRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.entry.toString()); - ber.startSequence(); - ber.writeString(this.attribute); - ber.writeString(this.value); - ber.endSequence(); + ber.writeString(this.entry.toString()) + ber.startSequence() + ber.writeString(this.attribute) + ber.writeString(this.value) + ber.endSequence() - return ber; -}; + return ber +} CompareRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.entry = this.entry.toString(); - j.attribute = this.attribute; - j.value = this.value; + j.entry = this.entry.toString() + j.attribute = this.attribute + j.value = this.value - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = CompareRequest; +module.exports = CompareRequest diff --git a/lib/messages/compare_response.js b/lib/messages/compare_response.js index 4f949d4..ee35bfa 100644 --- a/lib/messages/compare_response.js +++ b/lib/messages/compare_response.js @@ -1,36 +1,33 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPResult = require('./result'); -var Protocol = require('../protocol'); +var LDAPResult = require('./result') +var Protocol = require('../protocol') +/// --- API -///--- API +function CompareResponse (options) { + options = options || {} + assert.object(options) -function CompareResponse(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REP_COMPARE; - LDAPResult.call(this, options); + options.protocolOp = Protocol.LDAP_REP_COMPARE + LDAPResult.call(this, options) } -util.inherits(CompareResponse, LDAPResult); +util.inherits(CompareResponse, LDAPResult) CompareResponse.prototype.end = function (matches) { - var status = 0x06; + var status = 0x06 if (typeof (matches) === 'boolean') { - if (!matches) - status = 0x05; // Compare false + if (!matches) { status = 0x05 } // Compare false } else { - status = matches; + status = matches } - return LDAPResult.prototype.end.call(this, status); -}; + return LDAPResult.prototype.end.call(this, status) +} +/// --- Exports -///--- Exports - -module.exports = CompareResponse; +module.exports = CompareResponse diff --git a/lib/messages/del_request.js b/lib/messages/del_request.js index 2b97be2..4fb9028 100644 --- a/lib/messages/del_request.js +++ b/lib/messages/del_request.js @@ -1,65 +1,62 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./message'); -var Protocol = require('../protocol'); -var lassert = require('../assert'); +var LDAPMessage = require('./message') +var Protocol = require('../protocol') +var lassert = require('../assert') +/// --- API -///--- API +function DeleteRequest (options) { + options = options || {} + assert.object(options) + lassert.optionalStringDN(options.entry) -function DeleteRequest(options) { - options = options || {}; - assert.object(options); - lassert.optionalStringDN(options.entry); + options.protocolOp = Protocol.LDAP_REQ_DELETE + LDAPMessage.call(this, options) - options.protocolOp = Protocol.LDAP_REQ_DELETE; - LDAPMessage.call(this, options); - - this.entry = options.entry || null; + this.entry = options.entry || null } -util.inherits(DeleteRequest, LDAPMessage); +util.inherits(DeleteRequest, LDAPMessage) Object.defineProperties(DeleteRequest.prototype, { type: { - get: function getType() { return 'DeleteRequest'; }, + get: function getType () { return 'DeleteRequest' }, configurable: false }, _dn: { - get: function getDN() { return this.entry; }, + get: function getDN () { return this.entry }, configurable: false } -}); +}) DeleteRequest.prototype._parse = function (ber, length) { - assert.ok(ber); + assert.ok(ber) - this.entry = ber.buffer.slice(0, length).toString('utf8'); - ber._offset += ber.length; + this.entry = ber.buffer.slice(0, length).toString('utf8') + ber._offset += ber.length - return true; -}; + return true +} DeleteRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - var buf = Buffer.from(this.entry.toString()); - for (var i = 0; i < buf.length; i++) - ber.writeByte(buf[i]); + var buf = Buffer.from(this.entry.toString()) + for (var i = 0; i < buf.length; i++) { ber.writeByte(buf[i]) } - return ber; -}; + return ber +} DeleteRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.entry = this.entry; + j.entry = this.entry - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = DeleteRequest; +module.exports = DeleteRequest diff --git a/lib/messages/del_response.js b/lib/messages/del_response.js index f42322f..7e8c953 100644 --- a/lib/messages/del_response.js +++ b/lib/messages/del_response.js @@ -1,24 +1,22 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPResult = require('./result'); -var Protocol = require('../protocol'); +var LDAPResult = require('./result') +var Protocol = require('../protocol') +/// --- API -///--- API +function DeleteResponse (options) { + options = options || {} + assert.object(options) -function DeleteResponse(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REP_DELETE; - LDAPResult.call(this, options); + options.protocolOp = Protocol.LDAP_REP_DELETE + LDAPResult.call(this, options) } -util.inherits(DeleteResponse, LDAPResult); +util.inherits(DeleteResponse, LDAPResult) +/// --- Exports -///--- Exports - -module.exports = DeleteResponse; +module.exports = DeleteResponse diff --git a/lib/messages/ext_request.js b/lib/messages/ext_request.js index 1c464bf..b719825 100644 --- a/lib/messages/ext_request.js +++ b/lib/messages/ext_request.js @@ -1,120 +1,116 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./message'); -var Protocol = require('../protocol'); +var LDAPMessage = require('./message') +var Protocol = require('../protocol') +/// --- API -///--- API - -function ExtendedRequest(options) { - options = options || {}; - assert.object(options); - assert.optionalString(options.requestName); +function ExtendedRequest (options) { + options = options || {} + assert.object(options) + assert.optionalString(options.requestName) if (options.requestValue && !(Buffer.isBuffer(options.requestValue) || typeof (options.requestValue) === 'string')) { - throw new TypeError('options.requestValue must be a buffer or a string'); + throw new TypeError('options.requestValue must be a buffer or a string') } - options.protocolOp = Protocol.LDAP_REQ_EXTENSION; - LDAPMessage.call(this, options); + options.protocolOp = Protocol.LDAP_REQ_EXTENSION + LDAPMessage.call(this, options) - this.requestName = options.requestName || ''; - this.requestValue = options.requestValue; + this.requestName = options.requestName || '' + this.requestValue = options.requestValue - if(Buffer.isBuffer(this.requestValue)) { - this.requestValueBuffer = this.requestValue; + if (Buffer.isBuffer(this.requestValue)) { + this.requestValueBuffer = this.requestValue } else { - this.requestValueBuffer = Buffer.from(this.requestValue || '', 'utf8'); + this.requestValueBuffer = Buffer.from(this.requestValue || '', 'utf8') } } -util.inherits(ExtendedRequest, LDAPMessage); +util.inherits(ExtendedRequest, LDAPMessage) Object.defineProperties(ExtendedRequest.prototype, { type: { - get: function getType() { return 'ExtendedRequest'; }, + get: function getType () { return 'ExtendedRequest' }, configurable: false }, _dn: { - get: function getDN() { return this.requestName; }, + get: function getDN () { return this.requestName }, configurable: false }, name: { - get: function getName() { return this.requestName; }, - set: function setName(val) { - assert.string(val); - this.requestName = val; + get: function getName () { return this.requestName }, + set: function setName (val) { + assert.string(val) + this.requestName = val }, configurable: false }, value: { - get: function getValue() { return this.requestValue; }, - set: function setValue(val) { - if (!(Buffer.isBuffer(val) || typeof (val) === 'string')) - throw new TypeError('value must be a buffer or a string'); + get: function getValue () { return this.requestValue }, + set: function setValue (val) { + if (!(Buffer.isBuffer(val) || typeof (val) === 'string')) { throw new TypeError('value must be a buffer or a string') } - if(Buffer.isBuffer(val)) { - this.requestValueBuffer = val; + if (Buffer.isBuffer(val)) { + this.requestValueBuffer = val } else { - this.requestValueBuffer = Buffer.from(val, 'utf8'); + this.requestValueBuffer = Buffer.from(val, 'utf8') } - this.requestValue = val; + this.requestValue = val }, configurable: false }, valueBuffer: { - get: function getValueBuffer() { - return this.requestValueBuffer; + get: function getValueBuffer () { + return this.requestValueBuffer }, - set: function setValueBuffer(val) { - if(!Buffer.isBuffer(val)) - throw new TypeError('valueBuffer must be a buffer'); + set: function setValueBuffer (val) { + if (!Buffer.isBuffer(val)) { throw new TypeError('valueBuffer must be a buffer') } - this.value = val; + this.value = val }, configurable: false } -}); +}) ExtendedRequest.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.requestName = ber.readString(0x80); + this.requestName = ber.readString(0x80) if (ber.peek() === 0x81) { - this.requestValueBuffer = ber.readString(0x81, true); - this.requestValue = this.requestValueBuffer.toString('utf8'); + this.requestValueBuffer = ber.readString(0x81, true) + this.requestValue = this.requestValueBuffer.toString('utf8') } - return true; -}; + return true +} ExtendedRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.requestName, 0x80); + ber.writeString(this.requestName, 0x80) if (Buffer.isBuffer(this.requestValue)) { - ber.writeBuffer(this.requestValue, 0x81); + ber.writeBuffer(this.requestValue, 0x81) } else if (typeof (this.requestValue) === 'string') { - ber.writeString(this.requestValue, 0x81); + ber.writeString(this.requestValue, 0x81) } - return ber; -}; + return ber +} ExtendedRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.requestName = this.requestName; - j.requestValue = (Buffer.isBuffer(this.requestValue)) ? - this.requestValue.toString('hex') : this.requestValue; + j.requestName = this.requestName + j.requestValue = (Buffer.isBuffer(this.requestValue)) + ? this.requestValue.toString('hex') : this.requestValue - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = ExtendedRequest; +module.exports = ExtendedRequest diff --git a/lib/messages/ext_response.js b/lib/messages/ext_response.js index 4e72d0a..9ecb9bb 100644 --- a/lib/messages/ext_response.js +++ b/lib/messages/ext_response.js @@ -1,94 +1,86 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPResult = require('./result'); -var Protocol = require('../protocol'); +var LDAPResult = require('./result') +var Protocol = require('../protocol') +/// --- API -///--- API +function ExtendedResponse (options) { + options = options || {} + assert.object(options) + assert.optionalString(options.responseName) + assert.optionalString(options.responsevalue) -function ExtendedResponse(options) { - options = options || {}; - assert.object(options); - assert.optionalString(options.responseName); - assert.optionalString(options.responsevalue); + this.responseName = options.responseName || undefined + this.responseValue = options.responseValue || undefined - this.responseName = options.responseName || undefined; - this.responseValue = options.responseValue || undefined; - - options.protocolOp = Protocol.LDAP_REP_EXTENSION; - LDAPResult.call(this, options); + options.protocolOp = Protocol.LDAP_REP_EXTENSION + LDAPResult.call(this, options) } -util.inherits(ExtendedResponse, LDAPResult); +util.inherits(ExtendedResponse, LDAPResult) Object.defineProperties(ExtendedResponse.prototype, { type: { - get: function getType() { return 'ExtendedResponse'; }, + get: function getType () { return 'ExtendedResponse' }, configurable: false }, _dn: { - get: function getDN() { return this.responseName; }, + get: function getDN () { return this.responseName }, configurable: false }, name: { - get: function getName() { return this.responseName; }, - set: function setName(val) { - assert.string(val); - this.responseName = val; + get: function getName () { return this.responseName }, + set: function setName (val) { + assert.string(val) + this.responseName = val }, configurable: false }, value: { - get: function getValue() { return this.responseValue; }, + get: function getValue () { return this.responseValue }, set: function (val) { - assert.string(val); - this.responseValue = val; + assert.string(val) + this.responseValue = val }, configurable: false } -}); +}) ExtendedResponse.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (!LDAPResult.prototype._parse.call(this, ber)) - return false; + if (!LDAPResult.prototype._parse.call(this, ber)) { return false } - if (ber.peek() === 0x8a) - this.responseName = ber.readString(0x8a); - if (ber.peek() === 0x8b) - this.responseValue = ber.readString(0x8b); + if (ber.peek() === 0x8a) { this.responseName = ber.readString(0x8a) } + if (ber.peek() === 0x8b) { this.responseValue = ber.readString(0x8b) } - return true; -}; + return true +} ExtendedResponse.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (!LDAPResult.prototype._toBer.call(this, ber)) - return false; + if (!LDAPResult.prototype._toBer.call(this, ber)) { return false } - if (this.responseName) - ber.writeString(this.responseName, 0x8a); - if (this.responseValue) - ber.writeString(this.responseValue, 0x8b); + if (this.responseName) { ber.writeString(this.responseName, 0x8a) } + if (this.responseValue) { ber.writeString(this.responseValue, 0x8b) } - return ber; -}; + return ber +} ExtendedResponse.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j = LDAPResult.prototype._json.call(this, j); + j = LDAPResult.prototype._json.call(this, j) - j.responseName = this.responseName; - j.responseValue = this.responseValue; + j.responseName = this.responseName + j.responseValue = this.responseValue - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = ExtendedResponse; +module.exports = ExtendedResponse diff --git a/lib/messages/index.js b/lib/messages/index.js index 3586377..59b562d 100644 --- a/lib/messages/index.js +++ b/lib/messages/index.js @@ -1,34 +1,33 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var LDAPMessage = require('./message'); -var LDAPResult = require('./result'); -var Parser = require('./parser'); +var LDAPMessage = require('./message') +var LDAPResult = require('./result') +var Parser = require('./parser') -var AbandonRequest = require('./abandon_request'); -var AbandonResponse = require('./abandon_response'); -var AddRequest = require('./add_request'); -var AddResponse = require('./add_response'); -var BindRequest = require('./bind_request'); -var BindResponse = require('./bind_response'); -var CompareRequest = require('./compare_request'); -var CompareResponse = require('./compare_response'); -var DeleteRequest = require('./del_request'); -var DeleteResponse = require('./del_response'); -var ExtendedRequest = require('./ext_request'); -var ExtendedResponse = require('./ext_response'); -var ModifyRequest = require('./modify_request'); -var ModifyResponse = require('./modify_response'); -var ModifyDNRequest = require('./moddn_request'); -var ModifyDNResponse = require('./moddn_response'); -var SearchRequest = require('./search_request'); -var SearchEntry = require('./search_entry'); -var SearchReference = require('./search_reference'); -var SearchResponse = require('./search_response'); -var UnbindRequest = require('./unbind_request'); -var UnbindResponse = require('./unbind_response'); +var AbandonRequest = require('./abandon_request') +var AbandonResponse = require('./abandon_response') +var AddRequest = require('./add_request') +var AddResponse = require('./add_response') +var BindRequest = require('./bind_request') +var BindResponse = require('./bind_response') +var CompareRequest = require('./compare_request') +var CompareResponse = require('./compare_response') +var DeleteRequest = require('./del_request') +var DeleteResponse = require('./del_response') +var ExtendedRequest = require('./ext_request') +var ExtendedResponse = require('./ext_response') +var ModifyRequest = require('./modify_request') +var ModifyResponse = require('./modify_response') +var ModifyDNRequest = require('./moddn_request') +var ModifyDNResponse = require('./moddn_response') +var SearchRequest = require('./search_request') +var SearchEntry = require('./search_entry') +var SearchReference = require('./search_reference') +var SearchResponse = require('./search_response') +var UnbindRequest = require('./unbind_request') +var UnbindResponse = require('./unbind_response') - -///--- API +/// --- API module.exports = { @@ -59,4 +58,4 @@ module.exports = { UnbindRequest: UnbindRequest, UnbindResponse: UnbindResponse -}; +} diff --git a/lib/messages/message.js b/lib/messages/message.js index 0495f05..06790ef 100644 --- a/lib/messages/message.js +++ b/lib/messages/message.js @@ -1,51 +1,48 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +var asn1 = require('asn1') var logger = require('../logger') -var Control = require('../controls').Control; -var Protocol = require('../protocol'); +// var Control = require('../controls').Control +// var Protocol = require('../protocol') +/// --- Globals -///--- Globals - -var Ber = asn1.Ber; -var BerReader = asn1.BerReader; -var BerWriter = asn1.BerWriter; -var getControl = require('../controls').getControl; - - -///--- API +// var Ber = asn1.Ber +// var BerReader = asn1.BerReader +var BerWriter = asn1.BerWriter +var getControl = require('../controls').getControl +/// --- API /** * LDAPMessage structure. * * @param {Object} options stuff. */ -function LDAPMessage(options) { - assert.object(options); +function LDAPMessage (options) { + assert.object(options) - this.messageID = options.messageID || 0; - this.protocolOp = options.protocolOp || undefined; - this.controls = options.controls ? options.controls.slice(0) : []; + this.messageID = options.messageID || 0 + this.protocolOp = options.protocolOp || undefined + this.controls = options.controls ? options.controls.slice(0) : [] - this.log = options.log || logger; + this.log = options.log || logger } Object.defineProperties(LDAPMessage.prototype, { id: { - get: function getId() { return this.messageID; }, + get: function getId () { return this.messageID }, configurable: false }, dn: { - get: function getDN() { return this._dn || ''; }, + get: function getDN () { return this._dn || '' }, configurable: false }, type: { - get: function getType() { return 'LDAPMessage'; }, + get: function getType () { return 'LDAPMessage' }, configurable: false }, json: { @@ -53,66 +50,61 @@ Object.defineProperties(LDAPMessage.prototype, { var out = this._json({ messageID: this.messageID, protocolOp: this.type - }); - out.controls = this.controls; - return out; + }) + out.controls = this.controls + return out }, configurable: false } -}); +}) LDAPMessage.prototype.toString = function () { - return JSON.stringify(this.json); -}; + return JSON.stringify(this.json) +} LDAPMessage.prototype.parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - if (this.log.trace()) - this.log.trace('parse: data=%s', util.inspect(ber.buffer)); + if (this.log.trace()) { this.log.trace('parse: data=%s', util.inspect(ber.buffer)) } // Delegate off to the specific type to parse - this._parse(ber, ber.length); + this._parse(ber, ber.length) // Look for controls if (ber.peek() === 0xa0) { - ber.readSequence(); - var end = ber.offset + ber.length; + ber.readSequence() + var end = ber.offset + ber.length while (ber.offset < end) { - var c = getControl(ber); - if (c) - this.controls.push(c); + var c = getControl(ber) + if (c) { this.controls.push(c) } } } - if (this.log.trace()) - this.log.trace('Parsing done: %j', this.json); - return true; -}; + if (this.log.trace()) { this.log.trace('Parsing done: %j', this.json) } + return true +} LDAPMessage.prototype.toBer = function () { - var writer = new BerWriter(); - writer.startSequence(); - writer.writeInt(this.messageID); + var writer = new BerWriter() + writer.startSequence() + writer.writeInt(this.messageID) - writer.startSequence(this.protocolOp); - if (this._toBer) - writer = this._toBer(writer); - writer.endSequence(); + writer.startSequence(this.protocolOp) + if (this._toBer) { writer = this._toBer(writer) } + writer.endSequence() if (this.controls && this.controls.length) { - writer.startSequence(0xa0); + writer.startSequence(0xa0) this.controls.forEach(function (c) { - c.toBer(writer); - }); - writer.endSequence(); + c.toBer(writer) + }) + writer.endSequence() } - writer.endSequence(); - return writer.buffer; -}; + writer.endSequence() + return writer.buffer +} +/// --- Exports -///--- Exports - -module.exports = LDAPMessage; +module.exports = LDAPMessage diff --git a/lib/messages/moddn_request.js b/lib/messages/moddn_request.js index 6a63156..3fafdff 100644 --- a/lib/messages/moddn_request.js +++ b/lib/messages/moddn_request.js @@ -1,88 +1,85 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./message'); -var Protocol = require('../protocol'); -var dn = require('../dn'); -var lassert = require('../assert'); +var LDAPMessage = require('./message') +var Protocol = require('../protocol') +var dn = require('../dn') +var lassert = require('../assert') +/// --- API -///--- API +function ModifyDNRequest (options) { + options = options || {} + assert.object(options) + assert.optionalBool(options.deleteOldRdn) + lassert.optionalStringDN(options.entry) + lassert.optionalDN(options.newRdn) + lassert.optionalDN(options.newSuperior) -function ModifyDNRequest(options) { - options = options || {}; - assert.object(options); - assert.optionalBool(options.deleteOldRdn); - lassert.optionalStringDN(options.entry); - lassert.optionalDN(options.newRdn); - lassert.optionalDN(options.newSuperior); + options.protocolOp = Protocol.LDAP_REQ_MODRDN + LDAPMessage.call(this, options) - options.protocolOp = Protocol.LDAP_REQ_MODRDN; - LDAPMessage.call(this, options); - - this.entry = options.entry || null; - this.newRdn = options.newRdn || null; - this.deleteOldRdn = options.deleteOldRdn || true; - this.newSuperior = options.newSuperior || null; + this.entry = options.entry || null + this.newRdn = options.newRdn || null + this.deleteOldRdn = options.deleteOldRdn || true + this.newSuperior = options.newSuperior || null } -util.inherits(ModifyDNRequest, LDAPMessage); +util.inherits(ModifyDNRequest, LDAPMessage) Object.defineProperties(ModifyDNRequest.prototype, { type: { - get: function getType() { return 'ModifyDNRequest'; }, + get: function getType () { return 'ModifyDNRequest' }, configurable: false }, _dn: { - get: function getDN() { return this.entry; }, + get: function getDN () { return this.entry }, configurable: false } -}); +}) ModifyDNRequest.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.entry = ber.readString(); - this.newRdn = dn.parse(ber.readString()); - this.deleteOldRdn = ber.readBoolean(); - if (ber.peek() === 0x80) - this.newSuperior = dn.parse(ber.readString(0x80)); + this.entry = ber.readString() + this.newRdn = dn.parse(ber.readString()) + this.deleteOldRdn = ber.readBoolean() + if (ber.peek() === 0x80) { this.newSuperior = dn.parse(ber.readString(0x80)) } - return true; -}; + return true +} ModifyDNRequest.prototype._toBer = function (ber) { - //assert.ok(ber); + // assert.ok(ber); - ber.writeString(this.entry.toString()); - ber.writeString(this.newRdn.toString()); - ber.writeBoolean(this.deleteOldRdn); + ber.writeString(this.entry.toString()) + ber.writeString(this.newRdn.toString()) + ber.writeBoolean(this.deleteOldRdn) if (this.newSuperior) { - var s = this.newSuperior.toString(); - var len = Buffer.byteLength(s); + var s = this.newSuperior.toString() + var len = Buffer.byteLength(s) - ber.writeByte(0x80); // MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG - ber.writeByte(len); - ber._ensure(len); - ber._buf.write(s, ber._offset); - ber._offset += len; + ber.writeByte(0x80) // MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG + ber.writeByte(len) + ber._ensure(len) + ber._buf.write(s, ber._offset) + ber._offset += len } - return ber; -}; + return ber +} ModifyDNRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.entry = this.entry.toString(); - j.newRdn = this.newRdn.toString(); - j.deleteOldRdn = this.deleteOldRdn; - j.newSuperior = this.newSuperior ? this.newSuperior.toString() : ''; + j.entry = this.entry.toString() + j.newRdn = this.newRdn.toString() + j.deleteOldRdn = this.deleteOldRdn + j.newSuperior = this.newSuperior ? this.newSuperior.toString() : '' - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = ModifyDNRequest; +module.exports = ModifyDNRequest diff --git a/lib/messages/moddn_response.js b/lib/messages/moddn_response.js index 57f245f..13cd25f 100644 --- a/lib/messages/moddn_response.js +++ b/lib/messages/moddn_response.js @@ -1,24 +1,22 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPResult = require('./result'); -var Protocol = require('../protocol'); +var LDAPResult = require('./result') +var Protocol = require('../protocol') +/// --- API -///--- API +function ModifyDNResponse (options) { + options = options || {} + assert.object(options) -function ModifyDNResponse(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REP_MODRDN; - LDAPResult.call(this, options); + options.protocolOp = Protocol.LDAP_REP_MODRDN + LDAPResult.call(this, options) } -util.inherits(ModifyDNResponse, LDAPResult); +util.inherits(ModifyDNResponse, LDAPResult) +/// --- Exports -///--- Exports - -module.exports = ModifyDNResponse; +module.exports = ModifyDNResponse diff --git a/lib/messages/modify_request.js b/lib/messages/modify_request.js index 38f70b3..b4bb4d0 100644 --- a/lib/messages/modify_request.js +++ b/lib/messages/modify_request.js @@ -1,85 +1,83 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./message'); -var Change = require('../change'); -var Protocol = require('../protocol'); -var lassert = require('../assert'); +var LDAPMessage = require('./message') +var Change = require('../change') +var Protocol = require('../protocol') +var lassert = require('../assert') +/// --- API -///--- API +function ModifyRequest (options) { + options = options || {} + assert.object(options) + lassert.optionalStringDN(options.object) + lassert.optionalArrayOfAttribute(options.attributes) -function ModifyRequest(options) { - options = options || {}; - assert.object(options); - lassert.optionalStringDN(options.object); - lassert.optionalArrayOfAttribute(options.attributes); + options.protocolOp = Protocol.LDAP_REQ_MODIFY + LDAPMessage.call(this, options) - options.protocolOp = Protocol.LDAP_REQ_MODIFY; - LDAPMessage.call(this, options); - - this.object = options.object || null; - this.changes = options.changes ? options.changes.slice(0) : []; + this.object = options.object || null + this.changes = options.changes ? options.changes.slice(0) : [] } -util.inherits(ModifyRequest, LDAPMessage); +util.inherits(ModifyRequest, LDAPMessage) Object.defineProperties(ModifyRequest.prototype, { type: { - get: function getType() { return 'ModifyRequest'; }, + get: function getType () { return 'ModifyRequest' }, configurable: false }, _dn: { - get: function getDN() { return this.object; }, + get: function getDN () { return this.object }, configurable: false } -}); +}) ModifyRequest.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.object = ber.readString(); + this.object = ber.readString() - ber.readSequence(); - var end = ber.offset + ber.length; + ber.readSequence() + var end = ber.offset + ber.length while (ber.offset < end) { - var c = new Change(); - c.parse(ber); - c.modification.type = c.modification.type.toLowerCase(); - this.changes.push(c); + var c = new Change() + c.parse(ber) + c.modification.type = c.modification.type.toLowerCase() + this.changes.push(c) } - this.changes.sort(Change.compare); - return true; -}; + this.changes.sort(Change.compare) + return true +} ModifyRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.object.toString()); - ber.startSequence(); + ber.writeString(this.object.toString()) + ber.startSequence() this.changes.forEach(function (c) { - c.toBer(ber); - }); - ber.endSequence(); + c.toBer(ber) + }) + ber.endSequence() - return ber; -}; + return ber +} ModifyRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.object = this.object; - j.changes = []; + j.object = this.object + j.changes = [] this.changes.forEach(function (c) { - j.changes.push(c.json); - }); + j.changes.push(c.json) + }) - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = ModifyRequest; +module.exports = ModifyRequest diff --git a/lib/messages/modify_response.js b/lib/messages/modify_response.js index 5e568fc..9822efc 100644 --- a/lib/messages/modify_response.js +++ b/lib/messages/modify_response.js @@ -1,24 +1,22 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPResult = require('./result'); -var Protocol = require('../protocol'); +var LDAPResult = require('./result') +var Protocol = require('../protocol') +/// --- API -///--- API +function ModifyResponse (options) { + options = options || {} + assert.object(options) -function ModifyResponse(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REP_MODIFY; - LDAPResult.call(this, options); + options.protocolOp = Protocol.LDAP_REP_MODIFY + LDAPResult.call(this, options) } -util.inherits(ModifyResponse, LDAPResult); +util.inherits(ModifyResponse, LDAPResult) +/// --- Exports -///--- Exports - -module.exports = ModifyResponse; +module.exports = ModifyResponse diff --git a/lib/messages/parser.js b/lib/messages/parser.js index b71543d..89b4f83 100644 --- a/lib/messages/parser.js +++ b/lib/messages/parser.js @@ -1,228 +1,221 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +var EventEmitter = require('events').EventEmitter +var util = require('util') -var assert = require('assert-plus'); -var asn1 = require('asn1'); -var VError = require('verror').VError; +var assert = require('assert-plus') +var asn1 = require('asn1') +// var VError = require('verror').VError var logger = require('../logger') -var AbandonRequest = require('./abandon_request'); -var AddRequest = require('./add_request'); -var AddResponse = require('./add_response'); -var BindRequest = require('./bind_request'); -var BindResponse = require('./bind_response'); -var CompareRequest = require('./compare_request'); -var CompareResponse = require('./compare_response'); -var DeleteRequest = require('./del_request'); -var DeleteResponse = require('./del_response'); -var ExtendedRequest = require('./ext_request'); -var ExtendedResponse = require('./ext_response'); -var ModifyRequest = require('./modify_request'); -var ModifyResponse = require('./modify_response'); -var ModifyDNRequest = require('./moddn_request'); -var ModifyDNResponse = require('./moddn_response'); -var SearchRequest = require('./search_request'); -var SearchEntry = require('./search_entry'); -var SearchReference = require('./search_reference'); -var SearchResponse = require('./search_response'); -var UnbindRequest = require('./unbind_request'); -var UnbindResponse = require('./unbind_response'); +var AbandonRequest = require('./abandon_request') +var AddRequest = require('./add_request') +var AddResponse = require('./add_response') +var BindRequest = require('./bind_request') +var BindResponse = require('./bind_response') +var CompareRequest = require('./compare_request') +var CompareResponse = require('./compare_response') +var DeleteRequest = require('./del_request') +var DeleteResponse = require('./del_response') +var ExtendedRequest = require('./ext_request') +var ExtendedResponse = require('./ext_response') +var ModifyRequest = require('./modify_request') +var ModifyResponse = require('./modify_response') +var ModifyDNRequest = require('./moddn_request') +var ModifyDNResponse = require('./moddn_response') +var SearchRequest = require('./search_request') +var SearchEntry = require('./search_entry') +var SearchReference = require('./search_reference') +var SearchResponse = require('./search_response') +var UnbindRequest = require('./unbind_request') +// var UnbindResponse = require('./unbind_response') -var LDAPResult = require('./result'); -var Message = require('./message'); +var LDAPResult = require('./result') +// var Message = require('./message') -var Protocol = require('../protocol'); +var Protocol = require('../protocol') +/// --- Globals -///--- Globals +// var Ber = asn1.Ber +var BerReader = asn1.BerReader -var Ber = asn1.Ber; -var BerReader = asn1.BerReader; +/// --- API +function Parser (options = {}) { + assert.object(options) -///--- API + EventEmitter.call(this) -function Parser(options = {}) { - assert.object(options); - - EventEmitter.call(this); - - this.buffer = null; - this.log = options.log || logger; + this.buffer = null + this.log = options.log || logger } -util.inherits(Parser, EventEmitter); +util.inherits(Parser, EventEmitter) Parser.prototype.write = function (data) { - if (!data || !Buffer.isBuffer(data)) - throw new TypeError('data (buffer) required'); + if (!data || !Buffer.isBuffer(data)) { throw new TypeError('data (buffer) required') } - var nextMessage = null; - var self = this; + var nextMessage = null + var self = this - function end() { - if (nextMessage) - return self.write(nextMessage); + function end () { + if (nextMessage) { return self.write(nextMessage) } - return true; + return true } - self.buffer = (self.buffer ? Buffer.concat([self.buffer, data]) : data); + self.buffer = (self.buffer ? Buffer.concat([self.buffer, data]) : data) - var ber = new BerReader(self.buffer); + var ber = new BerReader(self.buffer) - var foundSeq = false; + var foundSeq = false try { - foundSeq = ber.readSequence(); + foundSeq = ber.readSequence() } catch (e) { - this.emit('error', e); + this.emit('error', e) } if (!foundSeq || ber.remain < ber.length) { // ENOTENOUGH - return false; + return false } else if (ber.remain > ber.length) { // ETOOMUCH // This is sort of ugly, but allows us to make miminal copies - nextMessage = self.buffer.slice(ber.offset + ber.length); - ber._size = ber.offset + ber.length; - assert.equal(ber.remain, ber.length); + nextMessage = self.buffer.slice(ber.offset + ber.length) + ber._size = ber.offset + ber.length + assert.equal(ber.remain, ber.length) } // If we're here, ber holds the message, and nextMessage is temporarily // pointing at the next sequence of data (if it exists) - self.buffer = null; + self.buffer = null - var message; + var message try { // Bail here if peer isn't speaking protocol at all - message = this.getMessage(ber); + message = this.getMessage(ber) if (!message) { - return end(); + return end() } - message.parse(ber); + message.parse(ber) } catch (e) { - this.emit('error', e, message); - return false; + this.emit('error', e, message) + return false } - this.emit('message', message); - return end(); -}; + this.emit('message', message) + return end() +} Parser.prototype.getMessage = function (ber) { - assert.ok(ber); + assert.ok(ber) - var self = this; + var self = this - var messageID = ber.readInt(); - var type = ber.readSequence(); + var messageID = ber.readInt() + var type = ber.readSequence() - var Message; + var Message switch (type) { + case Protocol.LDAP_REQ_ABANDON: + Message = AbandonRequest + break - case Protocol.LDAP_REQ_ABANDON: - Message = AbandonRequest; - break; + case Protocol.LDAP_REQ_ADD: + Message = AddRequest + break - case Protocol.LDAP_REQ_ADD: - Message = AddRequest; - break; + case Protocol.LDAP_REP_ADD: + Message = AddResponse + break - case Protocol.LDAP_REP_ADD: - Message = AddResponse; - break; + case Protocol.LDAP_REQ_BIND: + Message = BindRequest + break - case Protocol.LDAP_REQ_BIND: - Message = BindRequest; - break; + case Protocol.LDAP_REP_BIND: + Message = BindResponse + break - case Protocol.LDAP_REP_BIND: - Message = BindResponse; - break; + case Protocol.LDAP_REQ_COMPARE: + Message = CompareRequest + break - case Protocol.LDAP_REQ_COMPARE: - Message = CompareRequest; - break; + case Protocol.LDAP_REP_COMPARE: + Message = CompareResponse + break - case Protocol.LDAP_REP_COMPARE: - Message = CompareResponse; - break; + case Protocol.LDAP_REQ_DELETE: + Message = DeleteRequest + break - case Protocol.LDAP_REQ_DELETE: - Message = DeleteRequest; - break; + case Protocol.LDAP_REP_DELETE: + Message = DeleteResponse + break - case Protocol.LDAP_REP_DELETE: - Message = DeleteResponse; - break; + case Protocol.LDAP_REQ_EXTENSION: + Message = ExtendedRequest + break - case Protocol.LDAP_REQ_EXTENSION: - Message = ExtendedRequest; - break; + case Protocol.LDAP_REP_EXTENSION: + Message = ExtendedResponse + break - case Protocol.LDAP_REP_EXTENSION: - Message = ExtendedResponse; - break; + case Protocol.LDAP_REQ_MODIFY: + Message = ModifyRequest + break - case Protocol.LDAP_REQ_MODIFY: - Message = ModifyRequest; - break; + case Protocol.LDAP_REP_MODIFY: + Message = ModifyResponse + break - case Protocol.LDAP_REP_MODIFY: - Message = ModifyResponse; - break; + case Protocol.LDAP_REQ_MODRDN: + Message = ModifyDNRequest + break - case Protocol.LDAP_REQ_MODRDN: - Message = ModifyDNRequest; - break; + case Protocol.LDAP_REP_MODRDN: + Message = ModifyDNResponse + break - case Protocol.LDAP_REP_MODRDN: - Message = ModifyDNResponse; - break; + case Protocol.LDAP_REQ_SEARCH: + Message = SearchRequest + break - case Protocol.LDAP_REQ_SEARCH: - Message = SearchRequest; - break; + case Protocol.LDAP_REP_SEARCH_ENTRY: + Message = SearchEntry + break - case Protocol.LDAP_REP_SEARCH_ENTRY: - Message = SearchEntry; - break; + case Protocol.LDAP_REP_SEARCH_REF: + Message = SearchReference + break - case Protocol.LDAP_REP_SEARCH_REF: - Message = SearchReference; - break; + case Protocol.LDAP_REP_SEARCH: + Message = SearchResponse + break - case Protocol.LDAP_REP_SEARCH: - Message = SearchResponse; - break; + case Protocol.LDAP_REQ_UNBIND: + Message = UnbindRequest + break - case Protocol.LDAP_REQ_UNBIND: - Message = UnbindRequest; - break; - - default: - this.emit('error', - new Error('Op 0x' + (type ? type.toString(16) : '??') + + default: + this.emit('error', + new Error('Op 0x' + (type ? type.toString(16) : '??') + ' not supported'), - new LDAPResult({ - messageID: messageID, - protocolOp: type || Protocol.LDAP_REP_EXTENSION - })); + new LDAPResult({ + messageID: messageID, + protocolOp: type || Protocol.LDAP_REP_EXTENSION + })) - return false; + return false } - return new Message({ messageID: messageID, log: self.log - }); -}; + }) +} +/// --- Exports -///--- Exports - -module.exports = Parser; +module.exports = Parser diff --git a/lib/messages/result.js b/lib/messages/result.js index c0987d1..d92cfef 100644 --- a/lib/messages/result.js +++ b/lib/messages/result.js @@ -1,65 +1,61 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +// var asn1 = require('asn1') -var dtrace = require('../dtrace'); -var LDAPMessage = require('./message'); -var Protocol = require('../protocol'); +var dtrace = require('../dtrace') +var LDAPMessage = require('./message') +var Protocol = require('../protocol') +/// --- Globals -///--- Globals +// var Ber = asn1.Ber +// var BerWriter = asn1.BerWriter -var Ber = asn1.Ber; -var BerWriter = asn1.BerWriter; +/// --- API +function LDAPResult (options) { + options = options || {} + assert.object(options) + assert.optionalNumber(options.status) + assert.optionalString(options.matchedDN) + assert.optionalString(options.errorMessage) + assert.optionalArrayOfString(options.referrals) -///--- API + LDAPMessage.call(this, options) -function LDAPResult(options) { - options = options || {}; - assert.object(options); - assert.optionalNumber(options.status); - assert.optionalString(options.matchedDN); - assert.optionalString(options.errorMessage); - assert.optionalArrayOfString(options.referrals); + this.status = options.status || 0 // LDAP SUCCESS + this.matchedDN = options.matchedDN || '' + this.errorMessage = options.errorMessage || '' + this.referrals = options.referrals || [] - LDAPMessage.call(this, options); - - this.status = options.status || 0; // LDAP SUCCESS - this.matchedDN = options.matchedDN || ''; - this.errorMessage = options.errorMessage || ''; - this.referrals = options.referrals || []; - - this.connection = options.connection || null; + this.connection = options.connection || null } -util.inherits(LDAPResult, LDAPMessage); +util.inherits(LDAPResult, LDAPMessage) Object.defineProperties(LDAPResult.prototype, { type: { - get: function getType() { return 'LDAPResult'; }, + get: function getType () { return 'LDAPResult' }, configurable: false } -}); +}) LDAPResult.prototype.end = function (status) { - assert.ok(this.connection); + assert.ok(this.connection) - if (typeof (status) === 'number') - this.status = status; + if (typeof (status) === 'number') { this.status = status } - var ber = this.toBer(); - if (this.log.debug()) - this.log.debug('%s: sending: %j', this.connection.ldap.id, this.json); + var ber = this.toBer() + if (this.log.debug()) { this.log.debug('%s: sending: %j', this.connection.ldap.id, this.json) } try { - var self = this; - this.connection.write(ber); + var self = this + this.connection.write(ber) if (self._dtraceOp && self._dtraceId) { dtrace.fire('server-' + self._dtraceOp + '-done', function () { - var c = self.connection || {ldap: {}}; + var c = self.connection || { ldap: {} } return [ self._dtraceId || 0, (c.remoteAddress || ''), @@ -67,63 +63,59 @@ LDAPResult.prototype.end = function (status) { (self.requestDN ? self.requestDN.toString() : ''), status || self.status, self.errorMessage - ]; - }); + ] + }) } - } catch (e) { this.log.warn(e, '%s failure to write message %j', - this.connection.ldap.id, this.json); + this.connection.ldap.id, this.json) } - -}; +} LDAPResult.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.status = ber.readEnumeration(); - this.matchedDN = ber.readString(); - this.errorMessage = ber.readString(); + this.status = ber.readEnumeration() + this.matchedDN = ber.readString() + this.errorMessage = ber.readString() - var t = ber.peek(); + var t = ber.peek() if (t === Protocol.LDAP_REP_REFERRAL) { - var end = ber.offset + ber.length; - while (ber.offset < end) - this.referrals.push(ber.readString()); + var end = ber.offset + ber.length + while (ber.offset < end) { this.referrals.push(ber.readString()) } } - return true; -}; + return true +} LDAPResult.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeEnumeration(this.status); - ber.writeString(this.matchedDN || ''); - ber.writeString(this.errorMessage || ''); + ber.writeEnumeration(this.status) + ber.writeString(this.matchedDN || '') + ber.writeString(this.errorMessage || '') if (this.referrals.length) { - ber.startSequence(Protocol.LDAP_REP_REFERRAL); - ber.writeStringArray(this.referrals); - ber.endSequence(); + ber.startSequence(Protocol.LDAP_REP_REFERRAL) + ber.writeStringArray(this.referrals) + ber.endSequence() } - return ber; -}; + return ber +} LDAPResult.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.status = this.status; - j.matchedDN = this.matchedDN; - j.errorMessage = this.errorMessage; - j.referrals = this.referrals; + j.status = this.status + j.matchedDN = this.matchedDN + j.errorMessage = this.errorMessage + j.referrals = this.referrals - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = LDAPResult; +module.exports = LDAPResult diff --git a/lib/messages/search_entry.js b/lib/messages/search_entry.js index 57b1458..b6ba798 100644 --- a/lib/messages/search_entry.js +++ b/lib/messages/search_entry.js @@ -1,196 +1,187 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +// var asn1 = require('asn1') -var LDAPMessage = require('./message'); -var Attribute = require('../attribute'); -var Protocol = require('../protocol'); -var lassert = require('../assert'); +var LDAPMessage = require('./message') +var Attribute = require('../attribute') +var Protocol = require('../protocol') +var lassert = require('../assert') +/// --- Globals -///--- Globals +// var BerWriter = asn1.BerWriter -var BerWriter = asn1.BerWriter; +/// --- API +function SearchEntry (options) { + options = options || {} + assert.object(options) + lassert.optionalStringDN(options.objectName) -///--- API + options.protocolOp = Protocol.LDAP_REP_SEARCH_ENTRY + LDAPMessage.call(this, options) -function SearchEntry(options) { - options = options || {}; - assert.object(options); - lassert.optionalStringDN(options.objectName); - - options.protocolOp = Protocol.LDAP_REP_SEARCH_ENTRY; - LDAPMessage.call(this, options); - - this.objectName = options.objectName || null; - this.setAttributes(options.attributes || []); + this.objectName = options.objectName || null + this.setAttributes(options.attributes || []) } -util.inherits(SearchEntry, LDAPMessage); +util.inherits(SearchEntry, LDAPMessage) Object.defineProperties(SearchEntry.prototype, { type: { - get: function getType() { return 'SearchEntry'; }, + get: function getType () { return 'SearchEntry' }, configurable: false }, _dn: { - get: function getDN() { return this.objectName; }, + get: function getDN () { return this.objectName }, configurable: false }, object: { - get: function getObject() { + get: function getObject () { var obj = { dn: this.dn.toString(), controls: [] - }; + } this.attributes.forEach(function (a) { if (a.vals && a.vals.length) { if (a.vals.length > 1) { - obj[a.type] = a.vals.slice(); + obj[a.type] = a.vals.slice() } else { - obj[a.type] = a.vals[0]; + obj[a.type] = a.vals[0] } } else { - obj[a.type] = []; + obj[a.type] = [] } - }); + }) this.controls.forEach(function (element, index, array) { - obj.controls.push(element.json); - }); - return obj; + obj.controls.push(element.json) + }) + return obj }, configurable: false }, raw: { - get: function getRaw() { + get: function getRaw () { var obj = { dn: this.dn.toString(), controls: [] - }; + } this.attributes.forEach(function (a) { if (a.buffers && a.buffers.length) { if (a.buffers.length > 1) { - obj[a.type] = a.buffers.slice(); + obj[a.type] = a.buffers.slice() } else { - obj[a.type] = a.buffers[0]; + obj[a.type] = a.buffers[0] } } else { - obj[a.type] = []; + obj[a.type] = [] } - }); + }) this.controls.forEach(function (element, index, array) { - obj.controls.push(element.json); - }); - return obj; + obj.controls.push(element.json) + }) + return obj }, configurable: false } -}); +}) SearchEntry.prototype.addAttribute = function (attr) { - if (!attr || typeof (attr) !== 'object') - throw new TypeError('attr (attribute) required'); + if (!attr || typeof (attr) !== 'object') { throw new TypeError('attr (attribute) required') } - this.attributes.push(attr); -}; + this.attributes.push(attr) +} SearchEntry.prototype.toObject = function () { - return this.object; -}; + return this.object +} SearchEntry.prototype.fromObject = function (obj) { - if (typeof (obj) !== 'object') - throw new TypeError('object required'); + if (typeof (obj) !== 'object') { throw new TypeError('object required') } - var self = this; - if (obj.controls) - this.controls = obj.controls; + var self = this + if (obj.controls) { this.controls = obj.controls } - if (obj.attributes) - obj = obj.attributes; - this.attributes = []; + if (obj.attributes) { obj = obj.attributes } + this.attributes = [] Object.keys(obj).forEach(function (k) { - self.attributes.push(new Attribute({type: k, vals: obj[k]})); - }); + self.attributes.push(new Attribute({ type: k, vals: obj[k] })) + }) - return true; -}; + return true +} SearchEntry.prototype.setAttributes = function (obj) { - if (typeof (obj) !== 'object') - throw new TypeError('object required'); + if (typeof (obj) !== 'object') { throw new TypeError('object required') } if (Array.isArray(obj)) { obj.forEach(function (a) { - if (!Attribute.isAttribute(a)) - throw new TypeError('entry must be an Array of Attributes'); - }); - this.attributes = obj; + if (!Attribute.isAttribute(a)) { throw new TypeError('entry must be an Array of Attributes') } + }) + this.attributes = obj } else { - var self = this; + var self = this - self.attributes = []; + self.attributes = [] Object.keys(obj).forEach(function (k) { - var attr = new Attribute({type: k}); + var attr = new Attribute({ type: k }) if (Array.isArray(obj[k])) { obj[k].forEach(function (v) { - attr.addValue(v.toString()); - }); + attr.addValue(v.toString()) + }) } else { - attr.addValue(obj[k].toString()); + attr.addValue(obj[k].toString()) } - self.attributes.push(attr); - }); + self.attributes.push(attr) + }) } -}; +} SearchEntry.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.objectName = this.objectName.toString(); - j.attributes = []; + j.objectName = this.objectName.toString() + j.attributes = [] this.attributes.forEach(function (a) { - j.attributes.push(a.json || a); - }); + j.attributes.push(a.json || a) + }) - return j; -}; + return j +} SearchEntry.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.objectName = ber.readString(); - assert.ok(ber.readSequence()); + this.objectName = ber.readString() + assert.ok(ber.readSequence()) - var end = ber.offset + ber.length; + var end = ber.offset + ber.length while (ber.offset < end) { - var a = new Attribute(); - a.parse(ber); - this.attributes.push(a); + var a = new Attribute() + a.parse(ber) + this.attributes.push(a) } - return true; -}; + return true +} SearchEntry.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.objectName.toString()); - ber.startSequence(); + ber.writeString(this.objectName.toString()) + ber.startSequence() this.attributes.forEach(function (a) { // This may or may not be an attribute - ber = Attribute.toBer(a, ber); - }); - ber.endSequence(); + ber = Attribute.toBer(a, ber) + }) + ber.endSequence() - return ber; -}; + return ber +} +/// --- Exports -///--- Exports - -module.exports = SearchEntry; +module.exports = SearchEntry diff --git a/lib/messages/search_reference.js b/lib/messages/search_reference.js index f88b038..d9eb67d 100644 --- a/lib/messages/search_reference.js +++ b/lib/messages/search_reference.js @@ -1,105 +1,101 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +// var asn1 = require('asn1') -var LDAPMessage = require('./message'); -var Protocol = require('../protocol'); -var dn = require('../dn'); -var url = require('../url'); +var LDAPMessage = require('./message') +var Protocol = require('../protocol') +var dn = require('../dn') +var url = require('../url') +/// --- Globals -///--- Globals +// var BerWriter = asn1.BerWriter +var parseURL = url.parse -var BerWriter = asn1.BerWriter; -var parseURL = url.parse; +/// --- API +function SearchReference (options) { + options = options || {} + assert.object(options) -///--- API + options.protocolOp = Protocol.LDAP_REP_SEARCH_REF + LDAPMessage.call(this, options) -function SearchReference(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REP_SEARCH_REF; - LDAPMessage.call(this, options); - - this.uris = options.uris || []; + this.uris = options.uris || [] } -util.inherits(SearchReference, LDAPMessage); +util.inherits(SearchReference, LDAPMessage) Object.defineProperties(SearchReference.prototype, { type: { - get: function getType() { return 'SearchReference'; }, + get: function getType () { return 'SearchReference' }, configurable: false }, _dn: { - get: function getDN() { return new dn.DN(''); }, + get: function getDN () { return new dn.DN('') }, configurable: false }, object: { - get: function getObject() { + get: function getObject () { return { dn: this.dn.toString(), uris: this.uris.slice() - }; + } }, configurable: false }, urls: { - get: function getUrls() { return this.uris; }, - set: function setUrls(val) { - assert.ok(val); - assert.ok(Array.isArray(val)); - this.uris = val.slice(); + get: function getUrls () { return this.uris }, + set: function setUrls (val) { + assert.ok(val) + assert.ok(Array.isArray(val)) + this.uris = val.slice() }, configurable: false } -}); +}) SearchReference.prototype.toObject = function () { - return this.object; -}; + return this.object +} SearchReference.prototype.fromObject = function (obj) { - if (typeof (obj) !== 'object') - throw new TypeError('object required'); + if (typeof (obj) !== 'object') { throw new TypeError('object required') } - this.uris = obj.uris ? obj.uris.slice() : []; + this.uris = obj.uris ? obj.uris.slice() : [] - return true; -}; + return true +} SearchReference.prototype._json = function (j) { - assert.ok(j); - j.uris = this.uris.slice(); - return j; -}; + assert.ok(j) + j.uris = this.uris.slice() + return j +} SearchReference.prototype._parse = function (ber, length) { - assert.ok(ber); + assert.ok(ber) while (ber.offset < length) { - var _url = ber.readString(); - parseURL(_url); - this.uris.push(_url); + var _url = ber.readString() + parseURL(_url) + this.uris.push(_url) } - return true; -}; + return true +} SearchReference.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) this.uris.forEach(function (u) { - ber.writeString(u.href || u); - }); + ber.writeString(u.href || u) + }) - return ber; -}; + return ber +} +/// --- Exports -///--- Exports - -module.exports = SearchReference; +module.exports = SearchReference diff --git a/lib/messages/search_request.js b/lib/messages/search_request.js index d55e59e..5049ec7 100644 --- a/lib/messages/search_request.js +++ b/lib/messages/search_request.js @@ -1,150 +1,146 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var asn1 = require('asn1'); +var asn1 = require('asn1') -var LDAPMessage = require('./message'); -var LDAPResult = require('./result'); -var dn = require('../dn'); -var filters = require('../filters'); -var Protocol = require('../protocol'); +var LDAPMessage = require('./message') +// var LDAPResult = require('./result') +var dn = require('../dn') +var filters = require('../filters') +var Protocol = require('../protocol') +/// --- Globals -///--- Globals +var Ber = asn1.Ber -var Ber = asn1.Ber; +/// --- API +function SearchRequest (options) { + options = options || {} + assert.object(options) -///--- API - -function SearchRequest(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REQ_SEARCH; - LDAPMessage.call(this, options); + options.protocolOp = Protocol.LDAP_REQ_SEARCH + LDAPMessage.call(this, options) if (options.baseObject !== undefined) { - this.baseObject = options.baseObject; + this.baseObject = options.baseObject } else { - this.baseObject = dn.parse(''); + this.baseObject = dn.parse('') } - this.scope = options.scope || 'base'; - this.derefAliases = options.derefAliases || Protocol.NEVER_DEREF_ALIASES; - this.sizeLimit = options.sizeLimit || 0; - this.timeLimit = options.timeLimit || 0; - this.typesOnly = options.typesOnly || false; - this.filter = options.filter || null; - this.attributes = options.attributes ? options.attributes.slice(0) : []; + this.scope = options.scope || 'base' + this.derefAliases = options.derefAliases || Protocol.NEVER_DEREF_ALIASES + this.sizeLimit = options.sizeLimit || 0 + this.timeLimit = options.timeLimit || 0 + this.typesOnly = options.typesOnly || false + this.filter = options.filter || null + this.attributes = options.attributes ? options.attributes.slice(0) : [] } -util.inherits(SearchRequest, LDAPMessage); +util.inherits(SearchRequest, LDAPMessage) Object.defineProperties(SearchRequest.prototype, { type: { - get: function getType() { return 'SearchRequest'; }, + get: function getType () { return 'SearchRequest' }, configurable: false }, _dn: { - get: function getDN() { return this.baseObject; }, + get: function getDN () { return this.baseObject }, configurable: false }, scope: { - get: function getScope() { + get: function getScope () { switch (this._scope) { - case Protocol.SCOPE_BASE_OBJECT: return 'base'; - case Protocol.SCOPE_ONE_LEVEL: return 'one'; - case Protocol.SCOPE_SUBTREE: return 'sub'; - default: - throw new Error(this._scope + ' is an invalid search scope'); + case Protocol.SCOPE_BASE_OBJECT: return 'base' + case Protocol.SCOPE_ONE_LEVEL: return 'one' + case Protocol.SCOPE_SUBTREE: return 'sub' + default: + throw new Error(this._scope + ' is an invalid search scope') } }, - set: function setScope(val) { + set: function setScope (val) { if (typeof (val) === 'string') { switch (val) { - case 'base': - this._scope = Protocol.SCOPE_BASE_OBJECT; - break; - case 'one': - this._scope = Protocol.SCOPE_ONE_LEVEL; - break; - case 'sub': - this._scope = Protocol.SCOPE_SUBTREE; - break; - default: - throw new Error(val + ' is an invalid search scope'); + case 'base': + this._scope = Protocol.SCOPE_BASE_OBJECT + break + case 'one': + this._scope = Protocol.SCOPE_ONE_LEVEL + break + case 'sub': + this._scope = Protocol.SCOPE_SUBTREE + break + default: + throw new Error(val + ' is an invalid search scope') } } else { - this._scope = val; + this._scope = val } }, configurable: false } -}); +}) SearchRequest.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - this.baseObject = ber.readString(); - this.scope = ber.readEnumeration(); - this.derefAliases = ber.readEnumeration(); - this.sizeLimit = ber.readInt(); - this.timeLimit = ber.readInt(); - this.typesOnly = ber.readBoolean(); + this.baseObject = ber.readString() + this.scope = ber.readEnumeration() + this.derefAliases = ber.readEnumeration() + this.sizeLimit = ber.readInt() + this.timeLimit = ber.readInt() + this.typesOnly = ber.readBoolean() - this.filter = filters.parse(ber); + this.filter = filters.parse(ber) // look for attributes if (ber.peek() === 0x30) { - ber.readSequence(); - var end = ber.offset + ber.length; - while (ber.offset < end) - this.attributes.push(ber.readString().toLowerCase()); + ber.readSequence() + var end = ber.offset + ber.length + while (ber.offset < end) { this.attributes.push(ber.readString().toLowerCase()) } } - return true; -}; + return true +} SearchRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - ber.writeString(this.baseObject.toString()); - ber.writeEnumeration(this._scope); - ber.writeEnumeration(this.derefAliases); - ber.writeInt(this.sizeLimit); - ber.writeInt(this.timeLimit); - ber.writeBoolean(this.typesOnly); + ber.writeString(this.baseObject.toString()) + ber.writeEnumeration(this._scope) + ber.writeEnumeration(this.derefAliases) + ber.writeInt(this.sizeLimit) + ber.writeInt(this.timeLimit) + ber.writeBoolean(this.typesOnly) - var f = this.filter || new filters.PresenceFilter({attribute: 'objectclass'}); - ber = f.toBer(ber); + var f = this.filter || new filters.PresenceFilter({ attribute: 'objectclass' }) + ber = f.toBer(ber) - ber.startSequence(Ber.Sequence | Ber.Constructor); + ber.startSequence(Ber.Sequence | Ber.Constructor) if (this.attributes && this.attributes.length) { this.attributes.forEach(function (a) { - ber.writeString(a); - }); + ber.writeString(a) + }) } - ber.endSequence(); + ber.endSequence() - return ber; -}; + return ber +} SearchRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - j.baseObject = this.baseObject; - j.scope = this.scope; - j.derefAliases = this.derefAliases; - j.sizeLimit = this.sizeLimit; - j.timeLimit = this.timeLimit; - j.typesOnly = this.typesOnly; - j.filter = this.filter.toString(); - j.attributes = this.attributes; + j.baseObject = this.baseObject + j.scope = this.scope + j.derefAliases = this.derefAliases + j.sizeLimit = this.sizeLimit + j.timeLimit = this.timeLimit + j.typesOnly = this.typesOnly + j.filter = this.filter.toString() + j.attributes = this.attributes - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = SearchRequest; +module.exports = SearchRequest diff --git a/lib/messages/search_response.js b/lib/messages/search_response.js index 9c09024..d47e5ea 100644 --- a/lib/messages/search_response.js +++ b/lib/messages/search_response.js @@ -1,32 +1,31 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPResult = require('./result'); -var SearchEntry = require('./search_entry'); -var SearchReference = require('./search_reference'); +var LDAPResult = require('./result') +var SearchEntry = require('./search_entry') +var SearchReference = require('./search_reference') -var dtrace = require('../dtrace'); -var parseDN = require('../dn').parse; -var parseURL = require('../url').parse; -var Protocol = require('../protocol'); +var dtrace = require('../dtrace') +var parseDN = require('../dn').parse +var parseURL = require('../url').parse +var Protocol = require('../protocol') +/// --- API -///--- API +function SearchResponse (options) { + options = options || {} + assert.object(options) -function SearchResponse(options) { - options = options || {}; - assert.object(options); + options.protocolOp = Protocol.LDAP_REP_SEARCH + LDAPResult.call(this, options) - options.protocolOp = Protocol.LDAP_REP_SEARCH; - LDAPResult.call(this, options); - - this.attributes = options.attributes ? options.attributes.slice() : []; - this.notAttributes = []; - this.sentEntries = 0; + this.attributes = options.attributes ? options.attributes.slice() : [] + this.notAttributes = [] + this.sentEntries = 0 } -util.inherits(SearchResponse, LDAPResult); +util.inherits(SearchResponse, LDAPResult) /** * Allows you to send a SearchEntry back to the client. @@ -36,61 +35,54 @@ util.inherits(SearchResponse, LDAPResult); * Defaults to 'false'. */ SearchResponse.prototype.send = function (entry, nofiltering) { - if (!entry || typeof (entry) !== 'object') - throw new TypeError('entry (SearchEntry) required'); - if (nofiltering === undefined) - nofiltering = false; - if (typeof (nofiltering) !== 'boolean') - throw new TypeError('noFiltering must be a boolean'); + if (!entry || typeof (entry) !== 'object') { throw new TypeError('entry (SearchEntry) required') } + if (nofiltering === undefined) { nofiltering = false } + if (typeof (nofiltering) !== 'boolean') { throw new TypeError('noFiltering must be a boolean') } - var self = this; + var self = this if (entry instanceof SearchEntry || entry instanceof SearchReference) { - if (!entry.messageID) - entry.messageID = this.messageID; - if (entry.messageID !== this.messageID) - throw new Error('SearchEntry messageID mismatch'); + if (!entry.messageID) { entry.messageID = this.messageID } + if (entry.messageID !== this.messageID) { throw new Error('SearchEntry messageID mismatch') } } else { - if (!entry.attributes) - throw new Error('entry.attributes required'); + if (!entry.attributes) { throw new Error('entry.attributes required') } - var savedAttrs = {}; - var all = (self.attributes.indexOf('*') !== -1); + var savedAttrs = {} + var all = (self.attributes.indexOf('*') !== -1) Object.keys(entry.attributes).forEach(function (a) { - var _a = a.toLowerCase(); + var _a = a.toLowerCase() if (!nofiltering && _a.length && _a[0] === '_') { - savedAttrs[a] = entry.attributes[a]; - delete entry.attributes[a]; + savedAttrs[a] = entry.attributes[a] + delete entry.attributes[a] } else if (!nofiltering && self.notAttributes.indexOf(_a) !== -1) { - savedAttrs[a] = entry.attributes[a]; - delete entry.attributes[a]; + savedAttrs[a] = entry.attributes[a] + delete entry.attributes[a] } else if (all) { - return; - } else if (self.attributes.length && self.attributes.indexOf(_a) === -1) { - savedAttrs[a] = entry.attributes[a]; - delete entry.attributes[a]; - } - }); - var save = entry; + } else if (self.attributes.length && self.attributes.indexOf(_a) === -1) { + savedAttrs[a] = entry.attributes[a] + delete entry.attributes[a] + } + }) + + var save = entry entry = new SearchEntry({ objectName: typeof (save.dn) === 'string' ? parseDN(save.dn) : save.dn, messageID: self.messageID, log: self.log - }); - entry.fromObject(save); + }) + entry.fromObject(save) } try { - if (this.log.debug()) - this.log.debug('%s: sending: %j', this.connection.ldap.id, entry.json); + if (this.log.debug) { this.log.debug('%s: sending: %j', this.connection.ldap.id, entry.json) } - this.connection.write(entry.toBer()); - this.sentEntries++; + this.connection.write(entry.toBer()) + this.sentEntries++ if (self._dtraceOp && self._dtraceId) { dtrace.fire('server-search-entry', function () { - var c = self.connection || {ldap: {}}; + var c = self.connection || { ldap: {} } return [ self._dtraceId || 0, (c.remoteAddress || ''), @@ -98,54 +90,49 @@ SearchResponse.prototype.send = function (entry, nofiltering) { (self.requestDN ? self.requestDN.toString() : ''), entry.objectName.toString(), entry.attributes.length - ]; - }); + ] + }) } // Restore attributes Object.keys(savedAttrs || {}).forEach(function (k) { - save.attributes[k] = savedAttrs[k]; - }); - + save.attributes[k] = savedAttrs[k] + }) } catch (e) { this.log.warn(e, '%s failure to write message %j', - this.connection.ldap.id, this.json); + this.connection.ldap.id, this.json) } -}; +} SearchResponse.prototype.createSearchEntry = function (object) { - assert.object(object); + assert.object(object) var entry = new SearchEntry({ messageID: this.messageID, log: this.log, objectName: object.objectName || object.dn - }); - entry.fromObject((object.attributes || object)); - return entry; -}; + }) + entry.fromObject((object.attributes || object)) + return entry +} SearchResponse.prototype.createSearchReference = function (uris) { - if (!uris) - throw new TypeError('uris ([string]) required'); + if (!uris) { throw new TypeError('uris ([string]) required') } - if (!Array.isArray(uris)) - uris = [uris]; + if (!Array.isArray(uris)) { uris = [uris] } for (var i = 0; i < uris.length; i++) { - if (typeof (uris[i]) == 'string') - uris[i] = parseURL(uris[i]); + if (typeof (uris[i]) === 'string') { uris[i] = parseURL(uris[i]) } } - var self = this; + var self = this return new SearchReference({ messageID: self.messageID, log: self.log, uris: uris - }); -}; + }) +} +/// --- Exports -///--- Exports - -module.exports = SearchResponse; +module.exports = SearchResponse diff --git a/lib/messages/unbind_request.js b/lib/messages/unbind_request.js index c1366a6..700b9ba 100644 --- a/lib/messages/unbind_request.js +++ b/lib/messages/unbind_request.js @@ -1,65 +1,62 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var LDAPMessage = require('./message'); -var dn = require('../dn'); -var Protocol = require('../protocol'); +var LDAPMessage = require('./message') +var dn = require('../dn') +var Protocol = require('../protocol') +/// --- Globals -///--- Globals +var DN = dn.DN +var RDN = dn.RDN -var DN = dn.DN; -var RDN = dn.RDN; +/// --- API +function UnbindRequest (options) { + options = options || {} + assert.object(options) -///--- API - -function UnbindRequest(options) { - options = options || {}; - assert.object(options); - - options.protocolOp = Protocol.LDAP_REQ_UNBIND; - LDAPMessage.call(this, options); + options.protocolOp = Protocol.LDAP_REQ_UNBIND + LDAPMessage.call(this, options) } -util.inherits(UnbindRequest, LDAPMessage); +util.inherits(UnbindRequest, LDAPMessage) Object.defineProperties(UnbindRequest.prototype, { type: { - get: function getType() { return 'UnbindRequest'; }, + get: function getType () { return 'UnbindRequest' }, configurable: false }, _dn: { - get: function getDN() { + get: function getDN () { if (this.connection) { - return this.connection.ldap.bindDN; + return this.connection.ldap.bindDN } else { - return new DN([new RDN({cn: 'anonymous'})]); + return new DN([new RDN({ cn: 'anonymous' })]) } }, configurable: false } -}); +}) UnbindRequest.prototype._parse = function (ber) { - assert.ok(ber); + assert.ok(ber) - return true; -}; + return true +} UnbindRequest.prototype._toBer = function (ber) { - assert.ok(ber); + assert.ok(ber) - return ber; -}; + return ber +} UnbindRequest.prototype._json = function (j) { - assert.ok(j); + assert.ok(j) - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = UnbindRequest; +module.exports = UnbindRequest diff --git a/lib/messages/unbind_response.js b/lib/messages/unbind_response.js index e3ca56c..6e0b9e4 100644 --- a/lib/messages/unbind_response.js +++ b/lib/messages/unbind_response.js @@ -1,33 +1,32 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert-plus'); -var util = require('util'); +var assert = require('assert-plus') +var util = require('util') -var dtrace = require('../dtrace'); +var dtrace = require('../dtrace') -var LDAPMessage = require('./result'); -var Protocol = require('../protocol'); +var LDAPMessage = require('./result') +// var Protocol = require('../protocol') - -///--- API +/// --- API // Ok, so there's really no such thing as an unbind 'response', but to make // the framework not suck, I just made this up, and have it stubbed so it's // not such a one-off. -function UnbindResponse(options) { - options = options || {}; - assert.object(options); +function UnbindResponse (options) { + options = options || {} + assert.object(options) - options.protocolOp = 0; - LDAPMessage.call(this, options); + options.protocolOp = 0 + LDAPMessage.call(this, options) } -util.inherits(UnbindResponse, LDAPMessage); +util.inherits(UnbindResponse, LDAPMessage) Object.defineProperties(UnbindResponse.prototype, { type: { - get: function getType() { return 'UnbindResponse'; }, + get: function getType () { return 'UnbindResponse' }, configurable: false } -}); +}) /** * Special override that just ends the connection, if present. @@ -35,16 +34,16 @@ Object.defineProperties(UnbindResponse.prototype, { * @param {Number} status completely ignored. */ UnbindResponse.prototype.end = function (status) { - assert.ok(this.connection); + assert.ok(this.connection) - this.log.trace('%s: unbinding!', this.connection.ldap.id); + this.log.trace('%s: unbinding!', this.connection.ldap.id) - this.connection.end(); + this.connection.end() - var self = this; + var self = this if (self._dtraceOp && self._dtraceId) { dtrace.fire('server-' + self._dtraceOp + '-done', function () { - var c = self.connection || {ldap: {}}; + var c = self.connection || { ldap: {} } return [ self._dtraceId || 0, (c.remoteAddress || ''), @@ -52,16 +51,15 @@ UnbindResponse.prototype.end = function (status) { (self.requestDN ? self.requestDN.toString() : ''), 0, '' - ]; - }); + ] + }) } -}; +} UnbindResponse.prototype._json = function (j) { - return j; -}; + return j +} +/// --- Exports -///--- Exports - -module.exports = UnbindResponse; +module.exports = UnbindResponse diff --git a/lib/persistent_search.js b/lib/persistent_search.js index 79087aa..a94672f 100644 --- a/lib/persistent_search.js +++ b/lib/persistent_search.js @@ -1,123 +1,109 @@ -///--- Globals +/// --- Globals -var parseDN = require('./dn').parse; +// var parseDN = require('./dn').parse var EntryChangeNotificationControl = - require('./controls').EntryChangeNotificationControl; + require('./controls').EntryChangeNotificationControl -///--- API +/// --- API // Cache used to store connected persistent search clients -function PersistentSearch() { - this.clientList = []; +function PersistentSearch () { + this.clientList = [] } - PersistentSearch.prototype.addClient = function (req, res, callback) { - if (typeof (req) !== 'object') - throw new TypeError('req must be an object'); - if (typeof (res) !== 'object') - throw new TypeError('res must be an object'); - if (callback && typeof (callback) !== 'function') - throw new TypeError('callback must be a function'); + if (typeof (req) !== 'object') { throw new TypeError('req must be an object') } + if (typeof (res) !== 'object') { throw new TypeError('res must be an object') } + if (callback && typeof (callback) !== 'function') { throw new TypeError('callback must be a function') } - var log = req.log; + var log = req.log - var client = {}; - client.req = req; - client.res = res; + var client = {} + client.req = req + client.res = res - log.debug('%s storing client', req.logId); + log.debug('%s storing client', req.logId) - this.clientList.push(client); + this.clientList.push(client) - log.debug('%s stored client', req.logId); + log.debug('%s stored client', req.logId) log.debug('%s total number of clients %s', - req.logId, this.clientList.length); - if (callback) - callback(client); -}; - + req.logId, this.clientList.length) + if (callback) { callback(client) } +} PersistentSearch.prototype.removeClient = function (req, res, callback) { - if (typeof (req) !== 'object') - throw new TypeError('req must be an object'); - if (typeof (res) !== 'object') - throw new TypeError('res must be an object'); - if (callback && typeof (callback) !== 'function') - throw new TypeError('callback must be a function'); + if (typeof (req) !== 'object') { throw new TypeError('req must be an object') } + if (typeof (res) !== 'object') { throw new TypeError('res must be an object') } + if (callback && typeof (callback) !== 'function') { throw new TypeError('callback must be a function') } - var log = req.log; - log.debug('%s removing client', req.logId); - var client = {}; - client.req = req; - client.res = res; + var log = req.log + log.debug('%s removing client', req.logId) + var client = {} + client.req = req + client.res = res // remove the client if it exists this.clientList.forEach(function (element, index, array) { if (element.req === client.req) { - log.debug('%s removing client from list', req.logId); - array.splice(index, 1); + log.debug('%s removing client from list', req.logId) + array.splice(index, 1) } - }); + }) log.debug('%s number of persistent search clients %s', - req.logId, this.clientList.length); - if (callback) - callback(client); -}; + req.logId, this.clientList.length) + if (callback) { callback(client) } +} - -function getOperationType(requestType) { +function getOperationType (requestType) { switch (requestType) { case 'AddRequest': case 'add': - return 1; + return 1 case 'DeleteRequest': case 'delete': - return 2; + return 2 case 'ModifyRequest': case 'modify': - return 4; + return 4 case 'ModifyDNRequest': case 'modrdn': - return 8; + return 8 default: throw new TypeError('requestType %s, is an invalid request type', - requestType); + requestType) } } - -function getEntryChangeNotificationControl(req, obj, callback) { +function getEntryChangeNotificationControl (req, obj, callback) { // if we want to return a ECNC if (req.persistentSearch.value.returnECs) { - var attrs = obj.attributes; - var value = {}; - value.changeType = getOperationType(attrs.changetype); + var attrs = obj.attributes + var value = {} + value.changeType = getOperationType(attrs.changetype) // if it's a modDN request, fill in the previous DN if (value.changeType === 8 && attrs.previousDN) { - value.previousDN = attrs.previousDN; + value.previousDN = attrs.previousDN } - value.changeNumber = attrs.changenumber; - return new EntryChangeNotificationControl({ value: value }); + value.changeNumber = attrs.changenumber + return new EntryChangeNotificationControl({ value: value }) } else { - return false; + return false } } - -function checkChangeType(req, requestType) { +function checkChangeType (req, requestType) { return (req.persistentSearch.value.changeTypes & - getOperationType(requestType)); + getOperationType(requestType)) } - -///--- Exports +/// --- Exports module.exports = { PersistentSearchCache: PersistentSearch, checkChangeType: checkChangeType, getEntryChangeNotificationControl: getEntryChangeNotificationControl -}; +} diff --git a/lib/protocol.js b/lib/protocol.js index 398f7b3..5b7927d 100644 --- a/lib/protocol.js +++ b/lib/protocol.js @@ -1,6 +1,5 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. - module.exports = { // Misc @@ -51,4 +50,4 @@ module.exports = { LDAP_REP_MODRDN: 0x6d, LDAP_REP_COMPARE: 0x6f, LDAP_REP_EXTENSION: 0x78 -}; +} diff --git a/lib/server.js b/lib/server.js index 29750de..fbc8dc0 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1,239 +1,226 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var assert = require('assert'); -var EventEmitter = require('events').EventEmitter; -var net = require('net'); -var tls = require('tls'); -var util = require('util'); +var assert = require('assert') +var EventEmitter = require('events').EventEmitter +var net = require('net') +var tls = require('tls') +var util = require('util') -var asn1 = require('asn1'); -var VError = require('verror').VError; +// var asn1 = require('asn1') +var VError = require('verror').VError -var dn = require('./dn'); -var dtrace = require('./dtrace'); -var errors = require('./errors'); -var Protocol = require('./protocol'); +var dn = require('./dn') +var dtrace = require('./dtrace') +var errors = require('./errors') +var Protocol = require('./protocol') -var Parser = require('./messages').Parser; -var AbandonResponse = require('./messages/abandon_response'); -var AddResponse = require('./messages/add_response'); -var BindResponse = require('./messages/bind_response'); -var CompareResponse = require('./messages/compare_response'); -var DeleteResponse = require('./messages/del_response'); -var ExtendedResponse = require('./messages/ext_response'); -var LDAPResult = require('./messages/result'); -var ModifyResponse = require('./messages/modify_response'); -var ModifyDNResponse = require('./messages/moddn_response'); -var SearchRequest = require('./messages/search_request'); -var SearchResponse = require('./messages/search_response'); -var UnbindResponse = require('./messages/unbind_response'); +var Parser = require('./messages').Parser +var AbandonResponse = require('./messages/abandon_response') +var AddResponse = require('./messages/add_response') +var BindResponse = require('./messages/bind_response') +var CompareResponse = require('./messages/compare_response') +var DeleteResponse = require('./messages/del_response') +var ExtendedResponse = require('./messages/ext_response') +// var LDAPResult = require('./messages/result') +var ModifyResponse = require('./messages/modify_response') +var ModifyDNResponse = require('./messages/moddn_response') +var SearchRequest = require('./messages/search_request') +var SearchResponse = require('./messages/search_response') +var UnbindResponse = require('./messages/unbind_response') +/// --- Globals +// var Ber = asn1.Ber +// var BerReader = asn1.BerReader +var DN = dn.DN -///--- Globals +// var sprintf = util.format -var Ber = asn1.Ber; -var BerReader = asn1.BerReader; -var DN = dn.DN; +/// --- Helpers -var sprintf = util.format; +function mergeFunctionArgs (argv, start, end) { + assert.ok(argv) + if (!start) { start = 0 } + if (!end) { end = argv.length } -///--- Helpers - -function mergeFunctionArgs(argv, start, end) { - assert.ok(argv); - - if (!start) - start = 0; - if (!end) - end = argv.length; - - var handlers = []; + var handlers = [] for (var i = start; i < end; i++) { if (argv[i] instanceof Array) { - var arr = argv[i]; + var arr = argv[i] for (var j = 0; j < arr.length; j++) { if (!(arr[j] instanceof Function)) { - throw new TypeError('Invalid argument type: ' + typeof (arr[j])); + throw new TypeError('Invalid argument type: ' + typeof (arr[j])) } - handlers.push(arr[j]); + handlers.push(arr[j]) } } else if (argv[i] instanceof Function) { - handlers.push(argv[i]); + handlers.push(argv[i]) } else { - throw new TypeError('Invalid argument type: ' + typeof (argv[i])); + throw new TypeError('Invalid argument type: ' + typeof (argv[i])) } } - return handlers; + return handlers } +function getResponse (req) { + assert.ok(req) -function getResponse(req) { - assert.ok(req); - - var Response; + var Response switch (req.protocolOp) { - case Protocol.LDAP_REQ_BIND: - Response = BindResponse; - break; - case Protocol.LDAP_REQ_ABANDON: - Response = AbandonResponse; - break; - case Protocol.LDAP_REQ_ADD: - Response = AddResponse; - break; - case Protocol.LDAP_REQ_COMPARE: - Response = CompareResponse; - break; - case Protocol.LDAP_REQ_DELETE: - Response = DeleteResponse; - break; - case Protocol.LDAP_REQ_EXTENSION: - Response = ExtendedResponse; - break; - case Protocol.LDAP_REQ_MODIFY: - Response = ModifyResponse; - break; - case Protocol.LDAP_REQ_MODRDN: - Response = ModifyDNResponse; - break; - case Protocol.LDAP_REQ_SEARCH: - Response = SearchResponse; - break; - case Protocol.LDAP_REQ_UNBIND: - Response = UnbindResponse; - break; - default: - return null; + case Protocol.LDAP_REQ_BIND: + Response = BindResponse + break + case Protocol.LDAP_REQ_ABANDON: + Response = AbandonResponse + break + case Protocol.LDAP_REQ_ADD: + Response = AddResponse + break + case Protocol.LDAP_REQ_COMPARE: + Response = CompareResponse + break + case Protocol.LDAP_REQ_DELETE: + Response = DeleteResponse + break + case Protocol.LDAP_REQ_EXTENSION: + Response = ExtendedResponse + break + case Protocol.LDAP_REQ_MODIFY: + Response = ModifyResponse + break + case Protocol.LDAP_REQ_MODRDN: + Response = ModifyDNResponse + break + case Protocol.LDAP_REQ_SEARCH: + Response = SearchResponse + break + case Protocol.LDAP_REQ_UNBIND: + Response = UnbindResponse + break + default: + return null } - assert.ok(Response); + assert.ok(Response) var res = new Response({ messageID: req.messageID, log: req.log, attributes: ((req instanceof SearchRequest) ? req.attributes : undefined) - }); - res.connection = req.connection; - res.logId = req.logId; + }) + res.connection = req.connection + res.logId = req.logId - return res; + return res } +function defaultHandler (req, res, next) { + assert.ok(req) + assert.ok(res) + assert.ok(next) -function defaultHandler(req, res, next) { - assert.ok(req); - assert.ok(res); - assert.ok(next); - - res.matchedDN = req.dn.toString(); - res.errorMessage = 'Server method not implemented'; - res.end(errors.LDAP_OTHER); - return next(); + res.matchedDN = req.dn.toString() + res.errorMessage = 'Server method not implemented' + res.end(errors.LDAP_OTHER) + return next() } +function defaultNoOpHandler (req, res, next) { + assert.ok(req) + assert.ok(res) + assert.ok(next) -function defaultNoOpHandler(req, res, next) { - assert.ok(req); - assert.ok(res); - assert.ok(next); - - res.end(); - return next(); + res.end() + return next() } +function noSuffixHandler (req, res, next) { + assert.ok(req) + assert.ok(res) + assert.ok(next) -function noSuffixHandler(req, res, next) { - assert.ok(req); - assert.ok(res); - assert.ok(next); - - res.errorMessage = 'No tree found for: ' + req.dn.toString(); - res.end(errors.LDAP_NO_SUCH_OBJECT); - return next(); + res.errorMessage = 'No tree found for: ' + req.dn.toString() + res.end(errors.LDAP_NO_SUCH_OBJECT) + return next() } +function noExOpHandler (req, res, next) { + assert.ok(req) + assert.ok(res) + assert.ok(next) -function noExOpHandler(req, res, next) { - assert.ok(req); - assert.ok(res); - assert.ok(next); - - res.errorMessage = req.requestName + ' not supported'; - res.end(errors.LDAP_PROTOCOL_ERROR); - return next(); + res.errorMessage = req.requestName + ' not supported' + res.end(errors.LDAP_PROTOCOL_ERROR) + return next() } +function fireDTraceProbe (req, res) { + assert.ok(req) -function fireDTraceProbe(req, res) { - assert.ok(req); - - req._dtraceId = res._dtraceId = dtrace._nextId(); + req._dtraceId = res._dtraceId = dtrace._nextId() var probeArgs = [ req._dtraceId, req.connection.remoteAddress || 'localhost', req.connection.ldap.bindDN.toString(), req.dn.toString() - ]; + ] - var op; + var op switch (req.protocolOp) { - case Protocol.LDAP_REQ_ABANDON: - op = 'abandon'; - break; - case Protocol.LDAP_REQ_ADD: - op = 'add'; - probeArgs.push(req.attributes.length); - break; - case Protocol.LDAP_REQ_BIND: - op = 'bind'; - break; - case Protocol.LDAP_REQ_COMPARE: - op = 'compare'; - probeArgs.push(req.attribute); - probeArgs.push(req.value); - break; - case Protocol.LDAP_REQ_DELETE: - op = 'delete'; - break; - case Protocol.LDAP_REQ_EXTENSION: - op = 'exop'; - probeArgs.push(req.name); - probeArgs.push(req.value); - break; - case Protocol.LDAP_REQ_MODIFY: - op = 'modify'; - probeArgs.push(req.changes.length); - break; - case Protocol.LDAP_REQ_MODRDN: - op = 'modifydn'; - probeArgs.push(req.newRdn.toString()); - probeArgs.push((req.newSuperior ? req.newSuperior.toString() : '')); - break; - case Protocol.LDAP_REQ_SEARCH: - op = 'search'; - probeArgs.push(req.scope); - probeArgs.push(req.filter.toString()); - break; - case Protocol.LDAP_REQ_UNBIND: - op = 'unbind'; - break; - default: - break; + case Protocol.LDAP_REQ_ABANDON: + op = 'abandon' + break + case Protocol.LDAP_REQ_ADD: + op = 'add' + probeArgs.push(req.attributes.length) + break + case Protocol.LDAP_REQ_BIND: + op = 'bind' + break + case Protocol.LDAP_REQ_COMPARE: + op = 'compare' + probeArgs.push(req.attribute) + probeArgs.push(req.value) + break + case Protocol.LDAP_REQ_DELETE: + op = 'delete' + break + case Protocol.LDAP_REQ_EXTENSION: + op = 'exop' + probeArgs.push(req.name) + probeArgs.push(req.value) + break + case Protocol.LDAP_REQ_MODIFY: + op = 'modify' + probeArgs.push(req.changes.length) + break + case Protocol.LDAP_REQ_MODRDN: + op = 'modifydn' + probeArgs.push(req.newRdn.toString()) + probeArgs.push((req.newSuperior ? req.newSuperior.toString() : '')) + break + case Protocol.LDAP_REQ_SEARCH: + op = 'search' + probeArgs.push(req.scope) + probeArgs.push(req.filter.toString()) + break + case Protocol.LDAP_REQ_UNBIND: + op = 'unbind' + break + default: + break } - res._dtraceOp = op; + res._dtraceOp = op dtrace.fire('server-' + op + '-start', function () { - return probeArgs; - }); + return probeArgs + }) } - - -///--- API +/// --- API /** * Constructs a new server that you can call .listen() on, in the various @@ -250,12 +237,10 @@ function fireDTraceProbe(req, res) { * @param {Object} options (optional) parameterization object. * @throws {TypeError} on bad input. */ -function Server(options) { +function Server (options) { if (options) { - if (typeof (options) !== 'object') - throw new TypeError('options (object) required'); - if (typeof (options.log) !== 'object') - throw new TypeError('options.log must be an object'); + if (typeof (options) !== 'object') { throw new TypeError('options (object) required') } + if (typeof (options.log) !== 'object') { throw new TypeError('options.log must be an object') } if (options.certificate || options.key) { if (!(options.certificate && options.key) || @@ -264,270 +249,257 @@ function Server(options) { (typeof (options.key) !== 'string' && !Buffer.isBuffer(options.key))) { throw new TypeError('options.certificate and options.key ' + - '(string or buffer) are both required for TLS'); + '(string or buffer) are both required for TLS') } } } else { - options = {}; + options = {} } - var self = this; + var self = this - EventEmitter.call(this, options); + EventEmitter.call(this, options) - this._chain = []; - this.log = options.log; - this.strictDN = (options.strictDN !== undefined) ? options.strictDN : true; + this._chain = [] + this.log = options.log + this.strictDN = (options.strictDN !== undefined) ? options.strictDN : true - var log = this.log; + var log = this.log - function setupConnection(c) { - assert.ok(c); + function setupConnection (c) { + assert.ok(c) if (c.type === 'unix') { - c.remoteAddress = self.server.path; - c.remotePort = c.fd; + c.remoteAddress = self.server.path + c.remotePort = c.fd } else if (c.socket) { // TLS - c.remoteAddress = c.socket.remoteAddress; - c.remotePort = c.socket.remotePort; + c.remoteAddress = c.socket.remoteAddress + c.remotePort = c.socket.remotePort } - - var rdn = new dn.RDN({cn: 'anonymous'}); + var rdn = new dn.RDN({ cn: 'anonymous' }) c.ldap = { id: c.remoteAddress + ':' + c.remotePort, config: options, _bindDN: new DN([rdn]) - }; + } c.addListener('timeout', function () { - log.trace('%s timed out', c.ldap.id); - c.destroy(); - }); + log.trace('%s timed out', c.ldap.id) + c.destroy() + }) c.addListener('end', function () { - log.trace('%s shutdown', c.ldap.id); - }); + log.trace('%s shutdown', c.ldap.id) + }) c.addListener('error', function (err) { - log.warn('%s unexpected connection error', c.ldap.id, err); - self.emit('clientError', err); - c.destroy(); - }); - c.addListener('close', function (had_err) { - log.trace('%s close; had_err=%j', c.ldap.id, had_err); - c.end(); - }); + log.warn('%s unexpected connection error', c.ldap.id, err) + self.emit('clientError', err) + c.destroy() + }) + c.addListener('close', function (closeError) { + log.trace('%s close; had_err=%j', c.ldap.id, closeError) + c.end() + }) c.ldap.__defineGetter__('bindDN', function () { - return c.ldap._bindDN; - }); + return c.ldap._bindDN + }) c.ldap.__defineSetter__('bindDN', function (val) { - if (!(val instanceof DN)) - throw new TypeError('DN required'); + if (!(val instanceof DN)) { throw new TypeError('DN required') } - c.ldap._bindDN = val; - return val; - }); - return c; + c.ldap._bindDN = val + return val + }) + return c } - function newConnection(c) { - setupConnection(c); - log.trace('new connection from %s', c.ldap.id); + function newConnection (c) { + setupConnection(c) + log.trace('new connection from %s', c.ldap.id) dtrace.fire('server-connection', function () { - return [c.remoteAddress]; - }); + return [c.remoteAddress] + }) c.parser = new Parser({ log: options.log - }); + }) c.parser.on('message', function (req) { - req.connection = c; - req.logId = c.ldap.id + '::' + req.messageID; - req.startTime = new Date().getTime(); + req.connection = c + req.logId = c.ldap.id + '::' + req.messageID + req.startTime = new Date().getTime() - if (log.debug()) - log.debug('%s: message received: req=%j', c.ldap.id, req.json); + if (log.debug()) { log.debug('%s: message received: req=%j', c.ldap.id, req.json) } - var res = getResponse(req); + var res = getResponse(req) if (!res) { - log.warn('Unimplemented server method: %s', req.type); - c.destroy(); - return false; + log.warn('Unimplemented server method: %s', req.type) + c.destroy() + return false } // parse string DNs for routing/etc try { switch (req.protocolOp) { - case Protocol.LDAP_REQ_BIND: - req.name = dn.parse(req.name); - break; - case Protocol.LDAP_REQ_ADD: - case Protocol.LDAP_REQ_COMPARE: - case Protocol.LDAP_REQ_DELETE: - req.entry = dn.parse(req.entry); - break; - case Protocol.LDAP_REQ_MODIFY: - req.object = dn.parse(req.object); - break; - case Protocol.LDAP_REQ_MODRDN: - req.entry = dn.parse(req.entry); - // TODO: handle newRdn/Superior - break; - case Protocol.LDAP_REQ_SEARCH: - req.baseObject = dn.parse(req.baseObject); - break; - default: - break; + case Protocol.LDAP_REQ_BIND: + req.name = dn.parse(req.name) + break + case Protocol.LDAP_REQ_ADD: + case Protocol.LDAP_REQ_COMPARE: + case Protocol.LDAP_REQ_DELETE: + req.entry = dn.parse(req.entry) + break + case Protocol.LDAP_REQ_MODIFY: + req.object = dn.parse(req.object) + break + case Protocol.LDAP_REQ_MODRDN: + req.entry = dn.parse(req.entry) + // TODO: handle newRdn/Superior + break + case Protocol.LDAP_REQ_SEARCH: + req.baseObject = dn.parse(req.baseObject) + break + default: + break } } catch (e) { if (self.strictDN) { - return res.end(errors.LDAP_INVALID_DN_SYNTAX); + return res.end(errors.LDAP_INVALID_DN_SYNTAX) } } - res.connection = c; - res.logId = req.logId; - res.requestDN = req.dn; + res.connection = c + res.logId = req.logId + res.requestDN = req.dn - var chain = self._getHandlerChain(req, res); + var chain = self._getHandlerChain(req, res) - var i = 0; - return function (err) { - function sendError(err) { - res.status = err.code || errors.LDAP_OPERATIONS_ERROR; - res.matchedDN = req.suffix ? req.suffix.toString() : ''; - res.errorMessage = err.message || ''; - return res.end(); + var i = 0 + return (function messageIIFE (err) { + function sendError (err) { + res.status = err.code || errors.LDAP_OPERATIONS_ERROR + res.matchedDN = req.suffix ? req.suffix.toString() : '' + res.errorMessage = err.message || '' + return res.end() } - function after() { - if (!self._postChain || !self._postChain.length) - return; + function after () { + if (!self._postChain || !self._postChain.length) { return } - function next() {} // stub out next for the post chain + function next () {} // stub out next for the post chain self._postChain.forEach(function (c) { - c.call(self, req, res, next); - }); + c.call(self, req, res, next) + }) } if (err) { - log.trace('%s sending error: %s', req.logId, err.stack || err); - self.emit('clientError', err); - sendError(err); - return after(); + log.trace('%s sending error: %s', req.logId, err.stack || err) + self.emit('clientError', err) + sendError(err) + return after() } try { - var next = arguments.callee; - if (chain.handlers[i]) - return chain.handlers[i++].call(chain.backend, req, res, next); + var next = messageIIFE + if (chain.handlers[i]) { return chain.handlers[i++].call(chain.backend, req, res, next) } - if (req.protocolOp === Protocol.LDAP_REQ_BIND && res.status === 0) - c.ldap.bindDN = req.dn; + if (req.protocolOp === Protocol.LDAP_REQ_BIND && res.status === 0) { c.ldap.bindDN = req.dn } - return after(); + return after() } catch (e) { - if (!e.stack) - e.stack = e.toString(); - log.error('%s uncaught exception: %s', req.logId, e.stack); - return sendError(new errors.OperationsError(e.message)); + if (!e.stack) { e.stack = e.toString() } + log.error('%s uncaught exception: %s', req.logId, e.stack) + return sendError(new errors.OperationsError(e.message)) } - - }(); - }); + }()) + }) c.parser.on('error', function (err, message) { - self.emit('error', new VError(err, 'Parser error for %s', c.ldap.id)); + self.emit('error', new VError(err, 'Parser error for %s', c.ldap.id)) - if (!message) - return c.destroy(); + if (!message) { return c.destroy() } - var res = getResponse(message); - if (!res) - return c.destroy(); + var res = getResponse(message) + if (!res) { return c.destroy() } - res.status = 0x02; // protocol error - res.errorMessage = err.toString(); - return c.end(res.toBer()); - }); + res.status = 0x02 // protocol error + res.errorMessage = err.toString() + return c.end(res.toBer()) + }) c.on('data', function (data) { - if (log.trace()) - log.trace('data on %s: %s', c.ldap.id, util.inspect(data)); - - c.parser.write(data); - }); + if (log.trace()) { log.trace('data on %s: %s', c.ldap.id, util.inspect(data)) } + c.parser.write(data) + }) } // end newConnection - this.routes = {}; + this.routes = {} if ((options.cert || options.certificate) && options.key) { - options.cert = options.cert || options.certificate; - this.server = tls.createServer(options, newConnection); + options.cert = options.cert || options.certificate + this.server = tls.createServer(options, newConnection) } else { - this.server = net.createServer(newConnection); + this.server = net.createServer(newConnection) } - this.server.log = options.log; + this.server.log = options.log this.server.ldap = { config: options - }; + } this.server.on('close', function () { - self.emit('close'); - }); + self.emit('close') + }) this.server.on('error', function (err) { - self.emit('error', err); - }); + self.emit('error', err) + }) } -util.inherits(Server, EventEmitter); +util.inherits(Server, EventEmitter) Object.defineProperties(Server.prototype, { maxConnections: { - get: function getMaxConnections() { - return this.server.maxConnections; + get: function getMaxConnections () { + return this.server.maxConnections }, - set: function setMaxConnections(val) { - this.server.maxConnections = val; + set: function setMaxConnections (val) { + this.server.maxConnections = val }, configurable: false }, connections: { - get: function getConnections() { - return this.server.connections; + get: function getConnections () { + return this.server.connections }, configurable: false }, name: { - get: function getName() { - return 'LDAPServer'; + get: function getName () { + return 'LDAPServer' }, configurable: false }, url: { - get: function getURL() { - var str; - var addr = this.server.address(); + get: function getURL () { + var str + var addr = this.server.address() if (!addr) { - return null; + return null } if (!addr.family) { - str = 'ldapi://'; - str += this.host.replace(new RegExp('/', 'g'), '%2f'); - return str; + str = 'ldapi://' + str += this.host.replace(new RegExp('/', 'g'), '%2f') + return str } if (this.server instanceof tls.Server) { - str = 'ldaps://'; + str = 'ldaps://' } else { - str = 'ldap://'; + str = 'ldap://' } - str += this.host + ':' + this.port; - return str; + str += this.host + ':' + this.port + return str }, configurable: false } -}); -module.exports = Server; - +}) +module.exports = Server /** * Adds a handler (chain) for the LDAP add method. @@ -540,10 +512,9 @@ module.exports = Server; * @throws {TypeError} on bad input */ Server.prototype.add = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - return this._mount(Protocol.LDAP_REQ_ADD, name, args); -}; - + var args = Array.prototype.slice.call(arguments, 1) + return this._mount(Protocol.LDAP_REQ_ADD, name, args) +} /** * Adds a handler (chain) for the LDAP bind method. @@ -556,10 +527,9 @@ Server.prototype.add = function (name) { * @throws {TypeError} on bad input */ Server.prototype.bind = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - return this._mount(Protocol.LDAP_REQ_BIND, name, args); -}; - + var args = Array.prototype.slice.call(arguments, 1) + return this._mount(Protocol.LDAP_REQ_BIND, name, args) +} /** * Adds a handler (chain) for the LDAP compare method. @@ -572,10 +542,9 @@ Server.prototype.bind = function (name) { * @throws {TypeError} on bad input */ Server.prototype.compare = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - return this._mount(Protocol.LDAP_REQ_COMPARE, name, args); -}; - + var args = Array.prototype.slice.call(arguments, 1) + return this._mount(Protocol.LDAP_REQ_COMPARE, name, args) +} /** * Adds a handler (chain) for the LDAP delete method. @@ -588,10 +557,9 @@ Server.prototype.compare = function (name) { * @throws {TypeError} on bad input */ Server.prototype.del = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - return this._mount(Protocol.LDAP_REQ_DELETE, name, args); -}; - + var args = Array.prototype.slice.call(arguments, 1) + return this._mount(Protocol.LDAP_REQ_DELETE, name, args) +} /** * Adds a handler (chain) for the LDAP exop method. @@ -604,10 +572,9 @@ Server.prototype.del = function (name) { * @throws {TypeError} on bad input. */ Server.prototype.exop = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - return this._mount(Protocol.LDAP_REQ_EXTENSION, name, args, true); -}; - + var args = Array.prototype.slice.call(arguments, 1) + return this._mount(Protocol.LDAP_REQ_EXTENSION, name, args, true) +} /** * Adds a handler (chain) for the LDAP modify method. @@ -620,10 +587,9 @@ Server.prototype.exop = function (name) { * @throws {TypeError} on bad input */ Server.prototype.modify = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - return this._mount(Protocol.LDAP_REQ_MODIFY, name, args); -}; - + var args = Array.prototype.slice.call(arguments, 1) + return this._mount(Protocol.LDAP_REQ_MODIFY, name, args) +} /** * Adds a handler (chain) for the LDAP modifyDN method. @@ -636,10 +602,9 @@ Server.prototype.modify = function (name) { * @throws {TypeError} on bad input */ Server.prototype.modifyDN = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - return this._mount(Protocol.LDAP_REQ_MODRDN, name, args); -}; - + var args = Array.prototype.slice.call(arguments, 1) + return this._mount(Protocol.LDAP_REQ_MODRDN, name, args) +} /** * Adds a handler (chain) for the LDAP search method. @@ -652,10 +617,9 @@ Server.prototype.modifyDN = function (name) { * @throws {TypeError} on bad input */ Server.prototype.search = function (name) { - var args = Array.prototype.slice.call(arguments, 1); - return this._mount(Protocol.LDAP_REQ_SEARCH, name, args); -}; - + var args = Array.prototype.slice.call(arguments, 1) + return this._mount(Protocol.LDAP_REQ_SEARCH, name, args) +} /** * Adds a handler (chain) for the LDAP unbind method. @@ -667,139 +631,133 @@ Server.prototype.search = function (name) { * @throws {TypeError} on bad input */ Server.prototype.unbind = function () { - var args = Array.prototype.slice.call(arguments, 0); - return this._mount(Protocol.LDAP_REQ_UNBIND, 'unbind', args, true); -}; + var args = Array.prototype.slice.call(arguments, 0) + return this._mount(Protocol.LDAP_REQ_UNBIND, 'unbind', args, true) +} - -Server.prototype.use = function use() { - var args = Array.prototype.slice.call(arguments); - var chain = mergeFunctionArgs(args, 0, args.length); - var self = this; +Server.prototype.use = function use () { + var args = Array.prototype.slice.call(arguments) + var chain = mergeFunctionArgs(args, 0, args.length) + var self = this chain.forEach(function (c) { - self._chain.push(c); - }); -}; - + self._chain.push(c) + }) +} Server.prototype.after = function () { - if (!this._postChain) - this._postChain = []; + if (!this._postChain) { this._postChain = [] } - var self = this; + var self = this mergeFunctionArgs(arguments).forEach(function (h) { - self._postChain.push(h); - }); -}; - + self._postChain.push(h) + }) +} // All these just reexpose the requisite net.Server APIs Server.prototype.listen = function (port, host, callback) { - if (typeof (port) !== 'number' && typeof (port) !== 'string') - throw new TypeError('port (number or path) required'); + if (typeof (port) !== 'number' && typeof (port) !== 'string') { throw new TypeError('port (number or path) required') } if (typeof (host) === 'function') { - callback = host; - host = '0.0.0.0'; + callback = host + host = '0.0.0.0' } if (typeof (port) === 'string' && /^[0-9]+$/.test(port)) { // Disambiguate between string ports and file paths - port = parseInt(port, 10); + port = parseInt(port, 10) } - var self = this; + var self = this - function cbListen() { + function cbListen () { if (typeof (port) === 'number') { - self.host = self.address().address; - self.port = self.address().port; + self.host = self.address().address + self.port = self.address().port } else { - self.host = port; - self.port = self.server.fd; + self.host = port + self.port = self.server.fd } - if (typeof (callback) === 'function') - callback(); + if (typeof (callback) === 'function') { callback() } } if (typeof (port) === 'number') { - return this.server.listen(port, host, cbListen); + return this.server.listen(port, host, cbListen) } else { - return this.server.listen(port, cbListen); + return this.server.listen(port, cbListen) } -}; +} Server.prototype.listenFD = function (fd) { - this.host = 'unix-domain-socket'; - this.port = fd; - return this.server.listenFD(fd); -}; + this.host = 'unix-domain-socket' + this.port = fd + return this.server.listenFD(fd) +} Server.prototype.close = function (callback) { - return this.server.close(callback); -}; + return this.server.close(callback) +} Server.prototype.address = function () { - return this.server.address(); -}; - + return this.server.address() +} Server.prototype._getRoute = function (_dn, backend) { - assert.ok(dn); + assert.ok(dn) - if (!backend) - backend = this; + if (!backend) { backend = this } - var name; + var name if (_dn instanceof dn.DN) { - name = _dn.toString(); + name = _dn.toString() } else { - name = _dn; + name = _dn } if (!this.routes[name]) { - this.routes[name] = {}; - this.routes[name].backend = backend; - this.routes[name].dn = _dn; + this.routes[name] = {} + this.routes[name].backend = backend + this.routes[name].dn = _dn // Force regeneration of the route key cache on next request - this._routeKeyCache = null; + this._routeKeyCache = null } - return this.routes[name]; -}; + return this.routes[name] +} - -Server.prototype._sortedRouteKeys = function _sortedRouteKeys() { +Server.prototype._sortedRouteKeys = function _sortedRouteKeys () { // The filtered/sorted route keys are cached to prevent needlessly // regenerating the list for every incoming request. if (!this._routeKeyCache) { - var self = this; - var reversedRDNsToKeys = {}; + var self = this + var reversedRDNsToKeys = {} // Generate mapping of reversedRDNs(DN) -> routeKey Object.keys(this.routes).forEach(function (key) { - var _dn = self.routes[key].dn; + var _dn = self.routes[key].dn // Ignore non-DN routes such as exop or unbind if (_dn instanceof dn.DN) { - var reversed = _dn.clone(); - reversed.rdns.reverse(); - reversedRDNsToKeys[reversed.format()] = key; + var reversed = _dn.clone() + reversed.rdns.reverse() + reversedRDNsToKeys[reversed.format()] = key } - }); - var output = []; + }) + var output = [] // Reverse-sort on reversedRDS(DN) in order to output routeKey list. // This will place more specific DNs in front of their parents: // 1. dc=test, dc=domain, dc=sub // 2. dc=test, dc=domain // 3. dc=other, dc=foobar Object.keys(reversedRDNsToKeys).sort().reverse().forEach(function (_dn) { - output.push(reversedRDNsToKeys[_dn]); - }); - this._routeKeyCache = output; + output.push(reversedRDNsToKeys[_dn]) + }) + this._routeKeyCache = output } - return this._routeKeyCache; -}; + return this._routeKeyCache +} +Server.prototype._getHandlerChain = function _getHandlerChain (req, res) { + assert.ok(req) -Server.prototype._getHandlerChain = function _getHandlerChain(req, res) { - assert.ok(req); + fireDTraceProbe(req, res) - fireDTraceProbe(req, res); + var self = this + var routes = this.routes + var route // check anonymous bind if (req.protocolOp === Protocol.LDAP_REQ_BIND && @@ -808,75 +766,72 @@ Server.prototype._getHandlerChain = function _getHandlerChain(req, res) { return { backend: self, handlers: [defaultNoOpHandler] - }; + } } - var op = '0x' + req.protocolOp.toString(16); - var self = this; - var routes = this.routes; - var route; + var op = '0x' + req.protocolOp.toString(16) // Special cases are exops, unbinds and abandons. Handle those first. if (req.protocolOp === Protocol.LDAP_REQ_EXTENSION) { - route = routes[req.requestName]; + route = routes[req.requestName] if (route) { return { backend: route.backend, handlers: (route[op] ? route[op] : [noExOpHandler]) - }; + } } else { return { backend: self, handlers: [noExOpHandler] - }; + } } } else if (req.protocolOp === Protocol.LDAP_REQ_UNBIND) { - route = routes['unbind']; + route = routes.unbind if (route) { return { backend: route.backend, handlers: route[op] - }; + } } else { return { backend: self, handlers: [defaultNoOpHandler] - }; + } } } else if (req.protocolOp === Protocol.LDAP_REQ_ABANDON) { return { backend: self, handlers: [defaultNoOpHandler] - }; + } } // Otherwise, match via DN rules - assert.ok(req.dn); - var keys = this._sortedRouteKeys(); - var fallbackHandler = [noSuffixHandler]; + assert.ok(req.dn) + var keys = this._sortedRouteKeys() + var fallbackHandler = [noSuffixHandler] // invalid DNs in non-strict mode are routed to the default handler - var testDN = (typeof (req.dn) === 'string') ? '' : req.dn; + var testDN = (typeof (req.dn) === 'string') ? '' : req.dn for (var i = 0; i < keys.length; i++) { - var suffix = keys[i]; - route = routes[suffix]; - assert.ok(route.dn); + var suffix = keys[i] + route = routes[suffix] + assert.ok(route.dn) // Match a valid route or the route wildcard ('') if (route.dn.equals(testDN) || route.dn.parentOf(testDN) || suffix === '') { if (route[op]) { // We should be good to go. - req.suffix = route.dn; + req.suffix = route.dn return { backend: route.backend, handlers: route[op] - }; + } } else { if (suffix === '') { - break; + break } else { // We found a valid suffix but not a valid operation. // There might be a more generic suffix with a legitimate operation. - fallbackHandler = [defaultHandler]; + fallbackHandler = [defaultHandler] } } } @@ -884,34 +839,31 @@ Server.prototype._getHandlerChain = function _getHandlerChain(req, res) { return { backend: self, handlers: fallbackHandler - }; -}; - + } +} Server.prototype._mount = function (op, name, argv, notDN) { - assert.ok(op); - assert.ok(name !== undefined); - assert.ok(argv); + assert.ok(op) + assert.ok(name !== undefined) + assert.ok(argv) - if (typeof (name) !== 'string') - throw new TypeError('name (string) required'); - if (!argv.length) - throw new Error('at least one handler required'); + if (typeof (name) !== 'string') { throw new TypeError('name (string) required') } + if (!argv.length) { throw new Error('at least one handler required') } - var backend = this; - var index = 0; + var backend = this + var index = 0 if (typeof (argv[0]) === 'object' && !Array.isArray(argv[0])) { - backend = argv[0]; - index = 1; + backend = argv[0] + index = 1 } - var route = this._getRoute(notDN ? name : dn.parse(name), backend); + var route = this._getRoute(notDN ? name : dn.parse(name), backend) - var chain = this._chain.slice(); + var chain = this._chain.slice() argv.slice(index).forEach(function (a) { - chain.push(a); - }); - route['0x' + op.toString(16)] = mergeFunctionArgs(chain); + chain.push(a) + }) + route['0x' + op.toString(16)] = mergeFunctionArgs(chain) - return this; -}; + return this +} diff --git a/lib/url.js b/lib/url.js index 29fa14e..4e1b061 100644 --- a/lib/url.js +++ b/lib/url.js @@ -1,67 +1,66 @@ -// Copyright 2011 Mark Cavage, Inc. All rights reserved. - -var querystring = require('querystring'); -var url = require('url'); -var util = require('util'); - -var dn = require('./dn'); -var filter = require('./filters/index'); +'use strict' +const querystring = require('querystring') +const url = require('url') +const dn = require('./dn') +const filter = require('./filters/') module.exports = { parse: function (urlStr, parseDN) { - var u = url.parse(urlStr); - if (!u.protocol || !(u.protocol === 'ldap:' || u.protocol === 'ldaps:')) - throw new TypeError(urlStr + ' is an invalid LDAP url (protocol)'); + const parsedURL = new url.URL(urlStr) + if (!parsedURL.protocol || !(parsedURL.protocol === 'ldap:' || parsedURL.protocol === 'ldaps:')) { throw new TypeError(urlStr + ' is an invalid LDAP url (protocol)') } - u.secure = (u.protocol === 'ldaps:'); + const u = { + protocol: parsedURL.protocol, + hostname: parsedURL.hostname, + port: parsedURL.port, + pathname: parsedURL.pathname, + search: parsedURL.search, + href: parsedURL.href + } - if (!u.hostname) - u.hostname = 'localhost'; + u.secure = (u.protocol === 'ldaps:') + + if (!u.hostname) { u.hostname = 'localhost' } if (!u.port) { - u.port = (u.secure ? 636 : 389); + u.port = (u.secure ? 636 : 389) } else { - u.port = parseInt(u.port, 10); + u.port = parseInt(u.port, 10) } if (u.pathname) { - u.pathname = querystring.unescape(u.pathname.substr(1)); - u.DN = parseDN ? dn.parse(u.pathname) : u.pathname; + u.pathname = querystring.unescape(u.pathname.substr(1)) + u.DN = parseDN ? dn.parse(u.pathname) : u.pathname } if (u.search) { - u.attributes = []; - var tmp = u.search.substr(1).split('?'); + u.attributes = [] + var tmp = u.search.substr(1).split('?') if (tmp && tmp.length) { if (tmp[0]) { tmp[0].split(',').forEach(function (a) { - u.attributes.push(querystring.unescape(a.trim())); - }); + u.attributes.push(querystring.unescape(a.trim())) + }) } } if (tmp[1]) { - if (tmp[1] !== 'base' && tmp[1] !== 'one' && tmp[1] !== 'sub') - throw new TypeError(urlStr + ' is an invalid LDAP url (scope)'); - u.scope = tmp[1]; + if (tmp[1] !== 'base' && tmp[1] !== 'one' && tmp[1] !== 'sub') { throw new TypeError(urlStr + ' is an invalid LDAP url (scope)') } + u.scope = tmp[1] } if (tmp[2]) { - u.filter = querystring.unescape(tmp[2]); + u.filter = querystring.unescape(tmp[2]) } if (tmp[3]) { - u.extensions = querystring.unescape(tmp[3]); + u.extensions = querystring.unescape(tmp[3]) } - if (!u.scope) - u.scope = 'base'; - if (!u.filter) - u.filter = filter.parseString('(objectclass=*)'); - else - u.filter = filter.parseString(u.filter); + if (!u.scope) { u.scope = 'base' } + if (!u.filter) { u.filter = filter.parseString('(objectclass=*)') } else { u.filter = filter.parseString(u.filter) } } - return u; + return u } -}; +} diff --git a/package.json b/package.json index 8a2e33a..a1eb639 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,9 @@ "verror": "^1.8.1" }, "devDependencies": { + "husky": "^3.0.4", + "snazzy": "^8.0.0", + "standard": "^14.0.2", "tap": "^14.6.1", "uuid": "^3.3.3" }, @@ -47,6 +50,13 @@ "test": "tap --no-cov 'test/**/*.test.js'", "test:cov": "tap 'test/**/*.test.js'", "test:cov:html": "tap --coverage-report=html 'test/**/*.test.js'", - "test:watch": "tap -n -w --no-coverage-report 'test/**/*.test.js'" + "test:watch": "tap -n -w --no-coverage-report 'test/**/*.test.js'", + "lint": "standard 'examples/**/*.js' 'lib/**/*.js' 'test/**/*.js' | snazzy", + "lint:ci": "standard 'examples/**/*.js' 'lib/**/*.js' 'test/**/*.js'" + }, + "husky": { + "hooks": { + "pre-commit": "npm run lint && npm run test" + } } } diff --git a/test/attribute.test.js b/test/attribute.test.js index faaf87f..800529b 100644 --- a/test/attribute.test.js +++ b/test/attribute.test.js @@ -1,163 +1,163 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { Attribute } = require('../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { Attribute } = require('../lib') test('new no args', function (t) { - t.ok(new Attribute()); - t.end(); -}); + t.ok(new Attribute()) + t.end() +}) test('new with args', function (t) { - const attr = new Attribute({ + let attr = new Attribute({ type: 'cn', vals: ['foo', 'bar'] - }); - t.ok(attr); - attr.addValue('baz'); - t.equal(attr.type, 'cn'); - t.equal(attr.vals.length, 3); - t.equal(attr.vals[0], 'foo'); - t.equal(attr.vals[1], 'bar'); - t.equal(attr.vals[2], 'baz'); + }) + t.ok(attr) + attr.addValue('baz') + t.equal(attr.type, 'cn') + t.equal(attr.vals.length, 3) + t.equal(attr.vals[0], 'foo') + t.equal(attr.vals[1], 'bar') + t.equal(attr.vals[2], 'baz') t.throws(function () { - attr = new Attribute('not an object'); - }); + attr = new Attribute('not an object') + }) t.throws(function () { - const typeThatIsNotAString = 1; + const typeThatIsNotAString = 1 attr = new Attribute({ type: typeThatIsNotAString - }); - }); - t.end(); -}); + }) + }) + t.end() +}) test('toBer', function (t) { const attr = new Attribute({ type: 'cn', vals: ['foo', 'bar'] - }); - t.ok(attr); - const ber = new BerWriter(); - attr.toBer(ber); - const reader = new BerReader(ber.buffer); - t.ok(reader.readSequence()); - t.equal(reader.readString(), 'cn'); - t.equal(reader.readSequence(), 0x31); // lber set - t.equal(reader.readString(), 'foo'); - t.equal(reader.readString(), 'bar'); - t.end(); -}); + }) + t.ok(attr) + const ber = new BerWriter() + attr.toBer(ber) + const reader = new BerReader(ber.buffer) + t.ok(reader.readSequence()) + t.equal(reader.readString(), 'cn') + t.equal(reader.readSequence(), 0x31) // lber set + t.equal(reader.readString(), 'foo') + t.equal(reader.readString(), 'bar') + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.startSequence(); - ber.writeString('cn'); - ber.startSequence(0x31); - ber.writeStringArray(['foo', 'bar']); - ber.endSequence(); - ber.endSequence(); + const ber = new BerWriter() + ber.startSequence() + ber.writeString('cn') + ber.startSequence(0x31) + ber.writeStringArray(['foo', 'bar']) + ber.endSequence() + ber.endSequence() - const attr = new Attribute(); - t.ok(attr); - t.ok(attr.parse(new BerReader(ber.buffer))); + const attr = new Attribute() + t.ok(attr) + t.ok(attr.parse(new BerReader(ber.buffer))) - t.equal(attr.type, 'cn'); - t.equal(attr.vals.length, 2); - t.equal(attr.vals[0], 'foo'); - t.equal(attr.vals[1], 'bar'); - t.end(); -}); + t.equal(attr.type, 'cn') + t.equal(attr.vals.length, 2) + t.equal(attr.vals[0], 'foo') + t.equal(attr.vals[1], 'bar') + t.end() +}) test('parse - without 0x31', function (t) { - const ber = new BerWriter; - ber.startSequence(); - ber.writeString('sn'); - ber.endSequence(); + const ber = new BerWriter() + ber.startSequence() + ber.writeString('sn') + ber.endSequence() - const attr = new Attribute; - t.ok(attr); - t.ok(attr.parse(new BerReader(ber.buffer))); + const attr = new Attribute() + t.ok(attr) + t.ok(attr.parse(new BerReader(ber.buffer))) - t.equal(attr.type, 'sn'); - t.equal(attr.vals.length, 0); + t.equal(attr.type, 'sn') + t.equal(attr.vals.length, 0) - t.end(); -}); + t.end() +}) test('toString', function (t) { const attr = new Attribute({ type: 'foobar', vals: ['asdf'] - }); - const expected = attr.toString(); - const actual = JSON.stringify(attr.json); - t.equal(actual, expected); - t.end(); -}); + }) + const expected = attr.toString() + const actual = JSON.stringify(attr.json) + t.equal(actual, expected) + t.end() +}) test('isAttribute', function (t) { - const isA = Attribute.isAttribute; - t.notOk(isA(null)); - t.notOk(isA('asdf')); + const isA = Attribute.isAttribute + t.notOk(isA(null)) + t.notOk(isA('asdf')) t.ok(isA(new Attribute({ type: 'foobar', vals: ['asdf'] - }))); + }))) t.ok(isA({ type: 'foo', vals: ['item', Buffer.alloc(5)], toBer: function () { /* placeholder */ } - })); + })) // bad type in vals t.notOk(isA({ type: 'foo', vals: ['item', null], toBer: function () { /* placeholder */ } - })); + })) - t.end(); -}); + t.end() +}) test('compare', function (t) { - const comp = Attribute.compare; + const comp = Attribute.compare const a = new Attribute({ type: 'foo', vals: ['bar'] - }); + }) const b = new Attribute({ type: 'foo', vals: ['bar'] - }); - const notAnAttribute = 'this is not an attribute'; + }) + const notAnAttribute = 'this is not an attribute' t.throws(function () { - comp(a, notAnAttribute); - }); + comp(a, notAnAttribute) + }) t.throws(function () { - comp(notAnAttribute, b); - }); + comp(notAnAttribute, b) + }) - t.equal(comp(a, b), 0); + t.equal(comp(a, b), 0) // Different types - a.type = 'boo'; - t.equal(comp(a, b), -1); - t.equal(comp(b, a), 1); - a.type = 'foo'; + a.type = 'boo' + t.equal(comp(a, b), -1) + t.equal(comp(b, a), 1) + a.type = 'foo' // Different value counts - a.vals = ['bar', 'baz']; - t.equal(comp(a, b), 1); - t.equal(comp(b, a), -1); + a.vals = ['bar', 'baz'] + t.equal(comp(a, b), 1) + t.equal(comp(b, a), -1) // Different value contents (same count) - a.vals = ['baz']; - t.equal(comp(a, b), 1); - t.equal(comp(b, a), -1); + a.vals = ['baz'] + t.equal(comp(a, b), 1) + t.equal(comp(b, a), -1) - t.end(); -}); + t.end() +}) diff --git a/test/change.test.js b/test/change.test.js index b056c9a..6dd1576 100644 --- a/test/change.test.js +++ b/test/change.test.js @@ -1,13 +1,13 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { Attribute, Change } = require('../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { Attribute, Change } = require('../lib') test('new no args', function (t) { - t.ok(new Change()); - t.end(); -}); + t.ok(new Change()) + t.end() +}) test('new with args', function (t) { const change = new Change({ @@ -16,33 +16,33 @@ test('new with args', function (t) { type: 'cn', vals: ['foo', 'bar'] }) - }); - t.ok(change); + }) + t.ok(change) - t.equal(change.operation, 'add'); - t.equal(change.modification.type, 'cn'); - t.equal(change.modification.vals.length, 2); - t.equal(change.modification.vals[0], 'foo'); - t.equal(change.modification.vals[1], 'bar'); + t.equal(change.operation, 'add') + t.equal(change.modification.type, 'cn') + t.equal(change.modification.vals.length, 2) + t.equal(change.modification.vals[0], 'foo') + t.equal(change.modification.vals[1], 'bar') - t.end(); -}); + t.end() +}) test('validate fields', function (t) { - const c = new Change(); - t.ok(c); + const c = new Change() + t.ok(c) t.throws(function () { - c.operation = 'bogus'; - }); + c.operation = 'bogus' + }) t.throws(function () { - c.modification = {too: 'many', fields: 'here'}; - }); + c.modification = { too: 'many', fields: 'here' } + }) c.modification = { foo: ['bar', 'baz'] - }; - t.ok(c.modification); - t.end(); -}); + } + t.ok(c.modification) + t.end() +}) test('GH-31 (multiple attributes per Change)', function (t) { t.throws(function () { @@ -52,11 +52,11 @@ test('GH-31 (multiple attributes per Change)', function (t) { cn: 'foo', sn: 'bar' } - }); - t.notOk(c); - }); - t.end(); -}); + }) + t.notOk(c) + }) + t.end() +}) test('toBer', function (t) { const change = new Change({ @@ -65,168 +65,167 @@ test('toBer', function (t) { type: 'cn', vals: ['foo', 'bar'] }) - }); - t.ok(change); + }) + t.ok(change) - const ber = new BerWriter(); - change.toBer(ber); - const reader = new BerReader(ber.buffer); - t.ok(reader.readSequence()); - t.equal(reader.readEnumeration(), 0x00); - t.ok(reader.readSequence()); - t.equal(reader.readString(), 'cn'); - t.equal(reader.readSequence(), 0x31); // lber set - t.equal(reader.readString(), 'foo'); - t.equal(reader.readString(), 'bar'); - t.end(); -}); + const ber = new BerWriter() + change.toBer(ber) + const reader = new BerReader(ber.buffer) + t.ok(reader.readSequence()) + t.equal(reader.readEnumeration(), 0x00) + t.ok(reader.readSequence()) + t.equal(reader.readString(), 'cn') + t.equal(reader.readSequence(), 0x31) // lber set + t.equal(reader.readString(), 'foo') + t.equal(reader.readString(), 'bar') + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.startSequence(); - ber.writeEnumeration(0x00); - ber.startSequence(); - ber.writeString('cn'); - ber.startSequence(0x31); - ber.writeStringArray(['foo', 'bar']); - ber.endSequence(); - ber.endSequence(); - ber.endSequence(); + const ber = new BerWriter() + ber.startSequence() + ber.writeEnumeration(0x00) + ber.startSequence() + ber.writeString('cn') + ber.startSequence(0x31) + ber.writeStringArray(['foo', 'bar']) + ber.endSequence() + ber.endSequence() + ber.endSequence() - const change = new Change(); - t.ok(change); - t.ok(change.parse(new BerReader(ber.buffer))); + const change = new Change() + t.ok(change) + t.ok(change.parse(new BerReader(ber.buffer))) - t.equal(change.operation, 'add'); - t.equal(change.modification.type, 'cn'); - t.equal(change.modification.vals.length, 2); - t.equal(change.modification.vals[0], 'foo'); - t.equal(change.modification.vals[1], 'bar'); + t.equal(change.operation, 'add') + t.equal(change.modification.type, 'cn') + t.equal(change.modification.vals.length, 2) + t.equal(change.modification.vals[0], 'foo') + t.equal(change.modification.vals[1], 'bar') - t.end(); -}); + t.end() +}) test('apply - replace', function (t) { - let res; + let res const single = new Change({ operation: 'replace', modification: { type: 'cn', vals: ['new'] } - }); + }) const twin = new Change({ operation: 'replace', - modification: { - type: 'cn', - vals: ['new', 'two'] - } - }); + modification: { + type: 'cn', + vals: ['new', 'two'] + } + }) const empty = new Change({ operation: 'replace', modification: { type: 'cn', vals: [] } - }); + }) // plain - res = Change.apply(single, { cn: ['old'] }); - t.deepEqual(res.cn, ['new']); + res = Change.apply(single, { cn: ['old'] }) + t.deepEqual(res.cn, ['new']) // multiple - res = Change.apply(single, { cn: ['old', 'also'] }); - t.deepEqual(res.cn, ['new']); + res = Change.apply(single, { cn: ['old', 'also'] }) + t.deepEqual(res.cn, ['new']) // empty - res = Change.apply(empty, { cn: ['existing'] }); - t.equal(res.cn, undefined); - t.ok(Object.keys(res).indexOf('cn') === -1); + res = Change.apply(empty, { cn: ['existing'] }) + t.equal(res.cn, undefined) + t.ok(Object.keys(res).indexOf('cn') === -1) - //absent - res = Change.apply(single, { dn: ['otherjunk'] }); - t.deepEqual(res.cn, ['new']); + // absent + res = Change.apply(single, { dn: ['otherjunk'] }) + t.deepEqual(res.cn, ['new']) // scalar formatting "success" - res = Change.apply(single, { cn: 'old' }, true); - t.equal(res.cn, 'new'); + res = Change.apply(single, { cn: 'old' }, true) + t.equal(res.cn, 'new') // scalar formatting "failure" - res = Change.apply(twin, { cn: 'old' }, true); - t.deepEqual(res.cn, ['new', 'two']); + res = Change.apply(twin, { cn: 'old' }, true) + t.deepEqual(res.cn, ['new', 'two']) - t.end(); -}); + t.end() +}) test('apply - add', function (t) { - let res; + let res const single = new Change({ operation: 'add', modification: { type: 'cn', vals: ['new'] } - }); + }) // plain - res = Change.apply(single, { cn: ['old'] }); - t.deepEqual(res.cn, ['old', 'new']); + res = Change.apply(single, { cn: ['old'] }) + t.deepEqual(res.cn, ['old', 'new']) // multiple - res = Change.apply(single, { cn: ['old', 'also'] }); - t.deepEqual(res.cn, ['old', 'also', 'new']); + res = Change.apply(single, { cn: ['old', 'also'] }) + t.deepEqual(res.cn, ['old', 'also', 'new']) - //absent - res = Change.apply(single, { dn: ['otherjunk'] }); - t.deepEqual(res.cn, ['new']); + // absent + res = Change.apply(single, { dn: ['otherjunk'] }) + t.deepEqual(res.cn, ['new']) // scalar formatting "success" - res = Change.apply(single, { }, true); - t.equal(res.cn, 'new'); + res = Change.apply(single, { }, true) + t.equal(res.cn, 'new') // scalar formatting "failure" - res = Change.apply(single, { cn: 'old' }, true); - t.deepEqual(res.cn, ['old', 'new']); + res = Change.apply(single, { cn: 'old' }, true) + t.deepEqual(res.cn, ['old', 'new']) // duplicate add - res = Change.apply(single, { cn: 'new' }); - t.deepEqual(res.cn, ['new']); + res = Change.apply(single, { cn: 'new' }) + t.deepEqual(res.cn, ['new']) - t.end(); -}); + t.end() +}) test('apply - delete', function (t) { - let res; + let res const single = new Change({ operation: 'delete', modification: { type: 'cn', vals: ['old'] } - }); + }) // plain - res = Change.apply(single, { cn: ['old', 'new'] }); - t.deepEqual(res.cn, ['new']); + res = Change.apply(single, { cn: ['old', 'new'] }) + t.deepEqual(res.cn, ['new']) // empty - res = Change.apply(single, { cn: ['old'] }); - t.equal(res.cn, undefined); - t.ok(Object.keys(res).indexOf('cn') === -1); + res = Change.apply(single, { cn: ['old'] }) + t.equal(res.cn, undefined) + t.ok(Object.keys(res).indexOf('cn') === -1) // scalar formatting "success" - res = Change.apply(single, { cn: ['old', 'one'] }, true); - t.equal(res.cn, 'one'); + res = Change.apply(single, { cn: ['old', 'one'] }, true) + t.equal(res.cn, 'one') // scalar formatting "failure" - res = Change.apply(single, { cn: ['old', 'several', 'items'] }, true); - t.deepEqual(res.cn, ['several', 'items']); + res = Change.apply(single, { cn: ['old', 'several', 'items'] }, true) + t.deepEqual(res.cn, ['several', 'items']) + // absent + res = Change.apply(single, { dn: ['otherjunk'] }) + t.ok(res) + t.equal(res.cn, undefined) - //absent - res = Change.apply(single, { dn: ['otherjunk'] }); - t.ok(res); - t.equal(res.cn, undefined); - - t.end(); -}); + t.end() +}) diff --git a/test/client.test.js b/test/client.test.js index 7c698c9..f44c6f7 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -1,94 +1,93 @@ -'use strict'; +'use strict' -const util = require('util'); -const tap = require('tap'); -const uuid = require('uuid'); -const vasync = require('vasync'); -const { getSock } = require('./utils'); -const ldap = require('../lib'); -const { Attribute, Change } = ldap; +const util = require('util') +const tap = require('tap') +const uuid = require('uuid') +const vasync = require('vasync') +const { getSock } = require('./utils') +const ldap = require('../lib') +const { Attribute, Change } = ldap -const SUFFIX = 'dc=test'; -const LDAP_CONNECT_TIMEOUT = process.env.LDAP_CONNECT_TIMEOUT || 0; -const BIND_DN = 'cn=root'; -const BIND_PW = 'secret'; +const SUFFIX = 'dc=test' +const LDAP_CONNECT_TIMEOUT = process.env.LDAP_CONNECT_TIMEOUT || 0 +const BIND_DN = 'cn=root' +const BIND_PW = 'secret' tap.beforeEach((done, t) => { - t.context.socketPath = getSock(); - t.context.server = ldap.createServer(); + t.context.socketPath = getSock() + t.context.server = ldap.createServer() - const server = t.context.server; + const server = t.context.server server.bind(BIND_DN, function (req, res, next) { - if (req.credentials !== BIND_PW) - return next(new ldap.InvalidCredentialsError('Invalid password')); + if (req.credentials !== BIND_PW) { return next(new ldap.InvalidCredentialsError('Invalid password')) } - res.end(); - return next(); - }); + res.end() + return next() + }) server.add(SUFFIX, function (req, res, next) { - res.end(); - return next(); - }); + res.end() + return next() + }) server.compare(SUFFIX, function (req, res, next) { - res.end(req.value === 'test'); - return next(); - }); + res.end(req.value === 'test') + return next() + }) server.del(SUFFIX, function (req, res, next) { - res.end(); - return next(); - }); + res.end() + return next() + }) // LDAP whoami server.exop('1.3.6.1.4.1.4203.1.11.3', function (req, res, next) { - res.value = 'u:xxyyz@EXAMPLE.NET'; - res.end(); - return next(); - }); + res.value = 'u:xxyyz@EXAMPLE.NET' + res.end() + return next() + }) server.modify(SUFFIX, function (req, res, next) { - res.end(); - return next(); - }); + res.end() + return next() + }) server.modifyDN(SUFFIX, function (req, res, next) { - res.end(); - return next(); - }); + res.end() + return next() + }) server.search('dc=slow', function (req, res, next) { res.send({ dn: 'dc=slow', attributes: { - 'you': 'wish', - 'this': 'was', - 'faster': '.' + you: 'wish', + this: 'was', + faster: '.' } - }); + }) setTimeout(function () { - res.end(); - next(); - }, 250); - }); + res.end() + next() + }, 250) + }) server.search('dc=timeout', function (req, res, next) { // Cause the client to timeout by not sending a response. - }); + }) server.search(SUFFIX, function (req, res, next) { if (req.dn.equals('cn=ref,' + SUFFIX)) { - res.send(res.createSearchReference('ldap://localhost')); + res.send(res.createSearchReference('ldap://localhost')) } else if (req.dn.equals('cn=bin,' + SUFFIX)) { res.send(res.createSearchEntry({ objectName: req.dn, attributes: { 'foo;binary': 'wr0gKyDCvCA9IMK+', - 'gb18030': Buffer.from([0xB5, 0xE7, 0xCA, 0xD3, 0xBB, 0xFA]), - 'objectclass': 'binary' + gb18030: Buffer.from([0xB5, 0xE7, 0xCA, 0xD3, 0xBB, 0xFA]), + objectclass: 'binary' } - })); + })) } else { var e = res.createSearchEntry({ objectName: req.dn, @@ -96,23 +95,23 @@ tap.beforeEach((done, t) => { cn: ['unit', 'test'], SN: 'testy' } - }); - res.send(e); - res.send(e); + }) + res.send(e) + res.send(e) } - res.end(); - return next(); - }); + res.end() + return next() + }) server.search('cn=sizelimit', function (req, res, next) { - const sizeLimit = 200; + const sizeLimit = 200 for (let i = 0; i < 1000; i++) { if (req.sizeLimit > 0 && i >= req.sizeLimit) { - break; + break } else if (i > sizeLimit) { - res.end(ldap.LDAP_SIZE_LIMIT_EXCEEDED); - return next(); + res.end(ldap.LDAP_SIZE_LIMIT_EXCEEDED) + return next() } res.send({ dn: util.format('o=%d, cn=sizelimit', i), @@ -120,20 +119,20 @@ tap.beforeEach((done, t) => { o: [i], objectclass: ['pagedResult'] } - }); + }) } - res.end(); - return next(); - }); + res.end() + return next() + }) server.search('cn=paged', function (req, res, next) { - const min = 0; - const max = 1000; + const min = 0 + const max = 1000 - function sendResults(start, end) { - start = (start < min) ? min : start; - end = (end > max || end < min) ? max : end; - let i; + function sendResults (start, end) { + start = (start < min) ? min : start + end = (end > max || end < min) ? max : end + let i for (i = start; i < end; i++) { res.send({ dn: util.format('o=%d, cn=paged', i), @@ -141,78 +140,78 @@ tap.beforeEach((done, t) => { o: [i], objectclass: ['pagedResult'] } - }); + }) } - return i; + return i } - let cookie = null; - let pageSize = 0; + let cookie = null + let pageSize = 0 req.controls.forEach(function (control) { if (control.type === ldap.PagedResultsControl.OID) { - pageSize = control.value.size; - cookie = control.value.cookie; + pageSize = control.value.size + cookie = control.value.cookie } - }); + }) if (cookie && Buffer.isBuffer(cookie)) { // Do simple paging - let first = min; + let first = min if (cookie.length !== 0) { - first = parseInt(cookie.toString(), 10); + first = parseInt(cookie.toString(), 10) } - const last = sendResults(first, first + pageSize); + const last = sendResults(first, first + pageSize) - let resultCookie; + let resultCookie if (last < max) { - resultCookie = Buffer.from(last.toString()); + resultCookie = Buffer.from(last.toString()) } else { - resultCookie = Buffer.from(''); + resultCookie = Buffer.from('') } res.controls.push(new ldap.PagedResultsControl({ value: { size: pageSize, // correctness not required here cookie: resultCookie } - })); - res.end(); - next(); + })) + res.end() + next() } else { // don't allow non-paged searches for this test endpoint - next(new ldap.UnwillingToPerformError()); + next(new ldap.UnwillingToPerformError()) } - }); + }) server.search('cn=pagederr', function (req, res, next) { - let cookie = null; + let cookie = null req.controls.forEach(function (control) { if (control.type === ldap.PagedResultsControl.OID) { - cookie = control.value.cookie; + cookie = control.value.cookie } - }); + }) if (cookie && Buffer.isBuffer(cookie) && cookie.length === 0) { // send first "page" - res.send({ - dn: util.format('o=result, cn=pagederr'), - attributes: { - o: 'result', - objectclass: ['pagedResult'] - } - }); - res.controls.push(new ldap.PagedResultsControl({ - value: { - size: 2, - cookie: Buffer.from('a') - } - })); - res.end(); - return next(); + res.send({ + dn: util.format('o=result, cn=pagederr'), + attributes: { + o: 'result', + objectclass: ['pagedResult'] + } + }) + res.controls.push(new ldap.PagedResultsControl({ + value: { + size: 2, + cookie: Buffer.from('a') + } + })) + res.end() + return next() } else { // send error instead of second page - res.end(ldap.LDAP_SIZE_LIMIT_EXCEEDED); - return next(); + res.end(ldap.LDAP_SIZE_LIMIT_EXCEEDED) + return next() } - }); + }) server.search('dc=empty', function (req, res, next) { res.send({ @@ -221,14 +220,14 @@ tap.beforeEach((done, t) => { member: [], 'member;range=0-1': ['cn=user1, dc=empty', 'cn=user2, dc=empty'] } - }); - res.end(); - return next(); - }); + }) + res.end() + return next() + }) server.search('cn=busy', function (req, res, next) { - next(new ldap.BusyError('too much to do')); - }); + next(new ldap.BusyError('too much to do')) + }) server.search('', function (req, res, next) { if (req.dn.toString() === '') { @@ -237,97 +236,97 @@ tap.beforeEach((done, t) => { attributes: { objectclass: ['RootDSE', 'top'] } - }); - res.end(); + }) + res.end() } else { // Turn away any other requests (since '' is the fallthrough route) - res.errorMessage = 'No tree found for: ' + req.dn.toString(); - res.end(ldap.LDAP_NO_SUCH_OBJECT); + res.errorMessage = 'No tree found for: ' + req.dn.toString() + res.end(ldap.LDAP_NO_SUCH_OBJECT) } - return next(); - }); + return next() + }) server.unbind(function (req, res, next) { - res.end(); - return next(); - }); + res.end() + return next() + }) server.listen(t.context.socketPath, function () { const client = ldap.createClient({ connectTimeout: parseInt(LDAP_CONNECT_TIMEOUT, 10), socketPath: t.context.socketPath - }); - t.context.client = client; + }) + t.context.client = client client.on('connect', () => done()) }) }) tap.afterEach((done, t) => { t.context.client.unbind((err) => { - t.error(err); - t.context.server.close(() => done()); + t.error(err) + t.context.server.close(() => done()) }) }) tap.test('simple bind failure', function (t) { t.context.client.bind(BIND_DN, uuid(), function (err, res) { - t.ok(err); - t.notOk(res); + t.ok(err) + t.notOk(res) - t.ok(err instanceof ldap.InvalidCredentialsError); - t.ok(err instanceof Error); - t.ok(err.dn); - t.ok(err.message); - t.ok(err.stack); + t.ok(err instanceof ldap.InvalidCredentialsError) + t.ok(err instanceof Error) + t.ok(err.dn) + t.ok(err.message) + t.ok(err.stack) - t.end(); - }); -}); + t.end() + }) +}) tap.test('simple bind success', function (t) { t.context.client.bind(BIND_DN, BIND_PW, function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('simple anonymous bind (empty credentials)', function (t) { t.context.client.bind('', '', function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('auto-bind bad credentials', function (t) { const clt = ldap.createClient({ socketPath: t.context.socketPath, bindDN: BIND_DN, bindCredentials: 'totallybogus' - }); + }) clt.once('error', function (err) { - t.equal(err.code, ldap.LDAP_INVALID_CREDENTIALS); - t.ok(clt._socket.destroyed, 'expect socket to be destroyed'); - clt.destroy(); - t.end(); - }); -}); + t.equal(err.code, ldap.LDAP_INVALID_CREDENTIALS) + t.ok(clt._socket.destroyed, 'expect socket to be destroyed') + clt.destroy() + t.end() + }) +}) tap.test('auto-bind success', function (t) { const clt = ldap.createClient({ socketPath: t.context.socketPath, bindDN: BIND_DN, bindCredentials: BIND_PW - }); + }) clt.once('connect', function () { - t.ok(clt); - clt.destroy(); - t.end(); - }); -}); + t.ok(clt) + clt.destroy() + t.end() + }) +}) tap.test('add success', function (t) { const attrs = [ @@ -335,101 +334,101 @@ tap.test('add success', function (t) { type: 'cn', vals: ['test'] }) - ]; + ] t.context.client.add('cn=add, ' + SUFFIX, attrs, function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('add success with object', function (t) { const entry = { cn: ['unit', 'add'], sn: 'test' - }; + } t.context.client.add('cn=add, ' + SUFFIX, entry, function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('compare success', function (t) { t.context.client.compare('cn=compare, ' + SUFFIX, 'cn', 'test', function (err, matched, res) { - t.error(err); - t.ok(matched); - t.ok(res); - t.end(); - }); -}); + t.error(err) + t.ok(matched) + t.ok(res) + t.end() + }) +}) tap.test('compare false', function (t) { t.context.client.compare('cn=compare, ' + SUFFIX, 'cn', 'foo', function (err, matched, res) { - t.error(err); - t.notOk(matched); - t.ok(res); - t.end(); - }); -}); + t.error(err) + t.notOk(matched) + t.ok(res) + t.end() + }) +}) tap.test('compare bad suffix', function (t) { t.context.client.compare('cn=' + uuid(), 'cn', 'foo', function (err, matched, res) { - t.ok(err); - t.ok(err instanceof ldap.NoSuchObjectError); - t.notOk(matched); - t.notOk(res); - t.end(); - }); -}); + t.ok(err) + t.ok(err instanceof ldap.NoSuchObjectError) + t.notOk(matched) + t.notOk(res) + t.end() + }) +}) tap.test('delete success', function (t) { t.context.client.del('cn=delete, ' + SUFFIX, function (err, res) { - t.error(err); - t.ok(res); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.end() + }) +}) tap.test('delete with control (GH-212)', function (t) { const control = new ldap.Control({ type: '1.2.3.4', criticality: false - }); + }) t.context.client.del('cn=delete, ' + SUFFIX, control, function (err, res) { - t.error(err); - t.ok(res); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.end() + }) +}) tap.test('exop success', function (t) { t.context.client.exop('1.3.6.1.4.1.4203.1.11.3', function (err, value, res) { - t.error(err); - t.ok(value); - t.ok(res); - t.equal(value, 'u:xxyyz@EXAMPLE.NET'); - t.end(); - }); -}); + t.error(err) + t.ok(value) + t.ok(res) + t.equal(value, 'u:xxyyz@EXAMPLE.NET') + t.end() + }) +}) tap.test('exop invalid', function (t) { t.context.client.exop('1.2.3.4', function (err, res) { - t.ok(err); - t.ok(err instanceof ldap.ProtocolError); - t.notOk(res); - t.end(); - }); -}); + t.ok(err) + t.ok(err instanceof ldap.ProtocolError) + t.notOk(res) + t.end() + }) +}) tap.test('bogus exop (GH-17)', function (t) { t.context.client.exop('cn=root', function (err) { - t.ok(err); - t.end(); - }); -}); + t.ok(err) + t.end() + }) +}) tap.test('modify success', function (t) { const change = new Change({ @@ -438,14 +437,14 @@ tap.test('modify success', function (t) { type: 'cn', vals: ['test'] }) - }); + }) t.context.client.modify('cn=modify, ' + SUFFIX, change, function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('modify change plain object success', function (t) { const change = new Change({ @@ -453,28 +452,28 @@ tap.test('modify change plain object success', function (t) { modification: { cn: 'test' } - }); + }) t.context.client.modify('cn=modify, ' + SUFFIX, change, function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) // https://github.com/ldapjs/node-ldapjs/pull/435 tap.test('can delete attributes', function (t) { const change = new Change({ type: 'Delete', modification: { cn: null } - }); + }) t.context.client.modify('cn=modify,' + SUFFIX, change, function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('modify array success', function (t) { const changes = [ @@ -491,14 +490,14 @@ tap.test('modify array success', function (t) { type: 'sn' }) }) - ]; + ] t.context.client.modify('cn=modify, ' + SUFFIX, changes, function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('modify change plain object success (GH-31)', function (t) { const change = { @@ -507,553 +506,554 @@ tap.test('modify change plain object success (GH-31)', function (t) { cn: 'test', sn: 'bar' } - }; + } t.context.client.modify('cn=modify, ' + SUFFIX, change, function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('modify DN new RDN only', function (t) { t.context.client.modifyDN('cn=old, ' + SUFFIX, 'cn=new', function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('modify DN new superior', function (t) { t.context.client.modifyDN('cn=old, ' + SUFFIX, 'cn=new, dc=foo', function (err, res) { - t.error(err); - t.ok(res); - t.equal(res.status, 0); - t.end(); - }); -}); + t.error(err) + t.ok(res) + t.equal(res.status, 0) + t.end() + }) +}) tap.test('search basic', function (t) { t.context.client.search('cn=test, ' + SUFFIX, '(objectclass=*)', function (err, res) { - t.error(err); - t.ok(res); - let gotEntry = 0; + t.error(err) + t.ok(res) + let gotEntry = 0 res.on('searchEntry', function (entry) { - t.ok(entry); - t.ok(entry instanceof ldap.SearchEntry); - t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX); - t.ok(entry.attributes); - t.ok(entry.attributes.length); - t.equal(entry.attributes[0].type, 'cn'); - t.equal(entry.attributes[1].type, 'SN'); - t.ok(entry.object); - gotEntry++; - }); + t.ok(entry) + t.ok(entry instanceof ldap.SearchEntry) + t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX) + t.ok(entry.attributes) + t.ok(entry.attributes.length) + t.equal(entry.attributes[0].type, 'cn') + t.equal(entry.attributes[1].type, 'SN') + t.ok(entry.object) + gotEntry++ + }) res.on('error', function (err) { - t.fail(err); - }); + t.fail(err) + }) res.on('end', function (res) { - t.ok(res); - t.ok(res instanceof ldap.SearchResponse); - t.equal(res.status, 0); - t.equal(gotEntry, 2); - t.end(); - }); - }); -}); + t.ok(res) + t.ok(res instanceof ldap.SearchResponse) + t.equal(res.status, 0) + t.equal(gotEntry, 2) + t.end() + }) + }) +}) tap.test('search sizeLimit', function (t) { t.test('over limit', function (t2) { t.context.client.search('cn=sizelimit', {}, function (err, res) { - t2.error(err); + t2.error(err) res.on('error', function (error) { - t2.equal(error.name, 'SizeLimitExceededError'); - t2.end(); - }); - }); - }); + t2.equal(error.name, 'SizeLimitExceededError') + t2.end() + }) + }) + }) t.test('under limit', function (t2) { - const limit = 100; - t.context.client.search('cn=sizelimit', {sizeLimit: limit}, function (err, res) { - t2.error(err); - let count = 0; + const limit = 100 + t.context.client.search('cn=sizelimit', { sizeLimit: limit }, function (err, res) { + t2.error(err) + let count = 0 res.on('searchEntry', function (entry) { - count++; - }); + count++ + }) res.on('end', function () { - t2.pass(); - t2.equal(count, limit); - t2.end(); - }); - res.on('error', t2.error.bind(t)); - }); - }); + t2.pass() + t2.equal(count, limit) + t2.end() + }) + res.on('error', t2.error.bind(t)) + }) + }) t.end() -}); +}) tap.test('search paged', { timeout: 10000 }, function (t) { t.test('paged - no pauses', function (t2) { - let countEntries = 0; - let countPages = 0; - t.context.client.search('cn=paged', {paged: {pageSize: 100}}, function (err, res) { - t2.error(err); - res.on('searchEntry', entryListener); - res.on('page', pageListener); - res.on('error', (err) => t2.error(err)); + let countEntries = 0 + let countPages = 0 + t.context.client.search('cn=paged', { paged: { pageSize: 100 } }, function (err, res) { + t2.error(err) + res.on('searchEntry', entryListener) + res.on('page', pageListener) + res.on('error', (err) => t2.error(err)) res.on('end', function () { - t2.equal(countEntries, 1000); - t2.equal(countPages, 10); - t2.end(); - }); - - t2.tearDown(() => { - res.removeListener('searchEntry', entryListener); - res.removeListener('page', pageListener); + t2.equal(countEntries, 1000) + t2.equal(countPages, 10) + t2.end() }) - function entryListener() { - countEntries += 1; + t2.tearDown(() => { + res.removeListener('searchEntry', entryListener) + res.removeListener('page', pageListener) + }) + + function entryListener () { + countEntries += 1 } function pageListener () { - countPages += 1; + countPages += 1 } - }); - }); + }) + }) t.test('paged - pauses', function (t2) { - let countPages = 0; + let countPages = 0 t.context.client.search('cn=paged', { paged: { pageSize: 100, pagePause: true } }, function (err, res) { - t2.error(err); - res.on('page', pageListener); - res.on('error', (err) => t2.error(err)); + t2.error(err) + res.on('page', pageListener) + res.on('error', (err) => t2.error(err)) res.on('end', function () { - t2.equal(countPages, 9); - t2.end(); - }); + t2.equal(countPages, 9) + t2.end() + }) function pageListener (result, cb) { - countPages++; + countPages++ // cancel after 9 to verify callback usage if (countPages === 9) { // another page should never be encountered res.removeListener('page', pageListener) - .on('page', t2.fail.bind(null, 'unexpected page')); - return cb(new Error()); + .on('page', t2.fail.bind(null, 'unexpected page')) + return cb(new Error()) } - return cb(); + return cb() } - }); - }); + }) + }) t.test('paged - no support (err handled)', function (t2) { t.context.client.search(SUFFIX, { paged: { pageSize: 100 } }, function (err, res) { - t2.error(err); - res.on('pageError', t2.ok.bind(t2)); + t2.error(err) + res.on('pageError', t2.ok.bind(t2)) res.on('end', function () { - t2.pass(); - t2.end(); - }); - }); - }); + t2.pass() + t2.end() + }) + }) + }) t.test('paged - no support (err not handled)', function (t2) { t.context.client.search(SUFFIX, { paged: { pageSize: 100 } }, function (err, res) { - t2.error(err); - res.on('end', t2.fail.bind(t2)); + t2.error(err) + res.on('end', t2.fail.bind(t2)) res.on('error', function (error) { - t2.ok(error); - t2.end(); - }); - }); - }); + t2.ok(error) + t2.end() + }) + }) + }) t.test('paged - redundant control', function (t2) { try { t.context.client.search(SUFFIX, { paged: { pageSize: 100 } }, new ldap.PagedResultsControl(), - function (err, res) { - t2.fail(); - }); + function (err) { + t.error(err) + t2.fail() + }) } catch (e) { - t2.ok(e); - t2.end(); + t2.ok(e) + t2.end() } - }); + }) t.test('paged - handle later error', function (t2) { - let countEntries = 0; - let countPages = 0; + let countEntries = 0 + let countPages = 0 t.context.client.search('cn=pagederr', { paged: { pageSize: 1 } }, function (err, res) { - t2.error(err); + t2.error(err) res.on('searchEntry', function () { - t2.ok(++countEntries); - }); + t2.ok(++countEntries) + }) res.on('page', function () { - t2.ok(++countPages); - }); + t2.ok(++countPages) + }) res.on('error', function (error) { - t2.equal(countEntries, 1); - t2.equal(countPages, 1); - t2.end(); - }); + t2.ok(error) + t2.equal(countEntries, 1) + t2.equal(countPages, 1) + t2.end() + }) res.on('end', function () { - t2.fail('should not be reached'); - }); - }); - }); + t2.fail('should not be reached') + }) + }) + }) - t.end(); -}); + t.end() +}) tap.test('search referral', function (t) { t.context.client.search('cn=ref, ' + SUFFIX, '(objectclass=*)', function (err, res) { - t.error(err); - t.ok(res); - let gotEntry = 0; - let gotReferral = false; + t.error(err) + t.ok(res) + let gotEntry = 0 + let gotReferral = false res.on('searchEntry', function (entry) { - gotEntry++; - }); + gotEntry++ + }) res.on('searchReference', function (referral) { - gotReferral = true; - t.ok(referral); - t.ok(referral instanceof ldap.SearchReference); - t.ok(referral.uris); - t.ok(referral.uris.length); - }); + gotReferral = true + t.ok(referral) + t.ok(referral instanceof ldap.SearchReference) + t.ok(referral.uris) + t.ok(referral.uris.length) + }) res.on('error', function (err) { - t.fail(err); - }); + t.fail(err) + }) res.on('end', function (res) { - t.ok(res); - t.ok(res instanceof ldap.SearchResponse); - t.equal(res.status, 0); - t.equal(gotEntry, 0); - t.ok(gotReferral); - t.end(); - }); - }); -}); + t.ok(res) + t.ok(res instanceof ldap.SearchResponse) + t.equal(res.status, 0) + t.equal(gotEntry, 0) + t.ok(gotReferral) + t.end() + }) + }) +}) tap.test('search rootDSE', function (t) { t.context.client.search('', '(objectclass=*)', function (err, res) { - t.error(err); - t.ok(res); + t.error(err) + t.ok(res) res.on('searchEntry', function (entry) { - t.ok(entry); - t.equal(entry.dn.toString(), ''); - t.ok(entry.attributes); - t.ok(entry.object); - }); + t.ok(entry) + t.equal(entry.dn.toString(), '') + t.ok(entry.attributes) + t.ok(entry.object) + }) res.on('error', function (err) { - t.fail(err); - }); + t.fail(err) + }) res.on('end', function (res) { - t.ok(res); - t.ok(res instanceof ldap.SearchResponse); - t.equal(res.status, 0); - t.end(); - }); - }); -}); + t.ok(res) + t.ok(res instanceof ldap.SearchResponse) + t.equal(res.status, 0) + t.end() + }) + }) +}) tap.test('search empty attribute', function (t) { t.context.client.search('dc=empty', '(objectclass=*)', function (err, res) { - t.error(err); - t.ok(res); - let gotEntry = 0; + t.error(err) + t.ok(res) + let gotEntry = 0 res.on('searchEntry', function (entry) { - var obj = entry.toObject(); - t.equal('dc=empty', obj.dn); - t.ok(obj.member); - t.equal(obj.member.length, 0); - t.ok(obj['member;range=0-1']); - t.ok(obj['member;range=0-1'].length); - gotEntry++; - }); + var obj = entry.toObject() + t.equal('dc=empty', obj.dn) + t.ok(obj.member) + t.equal(obj.member.length, 0) + t.ok(obj['member;range=0-1']) + t.ok(obj['member;range=0-1'].length) + gotEntry++ + }) res.on('error', function (err) { - t.fail(err); - }); + t.fail(err) + }) res.on('end', function (res) { - t.ok(res); - t.ok(res instanceof ldap.SearchResponse); - t.equal(res.status, 0); - t.equal(gotEntry, 1); - t.end(); - }); - }); -}); + t.ok(res) + t.ok(res instanceof ldap.SearchResponse) + t.equal(res.status, 0) + t.equal(gotEntry, 1) + t.end() + }) + }) +}) tap.test('GH-21 binary attributes', function (t) { t.context.client.search('cn=bin, ' + SUFFIX, '(objectclass=*)', function (err, res) { - t.error(err); - t.ok(res); - let gotEntry = 0; - const expect = Buffer.from('\u00bd + \u00bc = \u00be', 'utf8'); - const expect2 = Buffer.from([0xB5, 0xE7, 0xCA, 0xD3, 0xBB, 0xFA]); + t.error(err) + t.ok(res) + let gotEntry = 0 + const expect = Buffer.from('\u00bd + \u00bc = \u00be', 'utf8') + const expect2 = Buffer.from([0xB5, 0xE7, 0xCA, 0xD3, 0xBB, 0xFA]) res.on('searchEntry', function (entry) { - t.ok(entry); - t.ok(entry instanceof ldap.SearchEntry); - t.equal(entry.dn.toString(), 'cn=bin, ' + SUFFIX); - t.ok(entry.attributes); - t.ok(entry.attributes.length); - t.equal(entry.attributes[0].type, 'foo;binary'); - t.equal(entry.attributes[0].vals[0], expect.toString('base64')); + t.ok(entry) + t.ok(entry instanceof ldap.SearchEntry) + t.equal(entry.dn.toString(), 'cn=bin, ' + SUFFIX) + t.ok(entry.attributes) + t.ok(entry.attributes.length) + t.equal(entry.attributes[0].type, 'foo;binary') + t.equal(entry.attributes[0].vals[0], expect.toString('base64')) t.equal(entry.attributes[0].buffers[0].toString('base64'), - expect.toString('base64')); + expect.toString('base64')) - t.ok(entry.attributes[1].type, 'gb18030'); - t.equal(entry.attributes[1].buffers.length, 1); - t.equal(expect2.length, entry.attributes[1].buffers[0].length); - for (var i = 0; i < expect2.length; i++) - t.equal(expect2[i], entry.attributes[1].buffers[0][i]); + t.ok(entry.attributes[1].type, 'gb18030') + t.equal(entry.attributes[1].buffers.length, 1) + t.equal(expect2.length, entry.attributes[1].buffers[0].length) + for (var i = 0; i < expect2.length; i++) { t.equal(expect2[i], entry.attributes[1].buffers[0][i]) } - t.ok(entry.object); - gotEntry++; - }); + t.ok(entry.object) + gotEntry++ + }) res.on('error', function (err) { - t.fail(err); - }); + t.fail(err) + }) res.on('end', function (res) { - t.ok(res); - t.ok(res instanceof ldap.SearchResponse); - t.equal(res.status, 0); - t.equal(gotEntry, 1); - t.end(); - }); - }); -}); + t.ok(res) + t.ok(res instanceof ldap.SearchResponse) + t.equal(res.status, 0) + t.equal(gotEntry, 1) + t.end() + }) + }) +}) tap.test('GH-23 case insensitive attribute filtering', function (t) { const opts = { filter: '(objectclass=*)', attributes: ['Cn'] - }; + } t.context.client.search('cn=test, ' + SUFFIX, opts, function (err, res) { - t.error(err); - t.ok(res); - let gotEntry = 0; + t.error(err) + t.ok(res) + let gotEntry = 0 res.on('searchEntry', function (entry) { - t.ok(entry); - t.ok(entry instanceof ldap.SearchEntry); - t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX); - t.ok(entry.attributes); - t.ok(entry.attributes.length); - t.equal(entry.attributes[0].type, 'cn'); - t.ok(entry.object); - gotEntry++; - }); + t.ok(entry) + t.ok(entry instanceof ldap.SearchEntry) + t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX) + t.ok(entry.attributes) + t.ok(entry.attributes.length) + t.equal(entry.attributes[0].type, 'cn') + t.ok(entry.object) + gotEntry++ + }) res.on('error', function (err) { - t.fail(err); - }); + t.fail(err) + }) res.on('end', function (res) { - t.ok(res); - t.ok(res instanceof ldap.SearchResponse); - t.equal(res.status, 0); - t.equal(gotEntry, 2); - t.end(); - }); - }); -}); + t.ok(res) + t.ok(res instanceof ldap.SearchResponse) + t.equal(res.status, 0) + t.equal(gotEntry, 2) + t.end() + }) + }) +}) tap.test('GH-24 attribute selection of *', function (t) { const opts = { filter: '(objectclass=*)', attributes: ['*'] - }; + } t.context.client.search('cn=test, ' + SUFFIX, opts, function (err, res) { - t.error(err); - t.ok(res); - let gotEntry = 0; + t.error(err) + t.ok(res) + let gotEntry = 0 res.on('searchEntry', function (entry) { - t.ok(entry); - t.ok(entry instanceof ldap.SearchEntry); - t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX); - t.ok(entry.attributes); - t.ok(entry.attributes.length); - t.equal(entry.attributes[0].type, 'cn'); - t.equal(entry.attributes[1].type, 'SN'); - t.ok(entry.object); - gotEntry++; - }); + t.ok(entry) + t.ok(entry instanceof ldap.SearchEntry) + t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX) + t.ok(entry.attributes) + t.ok(entry.attributes.length) + t.equal(entry.attributes[0].type, 'cn') + t.equal(entry.attributes[1].type, 'SN') + t.ok(entry.object) + gotEntry++ + }) res.on('error', function (err) { - t.fail(err); - }); + t.fail(err) + }) res.on('end', function (res) { - t.ok(res); - t.ok(res instanceof ldap.SearchResponse); - t.equal(res.status, 0); - t.equal(gotEntry, 2); - t.end(); - }); - }); -}); + t.ok(res) + t.ok(res instanceof ldap.SearchResponse) + t.equal(res.status, 0) + t.equal(gotEntry, 2) + t.end() + }) + }) +}) tap.test('idle timeout', function (t) { - t.context.client.idleTimeout = 250; - function premature() { - t.error(true); + t.context.client.idleTimeout = 250 + function premature () { + t.error(true) } - t.context.client.on('idle', premature); + t.context.client.on('idle', premature) t.context.client.search('dc=slow', 'objectclass=*', function (err, res) { - t.error(err); + t.error(err) res.on('searchEntry', function (res) { - t.ok(res); - }); + t.ok(res) + }) res.on('error', function (err) { - t.error(err); - }); + t.error(err) + }) res.on('end', function () { var late = setTimeout(function () { - t.error(false, 'too late'); - }, 500); + t.error(false, 'too late') + }, 500) // It's ok to go idle now - t.context.client.removeListener('idle', premature); + t.context.client.removeListener('idle', premature) t.context.client.on('idle', function () { - clearTimeout(late); - t.context.client.removeAllListeners('idle'); - t.context.client.idleTimeout = 0; - t.end(); - }); - }); - }); -}); + clearTimeout(late) + t.context.client.removeAllListeners('idle') + t.context.client.idleTimeout = 0 + t.end() + }) + }) + }) +}) tap.test('setup action', function (t) { const setupClient = ldap.createClient({ - connectTimeout: parseInt(LDAP_CONNECT_TIMEOUT, 10), - socketPath: t.context.socketPath - }); + connectTimeout: parseInt(LDAP_CONNECT_TIMEOUT, 10), + socketPath: t.context.socketPath + }) setupClient.on('setup', function (clt, cb) { clt.bind(BIND_DN, BIND_PW, function (err, res) { - t.error(err); - cb(err); - }); - }); - setupClient.search(SUFFIX, {scope: 'base'}, function (err, res) { - t.error(err); - t.ok(res); + t.error(err) + cb(err) + }) + }) + setupClient.search(SUFFIX, { scope: 'base' }, function (err, res) { + t.error(err) + t.ok(res) res.on('end', function () { - setupClient.destroy(); - t.end(); - }); - }); -}); + setupClient.destroy() + t.end() + }) + }) +}) tap.test('setup reconnect', function (t) { const rClient = ldap.createClient({ - connectTimeout: parseInt(LDAP_CONNECT_TIMEOUT, 10), - socketPath: t.context.socketPath, - reconnect: true - }); + connectTimeout: parseInt(LDAP_CONNECT_TIMEOUT, 10), + socketPath: t.context.socketPath, + reconnect: true + }) rClient.on('setup', function (clt, cb) { clt.bind(BIND_DN, BIND_PW, function (err, res) { - t.error(err); - cb(err); - }); - }); + t.error(err) + cb(err) + }) + }) - function doSearch(_, cb) { - rClient.search(SUFFIX, {scope: 'base'}, function (err, res) { - t.error(err); + function doSearch (_, cb) { + rClient.search(SUFFIX, { scope: 'base' }, function (err, res) { + t.error(err) res.on('end', function () { - cb(); - }); - }); + cb() + }) + }) } vasync.pipeline({ funcs: [ doSearch, - function cleanDisconnect(_, cb) { - t.ok(rClient.connected); - rClient.once('close', function (had_err) { - t.error(had_err); - t.equal(rClient.connected, false); - cb(); - }); - rClient.unbind(); + function cleanDisconnect (_, cb) { + t.ok(rClient.connected) + rClient.once('close', function (err) { + t.error(err) + t.equal(rClient.connected, false) + cb() + }) + rClient.unbind() }, doSearch, - function simulateError(_, cb) { - const msg = 'fake socket error'; + function simulateError (_, cb) { + const msg = 'fake socket error' rClient.once('error', function (err) { - t.equal(err.message, msg); - t.ok(err); - }); - rClient.once('close', function (had_err) { + t.equal(err.message, msg) + t.ok(err) + }) + rClient.once('close', function () { // can't test had_err because the socket error is being faked - cb(); - }); - rClient._socket.emit('error', new Error(msg)); + cb() + }) + rClient._socket.emit('error', new Error(msg)) }, doSearch ] }, function (err) { - t.error(err); - rClient.destroy(); - t.end(); - }); -}); + t.error(err) + rClient.destroy() + t.end() + }) +}) tap.test('setup abort', function (t) { const setupClient = ldap.createClient({ - connectTimeout: parseInt(LDAP_CONNECT_TIMEOUT, 10), - socketPath: t.context.socketPath, - reconnect: true - }); - const message = "It's a trap!"; + connectTimeout: parseInt(LDAP_CONNECT_TIMEOUT, 10), + socketPath: t.context.socketPath, + reconnect: true + }) + const message = "It's a trap!" setupClient.on('setup', function (clt, cb) { // simulate failure - t.ok(clt); - cb(new Error(message)); - }); + t.ok(clt) + cb(new Error(message)) + }) setupClient.on('setupError', function (err) { - t.ok(true); - t.equal(err.message, message); - setupClient.destroy(); - t.end(); - }); -}); + t.ok(true) + t.equal(err.message, message) + setupClient.destroy() + t.end() + }) +}) tap.test('abort reconnect', function (t) { const abortClient = ldap.createClient({ connectTimeout: parseInt(LDAP_CONNECT_TIMEOUT, 10), socketPath: 'an invalid path', reconnect: true - }); - var retryCount = 0; + }) + var retryCount = 0 abortClient.on('connectError', function () { - ++retryCount; - }); + ++retryCount + }) abortClient.once('connectError', function () { - t.ok(true); + t.ok(true) abortClient.once('destroy', function () { - t.ok(retryCount < 3); - t.end(); - }); - abortClient.destroy(); - }); -}); + t.ok(retryCount < 3) + t.end() + }) + abortClient.destroy() + }) +}) tap.test('reconnect max retries', function (t) { - const RETRIES = 5; + const RETRIES = 5 const rClient = ldap.createClient({ connectTimeout: 100, socketPath: 'an invalid path', @@ -1063,123 +1063,126 @@ tap.test('reconnect max retries', function (t) { initialDelay: 10, maxDelay: 100 } - }); - let count = 0; + }) + let count = 0 rClient.on('connectError', function () { - count++; - }); + count++ + }) rClient.on('error', function (err) { - t.equal(count, RETRIES); - rClient.destroy(); - t.end(); - }); -}); + t.ok(err) + t.equal(count, RETRIES) + rClient.destroy() + t.end() + }) +}) tap.test('reconnect on server close', function (t) { const clt = ldap.createClient({ socketPath: t.context.socketPath, reconnect: true - }); + }) clt.on('setup', function (sclt, cb) { sclt.bind(BIND_DN, BIND_PW, function (err, res) { - t.error(err); - cb(err); - }); - }); + t.error(err) + cb(err) + }) + }) clt.once('connect', function () { - t.ok(clt._socket); + t.ok(clt._socket) clt.once('connect', function () { - t.ok(true, 'successful reconnect'); - clt.destroy(); - t.end(); - }); + t.ok(true, 'successful reconnect') + clt.destroy() + t.end() + }) // Simulate server-side close - clt._socket.destroy(); - }); -}); + clt._socket.destroy() + }) +}) tap.test('no auto-reconnect on unbind', function (t) { const clt = ldap.createClient({ socketPath: t.context.socketPath, reconnect: true - }); + }) clt.on('setup', function (sclt, cb) { sclt.bind(BIND_DN, BIND_PW, function (err, res) { - t.error(err); - cb(err); - }); - }); + t.error(err) + cb(err) + }) + }) clt.once('connect', function () { clt.once('connect', function () { - t.error(new Error('client should not reconnect')); - }); + t.error(new Error('client should not reconnect')) + }) clt.once('close', function () { - t.ok(true, 'initial close'); + t.ok(true, 'initial close') setImmediate(function () { - t.ok(!clt.connected, 'should not be connected'); - t.ok(!clt.connecting, 'should not be connecting'); - clt.destroy(); - t.end(); - }); - }); + t.ok(!clt.connected, 'should not be connected') + t.ok(!clt.connecting, 'should not be connecting') + clt.destroy() + t.end() + }) + }) - clt.unbind(); - }); -}); + clt.unbind() + }) +}) tap.test('abandon (GH-27)', function (t) { // FIXME: test abandoning a real request t.context.client.abandon(401876543, function (err) { - t.error(err); - t.end(); - }); -}); + t.error(err) + t.end() + }) +}) tap.test('search timeout (GH-51)', function (t) { - t.context.client.timeout = 250; + t.context.client.timeout = 250 t.context.client.search('dc=timeout', 'objectclass=*', function (err, res) { - t.error(err); + t.error(err) res.on('error', function () { - t.end(); - }); - }); -}); + t.end() + }) + }) +}) tap.test('resultError handling', function (t) { - const client = t.context.client; + const client = t.context.client vasync.pipeline({ funcs: [errSearch, cleanSearch] }, function (err) { - t.error(err); - client.removeListener('resultError', error1); - client.removeListener('resultError', error2); - t.end(); - }); + t.error(err) + client.removeListener('resultError', error1) + client.removeListener('resultError', error2) + t.end() + }) - function errSearch(_, cb) { - client.once('resultError', error1); + function errSearch (_, cb) { + client.once('resultError', error1) client.search('cn=busy', {}, function (err, res) { + t.error(err) res.once('error', function (error) { - t.equal(error.name, 'BusyError'); - cb(); - }); - }); + t.equal(error.name, 'BusyError') + cb() + }) + }) } - function cleanSearch(_, cb) { - client.on('resultError', error2); + function cleanSearch (_, cb) { + client.on('resultError', error2) client.search(SUFFIX, {}, function (err, res) { + t.error(err) res.once('end', function () { - t.pass(); - cb(); - }); - }); + t.pass() + cb() + }) + }) } function error1 (error) { - t.equal(error.name, 'BusyError'); + t.equal(error.name, 'BusyError') } function error2 () { t.fail('should not get error') } -}); +}) diff --git a/test/controls/control.test.js b/test/controls/control.test.js index b654261..6175974 100644 --- a/test/controls/control.test.js +++ b/test/controls/control.test.js @@ -1,53 +1,53 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { Control, getControl } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { Control, getControl } = require('../../lib') test('new no args', function (t) { - t.ok(new Control()); - t.end(); -}); + t.ok(new Control()) + t.end() +}) test('new with args', function (t) { const c = new Control({ type: '2.16.840.1.113730.3.4.2', criticality: true - }); - t.ok(c); - t.equal(c.type, '2.16.840.1.113730.3.4.2'); - t.ok(c.criticality); - t.end(); -}); + }) + t.ok(c) + t.equal(c.type, '2.16.840.1.113730.3.4.2') + t.ok(c.criticality) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.startSequence(); - ber.writeString('2.16.840.1.113730.3.4.2'); - ber.writeBoolean(true); - ber.writeString('foo'); - ber.endSequence(); + const ber = new BerWriter() + ber.startSequence() + ber.writeString('2.16.840.1.113730.3.4.2') + ber.writeBoolean(true) + ber.writeString('foo') + ber.endSequence() - const c = getControl(new BerReader(ber.buffer)); + const c = getControl(new BerReader(ber.buffer)) - t.ok(c); - t.equal(c.type, '2.16.840.1.113730.3.4.2'); - t.ok(c.criticality); - t.equal(c.value.toString('utf8'), 'foo'); - t.end(); -}); + t.ok(c) + t.equal(c.type, '2.16.840.1.113730.3.4.2') + t.ok(c.criticality) + t.equal(c.value.toString('utf8'), 'foo') + t.end() +}) test('parse no value', function (t) { - const ber = new BerWriter(); - ber.startSequence(); - ber.writeString('2.16.840.1.113730.3.4.2'); - ber.endSequence(); + const ber = new BerWriter() + ber.startSequence() + ber.writeString('2.16.840.1.113730.3.4.2') + ber.endSequence() - const c = getControl(new BerReader(ber.buffer)); + const c = getControl(new BerReader(ber.buffer)) - t.ok(c); - t.equal(c.type, '2.16.840.1.113730.3.4.2'); - t.equal(c.criticality, false); - t.notOk(c.value, null); - t.end(); -}); + t.ok(c) + t.equal(c.type, '2.16.840.1.113730.3.4.2') + t.equal(c.criticality, false) + t.notOk(c.value, null) + t.end() +}) diff --git a/test/controls/entry_change_notification_control.test.js b/test/controls/entry_change_notification_control.test.js index 8b410c3..c29a97b 100644 --- a/test/controls/entry_change_notification_control.test.js +++ b/test/controls/entry_change_notification_control.test.js @@ -1,13 +1,13 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { getControl, EntryChangeNotificationControl } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { getControl, EntryChangeNotificationControl } = require('../../lib') test('new no args', function (t) { - t.ok(new EntryChangeNotificationControl()); - t.end(); -}); + t.ok(new EntryChangeNotificationControl()) + t.end() +}) test('new with args', function (t) { const c = new EntryChangeNotificationControl({ @@ -18,27 +18,27 @@ test('new with args', function (t) { previousDN: 'cn=foobarbazcar', changeNumber: 123456789 } - }); - t.ok(c); - t.equal(c.type, '2.16.840.1.113730.3.4.7'); - t.ok(c.criticality); - t.equal(c.value.changeType, 8); - t.equal(c.value.previousDN, 'cn=foobarbazcar'); - t.equal(c.value.changeNumber, 123456789); + }) + t.ok(c) + t.equal(c.type, '2.16.840.1.113730.3.4.7') + t.ok(c.criticality) + t.equal(c.value.changeType, 8) + t.equal(c.value.previousDN, 'cn=foobarbazcar') + t.equal(c.value.changeNumber, 123456789) - const writer = new BerWriter(); - c.toBer(writer); - const reader = new BerReader(writer.buffer); - const psc = getControl(reader); - t.ok(psc); - t.equal(psc.type, '2.16.840.1.113730.3.4.7'); - t.ok(psc.criticality); - t.equal(psc.value.changeType, 8); - t.equal(psc.value.previousDN, 'cn=foobarbazcar'); - t.equal(psc.value.changeNumber, 123456789); + const writer = new BerWriter() + c.toBer(writer) + const reader = new BerReader(writer.buffer) + const psc = getControl(reader) + t.ok(psc) + t.equal(psc.type, '2.16.840.1.113730.3.4.7') + t.ok(psc.criticality) + t.equal(psc.value.changeType, 8) + t.equal(psc.value.previousDN, 'cn=foobarbazcar') + t.equal(psc.value.changeNumber, 123456789) - t.end(); -}); + t.end() +}) test('tober', function (t) { const psc = new EntryChangeNotificationControl({ @@ -49,18 +49,18 @@ test('tober', function (t) { previousDN: 'cn=foobarbazcar', changeNumber: 123456789 } - }); + }) - const ber = new BerWriter(); - psc.toBer(ber); + const ber = new BerWriter() + psc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, '2.16.840.1.113730.3.4.7'); - t.ok(c.criticality); - t.equal(c.value.changeType, 8); - t.equal(c.value.previousDN, 'cn=foobarbazcar'); - t.equal(c.value.changeNumber, 123456789); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, '2.16.840.1.113730.3.4.7') + t.ok(c.criticality) + t.equal(c.value.changeType, 8) + t.equal(c.value.previousDN, 'cn=foobarbazcar') + t.equal(c.value.changeNumber, 123456789) - t.end(); -}); + t.end() +}) diff --git a/test/controls/paged_results_control.test.js b/test/controls/paged_results_control.test.js index bbb3476..39b3fb1 100644 --- a/test/controls/paged_results_control.test.js +++ b/test/controls/paged_results_control.test.js @@ -1,13 +1,13 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { getControl, PagedResultsControl } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { getControl, PagedResultsControl } = require('../../lib') test('new no args', function (t) { - t.ok(new PagedResultsControl()); - t.end(); -}); + t.ok(new PagedResultsControl()) + t.end() +}) test('new with args', function (t) { const c = new PagedResultsControl({ @@ -17,25 +17,25 @@ test('new with args', function (t) { size: 1000, cookie: Buffer.from([1, 2, 3]) } - }); - t.ok(c); - t.equal(c.type, '1.2.840.113556.1.4.319'); - t.ok(c.criticality); - t.equal(c.value.size, 1000); + }) + t.ok(c) + t.equal(c.type, '1.2.840.113556.1.4.319') + t.ok(c.criticality) + t.equal(c.value.size, 1000) t.is(Buffer.compare(c.value.cookie, Buffer.from([1, 2, 3])), 0) - const writer = new BerWriter(); - c.toBer(writer); - const reader = new BerReader(writer.buffer); - const psc = getControl(reader); - t.ok(psc); - t.equal(psc.type, '1.2.840.113556.1.4.319'); - t.ok(psc.criticality); - t.equal(psc.value.size, 1000); + const writer = new BerWriter() + c.toBer(writer) + const reader = new BerReader(writer.buffer) + const psc = getControl(reader) + t.ok(psc) + t.equal(psc.type, '1.2.840.113556.1.4.319') + t.ok(psc.criticality) + t.equal(psc.value.size, 1000) t.is(Buffer.compare(psc.value.cookie, Buffer.from([1, 2, 3])), 0) - t.end(); -}); + t.end() +}) test('tober', function (t) { const psc = new PagedResultsControl({ @@ -45,17 +45,17 @@ test('tober', function (t) { size: 20, cookie: Buffer.alloc(0) } - }); + }) - const ber = new BerWriter(); - psc.toBer(ber); + const ber = new BerWriter() + psc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, '1.2.840.113556.1.4.319'); - t.ok(c.criticality); - t.equal(c.value.size, 20); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, '1.2.840.113556.1.4.319') + t.ok(c.criticality) + t.equal(c.value.size, 20) t.is(Buffer.compare(c.value.cookie, Buffer.alloc(0)), 0) - t.end(); -}); + t.end() +}) diff --git a/test/controls/persistent_search_control.test.js b/test/controls/persistent_search_control.test.js index 0ab1df8..414de54 100644 --- a/test/controls/persistent_search_control.test.js +++ b/test/controls/persistent_search_control.test.js @@ -1,32 +1,28 @@ // Copyright 2011 Mark Cavage, Inc. All rights reserved. -var test = require('tap').test; +var test = require('tap').test -var asn1 = require('asn1'); +var asn1 = require('asn1') -var BerReader = asn1.BerReader; -var BerWriter = asn1.BerWriter; -var getControl; -var PersistentSearchControl; +var BerReader = asn1.BerReader +var BerWriter = asn1.BerWriter +var getControl +var PersistentSearchControl - - -///--- Tests +/// --- Tests test('load library', function (t) { - PersistentSearchControl = require('../../lib').PersistentSearchControl; - t.ok(PersistentSearchControl); - getControl = require('../../lib').getControl; - t.ok(getControl); - t.end(); -}); - + PersistentSearchControl = require('../../lib').PersistentSearchControl + t.ok(PersistentSearchControl) + getControl = require('../../lib').getControl + t.ok(getControl) + t.end() +}) test('new no args', function (t) { - t.ok(new PersistentSearchControl()); - t.end(); -}); - + t.ok(new PersistentSearchControl()) + t.end() +}) test('new with args', function (t) { var c = new PersistentSearchControl({ @@ -37,47 +33,46 @@ test('new with args', function (t) { changesOnly: false, returnECs: false } - }); - t.ok(c); - t.equal(c.type, '2.16.840.1.113730.3.4.3'); - t.ok(c.criticality); + }) + t.ok(c) + t.equal(c.type, '2.16.840.1.113730.3.4.3') + t.ok(c.criticality) - t.equal(c.value.changeTypes, 15); - t.equal(c.value.changesOnly, false); - t.equal(c.value.returnECs, false); + t.equal(c.value.changeTypes, 15) + t.equal(c.value.changesOnly, false) + t.equal(c.value.returnECs, false) + var writer = new BerWriter() + c.toBer(writer) + var reader = new BerReader(writer.buffer) + var psc = getControl(reader) + t.ok(psc) + t.equal(psc.type, '2.16.840.1.113730.3.4.3') + t.ok(psc.criticality) + t.equal(psc.value.changeTypes, 15) + t.equal(psc.value.changesOnly, false) + t.equal(psc.value.returnECs, false) - var writer = new BerWriter(); - c.toBer(writer); - var reader = new BerReader(writer.buffer); - var psc = getControl(reader); - t.ok(psc); - t.equal(psc.type, '2.16.840.1.113730.3.4.3'); - t.ok(psc.criticality); - t.equal(psc.value.changeTypes, 15); - t.equal(psc.value.changesOnly, false); - t.equal(psc.value.returnECs, false); - - t.end(); -}); + t.end() +}) test('getControl with args', function (t) { var buf = Buffer.from([ 0x30, 0x26, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x33, 0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01, - 0xff, 0x01, 0x01, 0xff]); + 0xff, 0x01, 0x01, 0xff]) - var ber = new BerReader(buf); - var psc = getControl(ber); - t.ok(psc); - t.equal(psc.type, '2.16.840.1.113730.3.4.3'); - t.equal(psc.criticality, false); - t.equal(psc.value.changeTypes, 15); - t.equal(psc.value.changesOnly, true); - t.equal(psc.value.returnECs, true); - t.end(); -}); + var ber = new BerReader(buf) + var psc = getControl(ber) + t.ok(psc) + t.equal(psc.type, '2.16.840.1.113730.3.4.3') + t.equal(psc.criticality, false) + t.equal(psc.value.changeTypes, 15) + t.equal(psc.value.changesOnly, true) + t.equal(psc.value.returnECs, true) + t.end() +}) test('tober', function (t) { var psc = new PersistentSearchControl({ @@ -88,17 +83,17 @@ test('tober', function (t) { changesOnly: false, returnECs: false } - }); + }) - var ber = new BerWriter(); - psc.toBer(ber); + var ber = new BerWriter() + psc.toBer(ber) - var c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, '2.16.840.1.113730.3.4.3'); - t.ok(c.criticality); - t.equal(c.value.changeTypes, 15); - t.equal(c.value.changesOnly, false); - t.equal(c.value.returnECs, false); - t.end(); -}); + var c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, '2.16.840.1.113730.3.4.3') + t.ok(c.criticality) + t.equal(c.value.changeTypes, 15) + t.equal(c.value.changesOnly, false) + t.equal(c.value.returnECs, false) + t.end() +}) diff --git a/test/controls/server_side_sorting_control_request.test.js b/test/controls/server_side_sorting_control_request.test.js index 3dbdbaa..a2cd85c 100644 --- a/test/controls/server_side_sorting_control_request.test.js +++ b/test/controls/server_side_sorting_control_request.test.js @@ -1,13 +1,13 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { getControl, ServerSideSortingRequestControl: SSSRControl } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { getControl, ServerSideSortingRequestControl: SSSRControl } = require('../../lib') test('new no args', function (t) { - t.ok(new SSSRControl()); - t.end(); -}); + t.ok(new SSSRControl()) + t.end() +}) test('new with args', function (t) { const c = new SSSRControl({ @@ -15,15 +15,15 @@ test('new with args', function (t) { value: { attributeType: 'sn' } - }); - t.ok(c); - t.equal(c.type, '1.2.840.113556.1.4.473'); - t.ok(c.criticality); - t.equal(c.value.length, 1); - t.equal(c.value[0].attributeType, 'sn'); + }) + t.ok(c) + t.equal(c.type, '1.2.840.113556.1.4.473') + t.ok(c.criticality) + t.equal(c.value.length, 1) + t.equal(c.value[0].attributeType, 'sn') - t.end(); -}); + t.end() +}) test('toBer - object', function (t) { const sssc = new SSSRControl({ @@ -32,21 +32,22 @@ test('toBer - object', function (t) { attributeType: 'sn', orderingRule: 'caseIgnoreOrderingMatch', reverseOrder: true - }}); + } + }) - const ber = new BerWriter(); - sssc.toBer(ber); + const ber = new BerWriter() + sssc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, '1.2.840.113556.1.4.473'); - t.ok(c.criticality); - t.equal(c.value[0].attributeType, 'sn'); - t.equal(c.value[0].orderingRule, 'caseIgnoreOrderingMatch'); - t.equal(c.value[0].reverseOrder, true); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, '1.2.840.113556.1.4.473') + t.ok(c.criticality) + t.equal(c.value[0].attributeType, 'sn') + t.equal(c.value[0].orderingRule, 'caseIgnoreOrderingMatch') + t.equal(c.value[0].reverseOrder, true) - t.end(); -}); + t.end() +}) test('toBer - array', function (t) { const sssc = new SSSRControl({ @@ -62,33 +63,33 @@ test('toBer - array', function (t) { orderingRule: 'caseIgnoreOrderingMatch' } ] - }); + }) - const ber = new BerWriter(); - sssc.toBer(ber); + const ber = new BerWriter() + sssc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, '1.2.840.113556.1.4.473'); - t.ok(c.criticality); - t.equal(c.value.length, 2); - t.equal(c.value[0].attributeType, 'sn'); - t.equal(c.value[0].orderingRule, 'caseIgnoreOrderingMatch'); - t.equal(c.value[0].reverseOrder, true); - t.equal(c.value[1].attributeType, 'givenName'); - t.equal(c.value[1].orderingRule, 'caseIgnoreOrderingMatch'); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, '1.2.840.113556.1.4.473') + t.ok(c.criticality) + t.equal(c.value.length, 2) + t.equal(c.value[0].attributeType, 'sn') + t.equal(c.value[0].orderingRule, 'caseIgnoreOrderingMatch') + t.equal(c.value[0].reverseOrder, true) + t.equal(c.value[1].attributeType, 'givenName') + t.equal(c.value[1].orderingRule, 'caseIgnoreOrderingMatch') - t.end(); -}); + t.end() +}) test('toBer - empty', function (t) { - const sssc = new SSSRControl(); - const ber = new BerWriter(); - sssc.toBer(ber); + const sssc = new SSSRControl() + const ber = new BerWriter() + sssc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, '1.2.840.113556.1.4.473'); - t.equal(c.value.length, 0); - t.end(); -}); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, '1.2.840.113556.1.4.473') + t.equal(c.value.length, 0) + t.end() +}) diff --git a/test/controls/server_side_sorting_control_response.test.js b/test/controls/server_side_sorting_control_response.test.js index f9e6926..7b094f7 100644 --- a/test/controls/server_side_sorting_control_response.test.js +++ b/test/controls/server_side_sorting_control_response.test.js @@ -1,18 +1,18 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const ldap = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const ldap = require('../../lib') const { getControl, ServerSideSortingResponseControl: SSSResponseControl } = ldap -const OID = '1.2.840.113556.1.4.474'; +const OID = '1.2.840.113556.1.4.474' test('new no args', function (t) { - const c = new SSSResponseControl(); - t.ok(c); - t.equal(c.type, OID); - t.equal(c.criticality, false); - t.end(); -}); + const c = new SSSResponseControl() + t.ok(c) + t.equal(c.type, OID) + t.equal(c.criticality, false) + t.end() +}) test('new with args', function (t) { const c = new SSSResponseControl({ @@ -21,82 +21,85 @@ test('new with args', function (t) { result: ldap.LDAP_SUCCESS, failedAttribute: 'cn' } - }); - t.ok(c); - t.equal(c.type, OID); - t.equal(c.criticality, false); - t.equal(c.value.result, ldap.LDAP_SUCCESS); - t.equal(c.value.failedAttribute, 'cn'); + }) + t.ok(c) + t.equal(c.type, OID) + t.equal(c.criticality, false) + t.equal(c.value.result, ldap.LDAP_SUCCESS) + t.equal(c.value.failedAttribute, 'cn') - t.end(); -}); + t.end() +}) test('toBer - success', function (t) { const sssc = new SSSResponseControl({ value: { result: ldap.LDAP_SUCCESS, failedAttribute: 'foobar' - }}); + } + }) - const ber = new BerWriter(); - sssc.toBer(ber); + const ber = new BerWriter() + sssc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, '1.2.840.113556.1.4.474'); - t.equal(c.criticality, false); - t.equal(c.value.result, ldap.LDAP_SUCCESS); - t.notOk(c.value.failedAttribute); - t.end(); -}); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, '1.2.840.113556.1.4.474') + t.equal(c.criticality, false) + t.equal(c.value.result, ldap.LDAP_SUCCESS) + t.notOk(c.value.failedAttribute) + t.end() +}) test('toBer - simple failure', function (t) { const sssc = new SSSResponseControl({ value: { result: ldap.LDAP_NO_SUCH_ATTRIBUTE - }}); + } + }) - const ber = new BerWriter(); - sssc.toBer(ber); + const ber = new BerWriter() + sssc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, OID); - t.equal(c.criticality, false); - t.equal(c.value.result, ldap.LDAP_NO_SUCH_ATTRIBUTE); - t.notOk(c.value.failedAttribute); - t.end(); -}); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, OID) + t.equal(c.criticality, false) + t.equal(c.value.result, ldap.LDAP_NO_SUCH_ATTRIBUTE) + t.notOk(c.value.failedAttribute) + t.end() +}) test('toBer - detailed failure', function (t) { const sssc = new SSSResponseControl({ value: { result: ldap.LDAP_NO_SUCH_ATTRIBUTE, failedAttribute: 'foobar' - }}); + } + }) - const ber = new BerWriter(); - sssc.toBer(ber); + const ber = new BerWriter() + sssc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, OID); - t.equal(c.criticality, false); - t.equal(c.value.result, ldap.LDAP_NO_SUCH_ATTRIBUTE); - t.equal(c.value.failedAttribute, 'foobar'); - t.end(); -}); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, OID) + t.equal(c.criticality, false) + t.equal(c.value.result, ldap.LDAP_NO_SUCH_ATTRIBUTE) + t.equal(c.value.failedAttribute, 'foobar') + t.end() +}) test('toBer - empty', function (t) { - const sssc = new SSSResponseControl(); - const ber = new BerWriter(); - sssc.toBer(ber); + const sssc = new SSSResponseControl() + const ber = new BerWriter() + sssc.toBer(ber) - const c = getControl(new BerReader(ber.buffer)); - t.ok(c); - t.equal(c.type, OID); - t.equal(c.criticality, false); - t.notOk(c.value.result); - t.notOk(c.value.failedAttribute); - t.end(); -}); + const c = getControl(new BerReader(ber.buffer)) + t.ok(c) + t.equal(c.type, OID) + t.equal(c.criticality, false) + t.notOk(c.value.result) + t.notOk(c.value.failedAttribute) + t.end() +}) diff --git a/test/dn.test.js b/test/dn.test.js index 055928f..0928069 100644 --- a/test/dn.test.js +++ b/test/dn.test.js @@ -1,234 +1,234 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { dn } = require('../lib'); +const { test } = require('tap') +const { dn } = require('../lib') test('parse basic', function (t) { - const DN_STR = 'cn=mark, ou=people, o=joyent'; - const name = dn.parse(DN_STR); - t.ok(name); - t.ok(name.rdns); - t.ok(Array.isArray(name.rdns)); - t.equal(3, name.rdns.length); + const DN_STR = 'cn=mark, ou=people, o=joyent' + const name = dn.parse(DN_STR) + t.ok(name) + t.ok(name.rdns) + t.ok(Array.isArray(name.rdns)) + t.equal(3, name.rdns.length) name.rdns.forEach(function (rdn) { - t.equal('object', typeof (rdn)); - }); - t.equal(name.toString(), DN_STR); - t.end(); -}); + t.equal('object', typeof (rdn)) + }) + t.equal(name.toString(), DN_STR) + t.end() +}) test('parse escaped', function (t) { - const DN_STR = 'cn=m\\,ark, ou=people, o=joyent'; - const name = dn.parse(DN_STR); - t.ok(name); - t.ok(name.rdns); - t.ok(Array.isArray(name.rdns)); - t.equal(3, name.rdns.length); + const DN_STR = 'cn=m\\,ark, ou=people, o=joyent' + const name = dn.parse(DN_STR) + t.ok(name) + t.ok(name.rdns) + t.ok(Array.isArray(name.rdns)) + t.equal(3, name.rdns.length) name.rdns.forEach(function (rdn) { - t.equal('object', typeof (rdn)); - }); - t.equal(name.toString(), DN_STR); - t.end(); -}); + t.equal('object', typeof (rdn)) + }) + t.equal(name.toString(), DN_STR) + t.end() +}) test('parse compound', function (t) { - const DN_STR = 'cn=mark+sn=cavage, ou=people, o=joyent'; - const name = dn.parse(DN_STR); - t.ok(name); - t.ok(name.rdns); - t.ok(Array.isArray(name.rdns)); - t.equal(3, name.rdns.length); + const DN_STR = 'cn=mark+sn=cavage, ou=people, o=joyent' + const name = dn.parse(DN_STR) + t.ok(name) + t.ok(name.rdns) + t.ok(Array.isArray(name.rdns)) + t.equal(3, name.rdns.length) name.rdns.forEach(function (rdn) { - t.equal('object', typeof (rdn)); - }); - t.equal(name.toString(), DN_STR); - t.end(); -}); + t.equal('object', typeof (rdn)) + }) + t.equal(name.toString(), DN_STR) + t.end() +}) test('parse quoted', function (t) { - const DN_STR = 'cn="mark+sn=cavage", ou=people, o=joyent'; - const ESCAPE_STR = 'cn=mark\\+sn\\=cavage, ou=people, o=joyent'; - const name = dn.parse(DN_STR); - t.ok(name); - t.ok(name.rdns); - t.ok(Array.isArray(name.rdns)); - t.equal(3, name.rdns.length); + const DN_STR = 'cn="mark+sn=cavage", ou=people, o=joyent' + const ESCAPE_STR = 'cn=mark\\+sn\\=cavage, ou=people, o=joyent' + const name = dn.parse(DN_STR) + t.ok(name) + t.ok(name.rdns) + t.ok(Array.isArray(name.rdns)) + t.equal(3, name.rdns.length) name.rdns.forEach(function (rdn) { - t.equal('object', typeof (rdn)); - }); - t.equal(name.toString(), ESCAPE_STR); - t.end(); -}); + t.equal('object', typeof (rdn)) + }) + t.equal(name.toString(), ESCAPE_STR) + t.end() +}) test('equals', function (t) { - const dn1 = dn.parse('cn=foo,dc=bar'); - t.ok(dn1.equals('cn=foo,dc=bar')); - t.ok(!dn1.equals('cn=foo1,dc=bar')); - t.ok(dn1.equals(dn.parse('cn=foo,dc=bar'))); - t.ok(!dn1.equals(dn.parse('cn=foo2,dc=bar'))); - t.end(); -}); + const dn1 = dn.parse('cn=foo,dc=bar') + t.ok(dn1.equals('cn=foo,dc=bar')) + t.ok(!dn1.equals('cn=foo1,dc=bar')) + t.ok(dn1.equals(dn.parse('cn=foo,dc=bar'))) + t.ok(!dn1.equals(dn.parse('cn=foo2,dc=bar'))) + t.end() +}) test('child of', function (t) { - const dn1 = dn.parse('cn=foo,dc=bar'); - t.ok(dn1.childOf('dc=bar')); - t.ok(!dn1.childOf('dc=moo')); - t.ok(!dn1.childOf('dc=foo')); - t.ok(!dn1.childOf('cn=foo,dc=bar')); + const dn1 = dn.parse('cn=foo,dc=bar') + t.ok(dn1.childOf('dc=bar')) + t.ok(!dn1.childOf('dc=moo')) + t.ok(!dn1.childOf('dc=foo')) + t.ok(!dn1.childOf('cn=foo,dc=bar')) - t.ok(dn1.childOf(dn.parse('dc=bar'))); - t.end(); -}); + t.ok(dn1.childOf(dn.parse('dc=bar'))) + t.end() +}) test('parent of', function (t) { - const dn1 = dn.parse('cn=foo,dc=bar'); - t.ok(dn1.parentOf('cn=moo,cn=foo,dc=bar')); - t.ok(!dn1.parentOf('cn=moo,cn=bar,dc=foo')); - t.ok(!dn1.parentOf('cn=foo,dc=bar')); + const dn1 = dn.parse('cn=foo,dc=bar') + t.ok(dn1.parentOf('cn=moo,cn=foo,dc=bar')) + t.ok(!dn1.parentOf('cn=moo,cn=bar,dc=foo')) + t.ok(!dn1.parentOf('cn=foo,dc=bar')) - t.ok(dn1.parentOf(dn.parse('cn=moo,cn=foo,dc=bar'))); - t.end(); -}); + t.ok(dn1.parentOf(dn.parse('cn=moo,cn=foo,dc=bar'))) + t.end() +}) test('DN parent', function (t) { - const _dn = dn.parse('cn=foo,ou=bar'); - const parent1 = _dn.parent(); - const parent2 = parent1.parent(); - t.ok(parent1.equals('ou=bar')); - t.ok(parent2.equals('')); - t.equal(parent2.parent(), null); - t.end(); -}); + const _dn = dn.parse('cn=foo,ou=bar') + const parent1 = _dn.parent() + const parent2 = parent1.parent() + t.ok(parent1.equals('ou=bar')) + t.ok(parent2.equals('')) + t.equal(parent2.parent(), null) + t.end() +}) test('empty DNs', function (t) { - const _dn = dn.parse(''); - const _dn2 = dn.parse('cn=foo'); - t.ok(_dn.isEmpty()); - t.notOk(_dn2.isEmpty()); - t.notOk(_dn.equals('cn=foo')); - t.notOk(_dn2.equals('')); - t.ok(_dn.parentOf('cn=foo')); - t.notOk(_dn.childOf('cn=foo')); - t.notOk(_dn2.parentOf('')); - t.ok(_dn2.childOf('')); - t.end(); -}); + const _dn = dn.parse('') + const _dn2 = dn.parse('cn=foo') + t.ok(_dn.isEmpty()) + t.notOk(_dn2.isEmpty()) + t.notOk(_dn.equals('cn=foo')) + t.notOk(_dn2.equals('')) + t.ok(_dn.parentOf('cn=foo')) + t.notOk(_dn.childOf('cn=foo')) + t.notOk(_dn2.parentOf('')) + t.ok(_dn2.childOf('')) + t.end() +}) test('case insensitive attribute names', function (t) { - const dn1 = dn.parse('CN=foo,dc=bar'); - t.ok(dn1.equals('cn=foo,dc=bar')); - t.ok(dn1.equals(dn.parse('cn=foo,DC=bar'))); - t.end(); -}); + const dn1 = dn.parse('CN=foo,dc=bar') + t.ok(dn1.equals('cn=foo,dc=bar')) + t.ok(dn1.equals(dn.parse('cn=foo,DC=bar'))) + t.end() +}) test('format', function (t) { - const DN_ORDER = dn.parse('sn=bar+cn=foo,ou=test'); - const DN_QUOTE = dn.parse('cn="foo",ou=test'); - const DN_QUOTE2 = dn.parse('cn=" foo",ou=test'); - const DN_SPACE = dn.parse('cn=foo,ou=test'); - const DN_SPACE2 = dn.parse('cn=foo ,ou=test'); - const DN_CASE = dn.parse('CN=foo,Ou=test'); + const DN_ORDER = dn.parse('sn=bar+cn=foo,ou=test') + const DN_QUOTE = dn.parse('cn="foo",ou=test') + const DN_QUOTE2 = dn.parse('cn=" foo",ou=test') + const DN_SPACE = dn.parse('cn=foo,ou=test') + const DN_SPACE2 = dn.parse('cn=foo ,ou=test') + const DN_CASE = dn.parse('CN=foo,Ou=test') - t.equal(DN_ORDER.format({keepOrder: false}), 'cn=foo+sn=bar, ou=test'); - t.equal(DN_ORDER.format({keepOrder: true}), 'sn=bar+cn=foo, ou=test'); + t.equal(DN_ORDER.format({ keepOrder: false }), 'cn=foo+sn=bar, ou=test') + t.equal(DN_ORDER.format({ keepOrder: true }), 'sn=bar+cn=foo, ou=test') - t.equal(DN_QUOTE.format({keepQuote: false}), 'cn=foo, ou=test'); - t.equal(DN_QUOTE.format({keepQuote: true}), 'cn="foo", ou=test'); - t.equal(DN_QUOTE2.format({keepQuote: false}), 'cn=" foo", ou=test'); - t.equal(DN_QUOTE2.format({keepQuote: true}), 'cn=" foo", ou=test'); + t.equal(DN_QUOTE.format({ keepQuote: false }), 'cn=foo, ou=test') + t.equal(DN_QUOTE.format({ keepQuote: true }), 'cn="foo", ou=test') + t.equal(DN_QUOTE2.format({ keepQuote: false }), 'cn=" foo", ou=test') + t.equal(DN_QUOTE2.format({ keepQuote: true }), 'cn=" foo", ou=test') - t.equal(DN_SPACE.format({keepSpace: false}), 'cn=foo, ou=test'); - t.equal(DN_SPACE.format({keepSpace: true}), 'cn=foo,ou=test'); - t.equal(DN_SPACE.format({skipSpace: true}), 'cn=foo,ou=test'); - t.equal(DN_SPACE2.format({keepSpace: false}), 'cn=foo, ou=test'); - t.equal(DN_SPACE2.format({keepSpace: true}), 'cn=foo ,ou=test'); - t.equal(DN_SPACE2.format({skipSpace: true}), 'cn=foo,ou=test'); + t.equal(DN_SPACE.format({ keepSpace: false }), 'cn=foo, ou=test') + t.equal(DN_SPACE.format({ keepSpace: true }), 'cn=foo,ou=test') + t.equal(DN_SPACE.format({ skipSpace: true }), 'cn=foo,ou=test') + t.equal(DN_SPACE2.format({ keepSpace: false }), 'cn=foo, ou=test') + t.equal(DN_SPACE2.format({ keepSpace: true }), 'cn=foo ,ou=test') + t.equal(DN_SPACE2.format({ skipSpace: true }), 'cn=foo,ou=test') - t.equal(DN_CASE.format({keepCase: false}), 'cn=foo, ou=test'); - t.equal(DN_CASE.format({keepCase: true}), 'CN=foo, Ou=test'); - t.equal(DN_CASE.format({upperName: true}), 'CN=foo, OU=test'); - t.end(); -}); + t.equal(DN_CASE.format({ keepCase: false }), 'cn=foo, ou=test') + t.equal(DN_CASE.format({ keepCase: true }), 'CN=foo, Ou=test') + t.equal(DN_CASE.format({ upperName: true }), 'CN=foo, OU=test') + t.end() +}) test('set format', function (t) { - const _dn = dn.parse('uid="user", sn=bar+cn=foo, dc=test , DC=com'); - t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test, dc=com'); - _dn.setFormat({keepOrder: true}); - t.equal(_dn.toString(), 'uid=user, sn=bar+cn=foo, dc=test, dc=com'); - _dn.setFormat({keepQuote: true}); - t.equal(_dn.toString(), 'uid="user", cn=foo+sn=bar, dc=test, dc=com'); - _dn.setFormat({keepSpace: true}); - t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test , dc=com'); - _dn.setFormat({keepCase: true}); - t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test, DC=com'); - _dn.setFormat({upperName: true}); - t.equal(_dn.toString(), 'UID=user, CN=foo+SN=bar, DC=test, DC=com'); - t.end(); -}); + const _dn = dn.parse('uid="user", sn=bar+cn=foo, dc=test , DC=com') + t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test, dc=com') + _dn.setFormat({ keepOrder: true }) + t.equal(_dn.toString(), 'uid=user, sn=bar+cn=foo, dc=test, dc=com') + _dn.setFormat({ keepQuote: true }) + t.equal(_dn.toString(), 'uid="user", cn=foo+sn=bar, dc=test, dc=com') + _dn.setFormat({ keepSpace: true }) + t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test , dc=com') + _dn.setFormat({ keepCase: true }) + t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test, DC=com') + _dn.setFormat({ upperName: true }) + t.equal(_dn.toString(), 'UID=user, CN=foo+SN=bar, DC=test, DC=com') + t.end() +}) test('format persists across clone', function (t) { - const _dn = dn.parse('uid="user", sn=bar+cn=foo, dc=test , DC=com'); - const OUT = 'UID="user", CN=foo+SN=bar, DC=test, DC=com'; - _dn.setFormat({keepQuote: true, upperName: true}); - const clone = _dn.clone(); - t.equals(_dn.toString(), OUT); - t.equals(clone.toString(), OUT); - t.end(); -}); + const _dn = dn.parse('uid="user", sn=bar+cn=foo, dc=test , DC=com') + const OUT = 'UID="user", CN=foo+SN=bar, DC=test, DC=com' + _dn.setFormat({ keepQuote: true, upperName: true }) + const clone = _dn.clone() + t.equals(_dn.toString(), OUT) + t.equals(clone.toString(), OUT) + t.end() +}) test('initialization', function (t) { - const dn1 = new dn.DN(); - t.ok(dn1); - t.equals(dn1.toString(), ''); - t.ok(dn1.isEmpty(), 'DN with no initializer defaults to null DN'); + const dn1 = new dn.DN() + t.ok(dn1) + t.equals(dn1.toString(), '') + t.ok(dn1.isEmpty(), 'DN with no initializer defaults to null DN') const data = [ new dn.RDN({ foo: 'bar' }), new dn.RDN({ o: 'base' }) - ]; - const dn2 = new dn.DN(data); - t.ok(dn2); - t.equals(dn2.toString(), 'foo=bar, o=base'); - t.ok(!dn2.isEmpty()); + ] + const dn2 = new dn.DN(data) + t.ok(dn2) + t.equals(dn2.toString(), 'foo=bar, o=base') + t.ok(!dn2.isEmpty()) - t.end(); -}); + t.end() +}) test('array functions', function (t) { - const dn1 = dn.parse('a=foo, b=bar, c=baz'); - t.ok(dn1); - t.equal(dn1.toString(), 'a=foo, b=bar, c=baz'); + const dn1 = dn.parse('a=foo, b=bar, c=baz') + t.ok(dn1) + t.equal(dn1.toString(), 'a=foo, b=bar, c=baz') - t.ok(dn1.reverse()); - t.equal(dn1.toString(), 'c=baz, b=bar, a=foo'); + t.ok(dn1.reverse()) + t.equal(dn1.toString(), 'c=baz, b=bar, a=foo') - let rdn = dn1.pop(); - t.ok(rdn); - t.equal(dn1.toString(), 'c=baz, b=bar'); + let rdn = dn1.pop() + t.ok(rdn) + t.equal(dn1.toString(), 'c=baz, b=bar') - t.ok(dn1.push(rdn)); - t.equal(dn1.toString(), 'c=baz, b=bar, a=foo'); + t.ok(dn1.push(rdn)) + t.equal(dn1.toString(), 'c=baz, b=bar, a=foo') - rdn = dn1.shift(); - t.ok(rdn); - t.equal(dn1.toString(), 'b=bar, a=foo'); + rdn = dn1.shift() + t.ok(rdn) + t.equal(dn1.toString(), 'b=bar, a=foo') - t.ok(dn1.unshift(rdn)); - t.equal(dn1.toString(), 'c=baz, b=bar, a=foo'); + t.ok(dn1.unshift(rdn)) + t.equal(dn1.toString(), 'c=baz, b=bar, a=foo') - t.end(); -}); + t.end() +}) test('isDN duck-testing', function (t) { - const valid = dn.parse('cn=foo'); - const isDN = dn.DN.isDN; - t.notOk(isDN(null)); - t.notOk(isDN('cn=foo')); - t.ok(isDN(valid)); + const valid = dn.parse('cn=foo') + const isDN = dn.DN.isDN + t.notOk(isDN(null)) + t.notOk(isDN('cn=foo')) + t.ok(isDN(valid)) const duck = { - rdns: [ {look: 'ma'}, {a: 'dn'} ], - toString: function () { return 'look=ma, a=dn'; } - }; - t.ok(isDN(duck)); - t.end(); -}); + rdns: [{ look: 'ma' }, { a: 'dn' }], + toString: function () { return 'look=ma, a=dn' } + } + t.ok(isDN(duck)) + t.end() +}) diff --git a/test/errors.test.js b/test/errors.test.js index 637ae79..a2c592a 100644 --- a/test/errors.test.js +++ b/test/errors.test.js @@ -1,35 +1,35 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { LDAPError, ConnectionError, AbandonedError, TimeoutError, LDAP_OTHER } = require('../lib'); +const { test } = require('tap') +const { LDAPError, ConnectionError, AbandonedError, TimeoutError, LDAP_OTHER } = require('../lib') test('basic error', function (t) { - const msg = 'mymsg'; - const err = new LDAPError(msg, null, null); - t.ok(err); - t.equal(err.name, 'LDAPError'); - t.equal(err.code, LDAP_OTHER); - t.equal(err.dn, ''); - t.equal(err.message, msg); - t.end(); -}); + const msg = 'mymsg' + const err = new LDAPError(msg, null, null) + t.ok(err) + t.equal(err.name, 'LDAPError') + t.equal(err.code, LDAP_OTHER) + t.equal(err.dn, '') + t.equal(err.message, msg) + t.end() +}) test('"custom" errors', function (t) { const errors = [ - { name: 'ConnectionError', func: ConnectionError }, - { name: 'AbandonedError', func: AbandonedError }, - { name: 'TimeoutError', func: TimeoutError } - ]; + { name: 'ConnectionError', Func: ConnectionError }, + { name: 'AbandonedError', Func: AbandonedError }, + { name: 'TimeoutError', Func: TimeoutError } + ] errors.forEach(function (entry) { - const msg = entry.name + 'msg'; - const err = new entry.func(msg); - t.ok(err); - t.equal(err.name, entry.name); - t.equal(err.code, LDAP_OTHER); - t.equal(err.dn, ''); - t.equal(err.message, msg); - }); + const msg = entry.name + 'msg' + const err = new entry.Func(msg) + t.ok(err) + t.equal(err.name, entry.name) + t.equal(err.code, LDAP_OTHER) + t.equal(err.dn, '') + t.equal(err.message, msg) + }) - t.end(); -}); + t.end() +}) diff --git a/test/filters/and.test.js b/test/filters/and.test.js index 7fd9235..694f612 100644 --- a/test/filters/and.test.js +++ b/test/filters/and.test.js @@ -1,55 +1,54 @@ -'use strict'; - -const { test } = require('tap'); -const { filters: { EqualityFilter, AndFilter } } = require('../../lib'); +'use strict' +const { test } = require('tap') +const { filters: { EqualityFilter, AndFilter } } = require('../../lib') test('Construct no args', function (t) { - t.ok(new AndFilter()); - t.end(); -}); + t.ok(new AndFilter()) + t.end() +}) test('Construct args', function (t) { - const f = new AndFilter(); + const f = new AndFilter() f.addFilter(new EqualityFilter({ attribute: 'foo', value: 'bar' - })); + })) f.addFilter(new EqualityFilter({ attribute: 'zig', value: 'zag' - })); - t.ok(f); - t.equal(f.toString(), '(&(foo=bar)(zig=zag))'); - t.end(); -}); + })) + t.ok(f) + t.equal(f.toString(), '(&(foo=bar)(zig=zag))') + t.end() +}) test('match true', function (t) { - const f = new AndFilter(); + const f = new AndFilter() f.addFilter(new EqualityFilter({ attribute: 'foo', value: 'bar' - })); + })) f.addFilter(new EqualityFilter({ attribute: 'zig', value: 'zag' - })); - t.ok(f); - t.ok(f.matches({ foo: 'bar', zig: 'zag' })); - t.end(); -}); + })) + t.ok(f) + t.ok(f.matches({ foo: 'bar', zig: 'zag' })) + t.end() +}) test('match false', function (t) { - const f = new AndFilter(); + const f = new AndFilter() f.addFilter(new EqualityFilter({ attribute: 'foo', value: 'bar' - })); + })) f.addFilter(new EqualityFilter({ attribute: 'zig', value: 'zag' - })); - t.ok(f); - t.ok(!f.matches({ foo: 'bar', zig: 'zonk' })); - t.end(); -}); + })) + t.ok(f) + t.ok(!f.matches({ foo: 'bar', zig: 'zonk' })) + t.end() +}) diff --git a/test/filters/approx.test.js b/test/filters/approx.test.js index a35144a..e615e98 100644 --- a/test/filters/approx.test.js +++ b/test/filters/approx.test.js @@ -1,85 +1,85 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { filters: { ApproximateFilter } } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { filters: { ApproximateFilter } } = require('../../lib') test('Construct no args', function (t) { - const f = new ApproximateFilter(); - t.ok(f); - t.ok(!f.attribute); - t.ok(!f.value); - t.end(); -}); + const f = new ApproximateFilter() + t.ok(f) + t.ok(!f.attribute) + t.ok(!f.value) + t.end() +}) test('Construct args', function (t) { const f = new ApproximateFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar'); - t.equal(f.toString(), '(foo~=bar)'); - t.end(); -}); + }) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar') + t.equal(f.toString(), '(foo~=bar)') + t.end() +}) test('GH-109 = escape value only in toString()', function (t) { const 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(); -}); + }) + 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('parse ok', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeString('bar'); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeString('bar') - const f = new ApproximateFilter(); - t.ok(f); - t.ok(f.parse(new BerReader(writer.buffer))); - t.end(); -}); + const f = new ApproximateFilter() + t.ok(f) + t.ok(f.parse(new BerReader(writer.buffer))) + t.end() +}) test('parse bad', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeInt(20); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeInt(20) - const f = new ApproximateFilter(); - t.ok(f); + const f = new ApproximateFilter() + t.ok(f) try { - f.parse(new BerReader(writer.buffer)); - t.fail('Should have thrown InvalidAsn1Error'); + f.parse(new BerReader(writer.buffer)) + t.fail('Should have thrown InvalidAsn1Error') } catch (e) { - t.equal(e.name, 'InvalidAsn1Error'); + t.equal(e.name, 'InvalidAsn1Error') } - t.end(); -}); + t.end() +}) test('GH-109 = to ber uses plain values', function (t) { let f = new ApproximateFilter({ attribute: 'foo', value: 'ba(r)' - }); - t.ok(f); - const writer = new BerWriter(); - f.toBer(writer); + }) + t.ok(f) + const writer = new BerWriter() + f.toBer(writer) - f = new ApproximateFilter(); - t.ok(f); + f = new ApproximateFilter() + t.ok(f) - const reader = new BerReader(writer.buffer); - reader.readSequence(); - t.ok(f.parse(reader)); + const 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(); -}); + 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 9a09b30..402c0f4 100644 --- a/test/filters/eq.test.js +++ b/test/filters/eq.test.js @@ -1,167 +1,167 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { filters: { EqualityFilter } } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { filters: { EqualityFilter } } = require('../../lib') test('Construct no args', function (t) { - const f = new EqualityFilter(); - t.ok(f); - t.ok(!f.attribute); - t.ok(!f.value); - t.end(); -}); + const f = new EqualityFilter() + t.ok(f) + t.ok(!f.attribute) + t.ok(!f.value) + t.end() +}) test('Construct args', function (t) { const f = new EqualityFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar'); - t.equal(f.toString(), '(foo=bar)'); - t.end(); -}); + }) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar') + t.equal(f.toString(), '(foo=bar)') + t.end() +}) test('GH-109 = escape value only in toString()', function (t) { const 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(); -}); + }) + 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) { const f = new EqualityFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(f.matches({ foo: 'bar' })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: 'bar' })) + t.end() +}) test('match multiple', function (t) { const f = new EqualityFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(f.matches({ foo: ['plop', 'bar'] })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: ['plop', 'bar'] })) + t.end() +}) test('match false', function (t) { const f = new EqualityFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(!f.matches({ foo: 'baz' })); - t.end(); -}); + }) + t.ok(f) + t.ok(!f.matches({ foo: 'baz' })) + t.end() +}) test('parse ok', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeString('bar'); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeString('bar') - const f = new EqualityFilter(); - t.ok(f); - t.ok(f.parse(new BerReader(writer.buffer))); - t.ok(f.matches({ foo: 'bar' })); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar'); - t.end(); -}); + const f = new EqualityFilter() + t.ok(f) + t.ok(f.parse(new BerReader(writer.buffer))) + t.ok(f.matches({ foo: 'bar' })) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar') + t.end() +}) test('escape EqualityFilter inputs', function (t) { const f = new EqualityFilter({ attribute: '(|(foo', value: 'bar))(' - }); + }) - t.equal(f.attribute, '(|(foo'); - t.equal(f.value, 'bar))('); - t.equal(f.toString(), '(\\28|\\28foo=bar\\29\\29\\28)'); - t.end(); -}); + t.equal(f.attribute, '(|(foo') + t.equal(f.value, 'bar))(') + t.equal(f.toString(), '(\\28|\\28foo=bar\\29\\29\\28)') + t.end() +}) test('parse bad', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeInt(20); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeInt(20) - const f = new EqualityFilter(); - t.ok(f); + const f = new EqualityFilter() + t.ok(f) try { - f.parse(new BerReader(writer.buffer)); - t.fail('Should have thrown InvalidAsn1Error'); + f.parse(new BerReader(writer.buffer)) + t.fail('Should have thrown InvalidAsn1Error') } catch (e) { - t.equal(e.name, 'InvalidAsn1Error'); + t.equal(e.name, 'InvalidAsn1Error') } - t.end(); -}); + t.end() +}) test('GH-109 = to ber uses plain values', function (t) { let f = new EqualityFilter({ attribute: 'foo', value: 'ba(r)' - }); - t.ok(f); - const writer = new BerWriter(); - f.toBer(writer); + }) + t.ok(f) + const writer = new BerWriter() + f.toBer(writer) - f = new EqualityFilter(); - t.ok(f); + f = new EqualityFilter() + t.ok(f) - const reader = new BerReader(writer.buffer); - reader.readSequence(); - t.ok(f.parse(reader)); + const 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(); -}); + t.equal(f.attribute, 'foo') + t.equal(f.value, 'ba(r)') + t.end() +}) test('handle values passed via buffer', function (t) { - const b = Buffer.from([32, 64, 128, 254]); + const b = Buffer.from([32, 64, 128, 254]) const f = new EqualityFilter({ attribute: 'foo', value: b - }); - t.ok(f); + }) + t.ok(f) - const writer = new BerWriter(); - f.toBer(writer); - const reader = new BerReader(writer.buffer); - reader.readSequence(); + const writer = new BerWriter() + f.toBer(writer) + const reader = new BerReader(writer.buffer) + reader.readSequence() - const f2 = new EqualityFilter(); - t.ok(f2.parse(reader)); + const f2 = new EqualityFilter() + t.ok(f2.parse(reader)) - t.equal(f2.value, b.toString()); - t.equal(f2.raw.length, b.length); + t.equal(f2.value, b.toString()) + t.equal(f2.raw.length, b.length) for (let i = 0; i < b.length; i++) { - t.equal(f2.raw[i], b[i]); + t.equal(f2.raw[i], b[i]) } - t.end(); -}); + t.end() +}) test('GH-277 objectClass should be case-insensitive', function (t) { const f = new EqualityFilter({ attribute: 'objectClass', value: 'CaseInsensitiveObj' - }); - t.ok(f); - t.ok(f.matches({ objectClass: 'CaseInsensitiveObj' })); - t.ok(f.matches({ OBJECTCLASS: 'CASEINSENSITIVEOBJ' })); - t.ok(f.matches({ objectclass: 'caseinsensitiveobj' })); - t.ok(!f.matches({ objectclass: 'matchless' })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ objectClass: 'CaseInsensitiveObj' })) + t.ok(f.matches({ OBJECTCLASS: 'CASEINSENSITIVEOBJ' })) + t.ok(f.matches({ objectclass: 'caseinsensitiveobj' })) + t.ok(!f.matches({ objectclass: 'matchless' })) + t.end() +}) diff --git a/test/filters/ext.test.js b/test/filters/ext.test.js index 78f27c7..438eeed 100644 --- a/test/filters/ext.test.js +++ b/test/filters/ext.test.js @@ -1,82 +1,82 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { filters: { parseString, ExtensibleFilter } } = require('../../lib'); +const { test } = require('tap') +const { filters: { parseString, ExtensibleFilter } } = require('../../lib') test('Construct no args', function (t) { - const f = new ExtensibleFilter(); - t.ok(f); - t.end(); -}); + const f = new ExtensibleFilter() + t.ok(f) + t.end() +}) test('Construct args', function (t) { const f = new ExtensibleFilter({ matchType: 'foo', value: 'bar' - }); - t.ok(f); - t.equal(f.matchType, 'foo'); - t.equal(f.value, 'bar'); - t.equal(f.toString(), '(foo:=bar)'); - t.end(); -}); + }) + t.ok(f) + t.equal(f.matchType, 'foo') + t.equal(f.value, 'bar') + t.equal(f.toString(), '(foo:=bar)') + t.end() +}) test('parse RFC example 1', function (t) { - const f = parseString('(cn:caseExactMatch:=Fred Flintstone)'); - t.ok(f); - t.equal(f.matchType, 'cn'); - t.equal(f.matchingRule, 'caseExactMatch'); - t.equal(f.matchValue, 'Fred Flintstone'); - t.notOk(f.dnAttributes); - t.end(); -}); + const f = parseString('(cn:caseExactMatch:=Fred Flintstone)') + t.ok(f) + t.equal(f.matchType, 'cn') + t.equal(f.matchingRule, 'caseExactMatch') + t.equal(f.matchValue, 'Fred Flintstone') + t.notOk(f.dnAttributes) + t.end() +}) test('parse RFC example 2', function (t) { - const f = parseString('(cn:=Betty Rubble)'); - t.ok(f); - t.equal(f.matchType, 'cn'); - t.equal(f.matchValue, 'Betty Rubble'); - t.notOk(f.dnAttributes); - t.notOk(f.matchingRule); - t.end(); -}); + const f = parseString('(cn:=Betty Rubble)') + t.ok(f) + t.equal(f.matchType, 'cn') + t.equal(f.matchValue, 'Betty Rubble') + t.notOk(f.dnAttributes) + t.notOk(f.matchingRule) + t.end() +}) test('parse RFC example 3', function (t) { - const f = parseString('(sn:dn:2.4.6.8.10:=Barney Rubble)'); - t.ok(f); - t.equal(f.matchType, 'sn'); - t.equal(f.matchingRule, '2.4.6.8.10'); - t.equal(f.matchValue, 'Barney Rubble'); - t.ok(f.dnAttributes); - t.end(); -}); + const f = parseString('(sn:dn:2.4.6.8.10:=Barney Rubble)') + t.ok(f) + t.equal(f.matchType, 'sn') + t.equal(f.matchingRule, '2.4.6.8.10') + t.equal(f.matchValue, 'Barney Rubble') + t.ok(f.dnAttributes) + t.end() +}) test('parse RFC example 3', function (t) { - const f = parseString('(o:dn:=Ace Industry)'); - t.ok(f); - t.equal(f.matchType, 'o'); - t.notOk(f.matchingRule); - t.equal(f.matchValue, 'Ace Industry'); - t.ok(f.dnAttributes); - t.end(); -}); + const f = parseString('(o:dn:=Ace Industry)') + t.ok(f) + t.equal(f.matchType, 'o') + t.notOk(f.matchingRule) + t.equal(f.matchValue, 'Ace Industry') + t.ok(f.dnAttributes) + t.end() +}) test('parse RFC example 4', function (t) { - const f = parseString('(:1.2.3:=Wilma Flintstone)'); - t.ok(f); - t.notOk(f.matchType); - t.equal(f.matchingRule, '1.2.3'); - t.equal(f.matchValue, 'Wilma Flintstone'); - t.notOk(f.dnAttributes); - t.end(); -}); + const f = parseString('(:1.2.3:=Wilma Flintstone)') + t.ok(f) + t.notOk(f.matchType) + t.equal(f.matchingRule, '1.2.3') + t.equal(f.matchValue, 'Wilma Flintstone') + t.notOk(f.dnAttributes) + t.end() +}) test('parse RFC example 5', function (t) { - const f = parseString('(:DN:2.4.6.8.10:=Dino)'); - t.ok(f); - t.notOk(f.matchType); - t.equal(f.matchingRule, '2.4.6.8.10'); - t.equal(f.matchValue, 'Dino'); - t.ok(f.dnAttributes); - t.end(); -}); + const f = parseString('(:DN:2.4.6.8.10:=Dino)') + t.ok(f) + t.notOk(f.matchType) + t.equal(f.matchingRule, '2.4.6.8.10') + t.equal(f.matchValue, 'Dino') + t.ok(f.dnAttributes) + t.end() +}) diff --git a/test/filters/ge.test.js b/test/filters/ge.test.js index 44e0738..ecc0dd3 100644 --- a/test/filters/ge.test.js +++ b/test/filters/ge.test.js @@ -1,116 +1,116 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { filters: { GreaterThanEqualsFilter } } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { filters: { GreaterThanEqualsFilter } } = require('../../lib') test('Construct no args', function (t) { - const f = new GreaterThanEqualsFilter(); - t.ok(f); - t.ok(!f.attribute); - t.ok(!f.value); - t.end(); -}); + const f = new GreaterThanEqualsFilter() + t.ok(f) + t.ok(!f.attribute) + t.ok(!f.value) + t.end() +}) test('Construct args', function (t) { const f = new GreaterThanEqualsFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar'); - t.equal(f.toString(), '(foo>=bar)'); - t.end(); -}); + }) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar') + t.equal(f.toString(), '(foo>=bar)') + t.end() +}) test('GH-109 = escape value only in toString()', function (t) { const 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(); -}); + }) + 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) { const f = new GreaterThanEqualsFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(f.matches({ foo: 'baz' })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: 'baz' })) + t.end() +}) test('match multiple', function (t) { const f = new GreaterThanEqualsFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(f.matches({ foo: ['beuha', 'baz'] })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: ['beuha', 'baz'] })) + t.end() +}) test('match false', function (t) { const f = new GreaterThanEqualsFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(!f.matches({ foo: 'abc' })); - t.end(); -}); + }) + t.ok(f) + t.ok(!f.matches({ foo: 'abc' })) + t.end() +}) test('parse ok', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeString('bar'); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeString('bar') - const f = new GreaterThanEqualsFilter(); - t.ok(f); - t.ok(f.parse(new BerReader(writer.buffer))); - t.ok(f.matches({ foo: 'bar' })); - t.end(); -}); + const f = new GreaterThanEqualsFilter() + t.ok(f) + t.ok(f.parse(new BerReader(writer.buffer))) + t.ok(f.matches({ foo: 'bar' })) + t.end() +}) test('parse bad', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeInt(20); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeInt(20) - const f = new GreaterThanEqualsFilter(); - t.ok(f); + const f = new GreaterThanEqualsFilter() + t.ok(f) try { - f.parse(new BerReader(writer.buffer)); - t.fail('Should have thrown InvalidAsn1Error'); + f.parse(new BerReader(writer.buffer)) + t.fail('Should have thrown InvalidAsn1Error') } catch (e) { - t.equal(e.name, 'InvalidAsn1Error'); + t.equal(e.name, 'InvalidAsn1Error') } - t.end(); -}); + t.end() +}) test('GH-109 = to ber uses plain values', function (t) { let f = new GreaterThanEqualsFilter({ attribute: 'foo', value: 'ba(r)' - }); - t.ok(f); - const writer = new BerWriter(); - f.toBer(writer); + }) + t.ok(f) + const writer = new BerWriter() + f.toBer(writer) - f = new GreaterThanEqualsFilter(); - t.ok(f); + f = new GreaterThanEqualsFilter() + t.ok(f) - const reader = new BerReader(writer.buffer); - reader.readSequence(); - t.ok(f.parse(reader)); + const 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(); -}); + 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 b97f2bc..4f72fd6 100644 --- a/test/filters/le.test.js +++ b/test/filters/le.test.js @@ -1,116 +1,116 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { filters: { LessThanEqualsFilter } } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { filters: { LessThanEqualsFilter } } = require('../../lib') test('Construct no args', function (t) { - const f = new LessThanEqualsFilter(); - t.ok(f); - t.ok(!f.attribute); - t.ok(!f.value); - t.end(); -}); + const f = new LessThanEqualsFilter() + t.ok(f) + t.ok(!f.attribute) + t.ok(!f.value) + t.end() +}) test('Construct args', function (t) { const f = new LessThanEqualsFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar'); - t.equal(f.toString(), '(foo<=bar)'); - t.end(); -}); + }) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar') + t.equal(f.toString(), '(foo<=bar)') + t.end() +}) test('GH-109 = escape value only in toString()', function (t) { const 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(); -}); + }) + 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) { const f = new LessThanEqualsFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(f.matches({ foo: 'abc' })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: 'abc' })) + t.end() +}) test('match multiple', function (t) { const f = new LessThanEqualsFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(f.matches({ foo: ['abc', 'beuha'] })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: ['abc', 'beuha'] })) + t.end() +}) test('match false', function (t) { const f = new LessThanEqualsFilter({ attribute: 'foo', value: 'bar' - }); - t.ok(f); - t.ok(!f.matches({ foo: 'baz' })); - t.end(); -}); + }) + t.ok(f) + t.ok(!f.matches({ foo: 'baz' })) + t.end() +}) test('parse ok', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeString('bar'); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeString('bar') - const f = new LessThanEqualsFilter(); - t.ok(f); - t.ok(f.parse(new BerReader(writer.buffer))); - t.ok(f.matches({ foo: 'bar' })); - t.end(); -}); + const f = new LessThanEqualsFilter() + t.ok(f) + t.ok(f.parse(new BerReader(writer.buffer))) + t.ok(f.matches({ foo: 'bar' })) + t.end() +}) test('parse bad', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeInt(20); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeInt(20) - const f = new LessThanEqualsFilter(); - t.ok(f); + const f = new LessThanEqualsFilter() + t.ok(f) try { - f.parse(new BerReader(writer.buffer)); - t.fail('Should have thrown InvalidAsn1Error'); + f.parse(new BerReader(writer.buffer)) + t.fail('Should have thrown InvalidAsn1Error') } catch (e) { - t.equal(e.name, 'InvalidAsn1Error'); + t.equal(e.name, 'InvalidAsn1Error') } - t.end(); -}); + t.end() +}) test('GH-109 = to ber uses plain values', function (t) { let f = new LessThanEqualsFilter({ attribute: 'foo', value: 'ba(r)' - }); - t.ok(f); - const writer = new BerWriter(); - f.toBer(writer); + }) + t.ok(f) + const writer = new BerWriter() + f.toBer(writer) - f = new LessThanEqualsFilter(); - t.ok(f); + f = new LessThanEqualsFilter() + t.ok(f) - const reader = new BerReader(writer.buffer); - reader.readSequence(); - t.ok(f.parse(reader)); + const 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(); -}); + t.equal(f.attribute, 'foo') + t.equal(f.value, 'ba(r)') + t.end() +}) diff --git a/test/filters/not.test.js b/test/filters/not.test.js index f91dbc7..b9164c1 100644 --- a/test/filters/not.test.js +++ b/test/filters/not.test.js @@ -1,12 +1,12 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { filters: { EqualityFilter, NotFilter } } = require('../../lib'); +const { test } = require('tap') +const { filters: { EqualityFilter, NotFilter } } = require('../../lib') test('Construct no args', function (t) { - t.ok(new NotFilter()); - t.end(); -}); + t.ok(new NotFilter()) + t.end() +}) test('Construct args', function (t) { const f = new NotFilter({ @@ -14,11 +14,11 @@ test('Construct args', function (t) { attribute: 'foo', value: 'bar' }) - }); - t.ok(f); - t.equal(f.toString(), '(!(foo=bar))'); - t.end(); -}); + }) + t.ok(f) + t.equal(f.toString(), '(!(foo=bar))') + t.end() +}) test('match true', function (t) { const f = new NotFilter({ @@ -26,11 +26,11 @@ test('match true', function (t) { attribute: 'foo', value: 'bar' }) - }); - t.ok(f); - t.ok(f.matches({ foo: 'baz' })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: 'baz' })) + t.end() +}) test('match false', function (t) { const f = new NotFilter({ @@ -38,8 +38,8 @@ test('match false', function (t) { attribute: 'foo', value: 'bar' }) - }); - t.ok(f); - t.ok(!f.matches({ foo: 'bar' })); - t.end(); -}); + }) + t.ok(f) + t.ok(!f.matches({ foo: 'bar' })) + t.end() +}) diff --git a/test/filters/or.test.js b/test/filters/or.test.js index cb95826..dacb694 100644 --- a/test/filters/or.test.js +++ b/test/filters/or.test.js @@ -1,54 +1,54 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { filters: { EqualityFilter, OrFilter } } = require('../../lib'); +const { test } = require('tap') +const { filters: { EqualityFilter, OrFilter } } = require('../../lib') test('Construct no args', function (t) { - t.ok(new OrFilter()); - t.end(); -}); + t.ok(new OrFilter()) + t.end() +}) test('Construct args', function (t) { - const f = new OrFilter(); + const f = new OrFilter() f.addFilter(new EqualityFilter({ attribute: 'foo', value: 'bar' - })); + })) f.addFilter(new EqualityFilter({ attribute: 'zig', value: 'zag' - })); - t.ok(f); - t.equal(f.toString(), '(|(foo=bar)(zig=zag))'); - t.end(); -}); + })) + t.ok(f) + t.equal(f.toString(), '(|(foo=bar)(zig=zag))') + t.end() +}) test('match true', function (t) { - const f = new OrFilter(); + const f = new OrFilter() f.addFilter(new EqualityFilter({ attribute: 'foo', value: 'bar' - })); + })) f.addFilter(new EqualityFilter({ attribute: 'zig', value: 'zag' - })); - t.ok(f); - t.ok(f.matches({ foo: 'bar', zig: 'zonk' })); - t.end(); -}); + })) + t.ok(f) + t.ok(f.matches({ foo: 'bar', zig: 'zonk' })) + t.end() +}) test('match false', function (t) { - const f = new OrFilter(); + const f = new OrFilter() f.addFilter(new EqualityFilter({ attribute: 'foo', value: 'bar' - })); + })) f.addFilter(new EqualityFilter({ attribute: 'zig', value: 'zag' - })); - t.ok(f); - t.ok(!f.matches({ foo: 'baz', zig: 'zonk' })); - t.end(); -}); + })) + t.ok(f) + t.ok(!f.matches({ foo: 'baz', zig: 'zonk' })) + t.end() +}) diff --git a/test/filters/parse.test.js b/test/filters/parse.test.js index 0f9cd08..5eb6a94 100644 --- a/test/filters/parse.test.js +++ b/test/filters/parse.test.js @@ -1,121 +1,121 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { parseFilter: parse } = require('../../lib'); +const { test } = require('tap') +const { parseFilter: parse } = require('../../lib') test('GH-48 XML Strings in filter', function (t) { - const str = '(&(CentralUIEnrollments=\\*)(objectClass=User))'; - const f = parse(str); - t.ok(f); - t.ok(f.filters); - t.equal(f.filters.length, 2); + const str = '(&(CentralUIEnrollments=\\*)(objectClass=User))' + const f = parse(str) + t.ok(f) + t.ok(f.filters) + t.equal(f.filters.length, 2) f.filters.forEach(function (filter) { - t.ok(filter.attribute); - }); - t.end(); -}); + t.ok(filter.attribute) + }) + t.end() +}) test('GH-50 = in filter', function (t) { const str = '(uniquemember=uuid=930896af-bf8c-48d4-885c-6573a94b1853, ' + - 'ou=users, o=smartdc)'; - const f = parse(str); - t.ok(f); - t.equal(f.attribute, 'uniquemember'); + 'ou=users, o=smartdc)' + const f = parse(str) + t.ok(f) + t.equal(f.attribute, 'uniquemember') t.equal(f.value, - 'uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc'); - t.end(); -}); + 'uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc') + t.end() +}) test('( in filter', function (t) { - const str = '(foo=bar\\()'; - const f = parse(str); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar('); - t.equal(f.toString(), '(foo=bar\\28)'); - t.end(); -}); + const str = '(foo=bar\\()' + const f = parse(str) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar(') + t.equal(f.toString(), '(foo=bar\\28)') + t.end() +}) test(') in filter', function (t) { - const str = '(foo=bar\\))'; - const f = parse(str); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar)'); - t.equal(f.toString(), '(foo=bar\\29)'); - t.end(); -}); + const str = '(foo=bar\\))' + const f = parse(str) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar)') + t.equal(f.toString(), '(foo=bar\\29)') + t.end() +}) test('\\ in filter', function (t) { - const str = '(foo=bar\\\\)'; - const f = parse(str); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar\\'); - t.equal(f.toString(), '(foo=bar\\5c)'); - t.end(); -}); + const str = '(foo=bar\\\\)' + const f = parse(str) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar\\') + t.equal(f.toString(), '(foo=bar\\5c)') + t.end() +}) test('* in equality filter', function (t) { - const str = '(foo=bar\\*)'; - const f = parse(str); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.value, 'bar*'); - t.equal(f.toString(), '(foo=bar\\2a)'); - t.end(); -}); + const str = '(foo=bar\\*)' + const f = parse(str) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.value, 'bar*') + t.equal(f.toString(), '(foo=bar\\2a)') + t.end() +}) test('* substr filter (prefix)', function (t) { - const str = '(foo=bar*)'; - const f = parse(str); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.initial, 'bar'); - t.equal(f.toString(), '(foo=bar*)'); - t.end(); -}); + const str = '(foo=bar*)' + const f = parse(str) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.initial, 'bar') + t.equal(f.toString(), '(foo=bar*)') + t.end() +}) test('GH-53 NotFilter', function (t) { - const str = '(&(objectClass=person)(!(objectClass=shadowAccount)))'; - const f = parse(str); - t.ok(f); - t.equal(f.type, 'and'); - t.equal(f.filters.length, 2); - t.equal(f.filters[0].type, 'equal'); - t.equal(f.filters[1].type, 'not'); - t.equal(f.filters[1].filter.type, 'equal'); - t.equal(f.filters[1].filter.attribute, 'objectClass'); - t.equal(f.filters[1].filter.value, 'shadowAccount'); - t.end(); -}); + const str = '(&(objectClass=person)(!(objectClass=shadowAccount)))' + const f = parse(str) + t.ok(f) + t.equal(f.type, 'and') + t.equal(f.filters.length, 2) + t.equal(f.filters[0].type, 'equal') + t.equal(f.filters[1].type, 'not') + t.equal(f.filters[1].filter.type, 'equal') + t.equal(f.filters[1].filter.attribute, 'objectClass') + t.equal(f.filters[1].filter.value, 'shadowAccount') + t.end() +}) test('presence filter', function (t) { - const f = parse('(foo=*)'); - t.ok(f); - t.equal(f.type, 'present'); - t.equal(f.attribute, 'foo'); - t.equal(f.toString(), '(foo=*)'); - t.end(); -}); + const f = parse('(foo=*)') + t.ok(f) + t.equal(f.type, 'present') + t.equal(f.attribute, 'foo') + t.equal(f.toString(), '(foo=*)') + t.end() +}) test('bogus filter', function (t) { t.throws(function () { - parse('foo>1'); - }); - t.end(); -}); + parse('foo>1') + }) + t.end() +}) test('bogus filter !=', function (t) { t.throws(function () { - parse('foo!=1'); - }); - t.end(); -}); + parse('foo!=1') + }) + t.end() +}) test('mismatched parens', function (t) { t.throws(function () { - parse('(&(foo=bar)(!(state=done))'); - }); - t.end(); -}); + parse('(&(foo=bar)(!(state=done))') + }) + t.end() +}) diff --git a/test/filters/presence.test.js b/test/filters/presence.test.js index 9d7ce64..5d78dae 100644 --- a/test/filters/presence.test.js +++ b/test/filters/presence.test.js @@ -1,83 +1,83 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { filters: { PresenceFilter } } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { filters: { PresenceFilter } } = require('../../lib') test('Construct no args', function (t) { - const f = new PresenceFilter(); - t.ok(f); - t.ok(!f.attribute); - t.end(); -}); + const f = new PresenceFilter() + t.ok(f) + t.ok(!f.attribute) + t.end() +}) test('Construct args', function (t) { const f = new PresenceFilter({ attribute: 'foo' - }); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.toString(), '(foo=*)'); - t.end(); -}); + }) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.toString(), '(foo=*)') + t.end() +}) test('GH-109 = escape value only in toString()', function (t) { const f = new PresenceFilter({ attribute: 'fo)o' - }); - t.ok(f); - t.equal(f.attribute, 'fo)o'); - t.equal(f.toString(), '(fo\\29o=*)'); - t.end(); -}); + }) + t.ok(f) + t.equal(f.attribute, 'fo)o') + t.equal(f.toString(), '(fo\\29o=*)') + t.end() +}) test('match true', function (t) { const f = new PresenceFilter({ attribute: 'foo' - }); - t.ok(f); - t.ok(f.matches({ foo: 'bar' })); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: 'bar' })) + t.end() +}) test('match false', function (t) { const f = new PresenceFilter({ attribute: 'foo' - }); - t.ok(f); - t.ok(!f.matches({ bar: 'foo' })); - t.end(); -}); + }) + t.ok(f) + t.ok(!f.matches({ bar: 'foo' })) + t.end() +}) test('parse ok', function (t) { - const writer = new BerWriter(); - writer.writeString('foo', 0x87); + const writer = new BerWriter() + writer.writeString('foo', 0x87) - const f = new PresenceFilter(); - t.ok(f); + const f = new PresenceFilter() + t.ok(f) - const reader = new BerReader(writer.buffer); - reader.readSequence(); - t.ok(f.parse(reader)); - t.ok(f.matches({ foo: 'bar' })); - t.end(); -}); + const reader = new BerReader(writer.buffer) + reader.readSequence() + t.ok(f.parse(reader)) + t.ok(f.matches({ foo: 'bar' })) + t.end() +}) test('GH-109 = to ber uses plain values', function (t) { let f = new PresenceFilter({ attribute: 'f(o)o' - }); - t.ok(f); - const writer = new BerWriter(); - f.toBer(writer); + }) + t.ok(f) + const writer = new BerWriter() + f.toBer(writer) - f = new PresenceFilter(); - t.ok(f); + f = new PresenceFilter() + t.ok(f) - const reader = new BerReader(writer.buffer); - reader.readSequence(); - t.ok(f.parse(reader)); + const reader = new BerReader(writer.buffer) + reader.readSequence() + t.ok(f.parse(reader)) - t.equal(f.attribute, 'f(o)o'); - t.end(); -}); + t.equal(f.attribute, 'f(o)o') + t.end() +}) diff --git a/test/filters/substr.test.js b/test/filters/substr.test.js index bb62b88..0526a28 100644 --- a/test/filters/substr.test.js +++ b/test/filters/substr.test.js @@ -1,152 +1,152 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { filters: { SubstringFilter } } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { filters: { SubstringFilter } } = require('../../lib') test('Construct no args', function (t) { - const f = new SubstringFilter(); - t.ok(f); - t.ok(!f.attribute); - t.ok(!f.value); - t.end(); -}); + const f = new SubstringFilter() + t.ok(f) + t.ok(!f.attribute) + t.ok(!f.value) + t.end() +}) test('Construct args', function (t) { const f = new SubstringFilter({ attribute: 'foo', initial: 'bar', any: ['zig', 'zag'], - 'final': 'baz' - }); - t.ok(f); - t.equal(f.attribute, 'foo'); - t.equal(f.initial, 'bar'); - t.equal(f.any.length, 2); - t.equal(f.any[0], 'zig'); - t.equal(f.any[1], 'zag'); - t.equal(f['final'], 'baz'); - t.equal(f.toString(), '(foo=bar*zig*zag*baz)'); - t.end(); -}); + final: 'baz' + }) + t.ok(f) + t.equal(f.attribute, 'foo') + t.equal(f.initial, 'bar') + t.equal(f.any.length, 2) + t.equal(f.any[0], 'zig') + t.equal(f.any[1], 'zag') + t.equal(f.final, 'baz') + t.equal(f.toString(), '(foo=bar*zig*zag*baz)') + t.end() +}) test('GH-109 = escape value only in toString()', function (t) { const 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(); -}); + 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) { const f = new SubstringFilter({ attribute: 'foo', initial: 'bar', any: ['zig', 'zag'], - 'final': 'baz' - }); - t.ok(f); - t.ok(f.matches({ foo: 'barmoozigbarzagblahbaz' })); - t.end(); -}); + final: 'baz' + }) + t.ok(f) + t.ok(f.matches({ foo: 'barmoozigbarzagblahbaz' })) + t.end() +}) test('match false', function (t) { const f = new SubstringFilter({ attribute: 'foo', initial: 'bar', foo: ['zig', 'zag'], - 'final': 'baz' - }); - t.ok(f); - t.ok(!f.matches({ foo: 'bafmoozigbarzagblahbaz' })); - t.end(); -}); + final: 'baz' + }) + t.ok(f) + t.ok(!f.matches({ foo: 'bafmoozigbarzagblahbaz' })) + t.end() +}) test('match any', function (t) { const f = new SubstringFilter({ attribute: 'foo', initial: 'bar' - }); - t.ok(f); - t.ok(f.matches({ foo: ['beuha', 'barista']})); - t.end(); -}); + }) + t.ok(f) + t.ok(f.matches({ foo: ['beuha', 'barista'] })) + t.end() +}) test('GH-109 = escape for regex in matches', function (t) { const 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(); -}); + 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) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.startSequence(); - writer.writeString('bar', 0x80); - writer.writeString('bad', 0x81); - writer.writeString('baz', 0x82); - writer.endSequence(); - const f = new SubstringFilter(); - t.ok(f); - t.ok(f.parse(new BerReader(writer.buffer))); - t.ok(f.matches({ foo: 'bargoobadgoobaz' })); - t.end(); -}); + const writer = new BerWriter() + writer.writeString('foo') + writer.startSequence() + writer.writeString('bar', 0x80) + writer.writeString('bad', 0x81) + writer.writeString('baz', 0x82) + writer.endSequence() + const f = new SubstringFilter() + t.ok(f) + t.ok(f.parse(new BerReader(writer.buffer))) + t.ok(f.matches({ foo: 'bargoobadgoobaz' })) + t.end() +}) test('parse bad', function (t) { - const writer = new BerWriter(); - writer.writeString('foo'); - writer.writeInt(20); + const writer = new BerWriter() + writer.writeString('foo') + writer.writeInt(20) - const f = new SubstringFilter(); - t.ok(f); + const f = new SubstringFilter() + t.ok(f) try { - f.parse(new BerReader(writer.buffer)); - t.fail('Should have thrown InvalidAsn1Error'); + f.parse(new BerReader(writer.buffer)) + t.fail('Should have thrown InvalidAsn1Error') } catch (e) { } - t.end(); -}); + t.end() +}) test('GH-109 = to ber uses plain values', function (t) { let f = new SubstringFilter({ attribute: 'fo(o', initial: 'ba(r)', any: ['zi)g', 'z(ag'], - 'final': '(baz)' - }); - t.ok(f); - const writer = new BerWriter(); - f.toBer(writer); + final: '(baz)' + }) + t.ok(f) + const writer = new BerWriter() + f.toBer(writer) - f = new SubstringFilter(); - t.ok(f); + f = new SubstringFilter() + t.ok(f) - const reader = new BerReader(writer.buffer); - reader.readSequence(); - t.ok(f.parse(reader)); + const 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(); -}); + 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() +}) diff --git a/test/laundry.test.js b/test/laundry.test.js index fb9b3e2..796e48c 100644 --- a/test/laundry.test.js +++ b/test/laundry.test.js @@ -1,39 +1,39 @@ -'use strict'; +'use strict' -const tap = require('tap'); +const tap = require('tap') const uuid = require('uuid') const { getSock } = require('./utils') -const ldap = require('../lib'); +const ldap = require('../lib') -function search(t, options, callback) { +function search (t, options, callback) { t.context.client.search(t.context.suffix, options, function (err, res) { - t.error(err); - t.ok(res); - let found = false; + t.error(err) + t.ok(res) + let found = false res.on('searchEntry', function (entry) { - t.ok(entry); - found = true; - }); + t.ok(entry) + found = true + }) res.on('end', function () { - t.true(found); - if (callback) return callback(); - return t.end(); - }); - }); + t.true(found) + if (callback) return callback() + return t.end() + }) + }) } tap.beforeEach((done, t) => { - const suffix = `dc=${uuid()}`; - const server = ldap.createServer(); + const suffix = `dc=${uuid()}` + const server = ldap.createServer() - t.context.server = server; - t.context.socketPath = getSock(); - t.context.suffix = suffix; + t.context.server = server + t.context.socketPath = getSock() + t.context.suffix = suffix server.bind('cn=root', function (req, res, next) { - res.end(); - return next(); - }); + res.end() + return next() + }) server.search(suffix, function (req, res, next) { var entry = { @@ -45,27 +45,26 @@ tap.beforeEach((done, t) => { givenname: 'ogo', mail: uuid() + '@pogostick.org' } - }; + } - if (req.filter.matches(entry.attributes)) - res.send(entry); + if (req.filter.matches(entry.attributes)) { res.send(entry) } - res.end(); - }); + res.end() + }) server.listen(t.context.socketPath, function () { t.context.client = ldap.createClient({ socketPath: t.context.socketPath - }); + }) t.context.client.on('connectError', (err) => { - t.context.server.close(() => done(err)); + t.context.server.close(() => done(err)) }) t.context.client.on('connect', (socket) => { - t.context.socket = socket; - done(); + t.context.socket = socket + done() }) - }); + }) }) tap.afterEach((done, t) => { @@ -93,35 +92,35 @@ tap.test('Evolution search filter (GH-3)', function (t) { '(otherpostaladdress=ogo*)(jpegphoto=ogo*)(usercertificate=ogo*)' + '(labeleduri=ogo*)(displayname=ogo*)(spousename=ogo*)(note=ogo*)' + '(anniversary=ogo*)(birthdate=ogo*)(mailer=ogo*)(fileas=ogo*)' + - '(category=ogo*)(calcaluri=ogo*)(calfburl=ogo*)(icscalendar=ogo*))'; + '(category=ogo*)(calcaluri=ogo*)(calfburl=ogo*)(icscalendar=ogo*))' - return search(t, filter); -}); + return search(t, filter) +}) tap.test('GH-49 Client errors on bad attributes', function (t) { const searchOpts = { filter: 'cn=*ogo*', scope: 'one', attributes: 'dn' - }; - return search(t, searchOpts); -}); + } + return search(t, searchOpts) +}) tap.test('GH-55 Client emits connect multiple times', function (t) { const c = ldap.createClient({ socketPath: t.context.socketPath - }); + }) - let count = 0; + let count = 0 c.on('connect', function (socket) { - t.ok(socket); - count++; + t.ok(socket) + count++ c.bind('cn=root', 'secret', function (err) { - t.ifError(err); + t.ifError(err) c.unbind(function () { - t.equal(count, 1); - t.end(); - }); - }); - }); -}); + t.equal(count, 1) + t.end() + }) + }) + }) +}) diff --git a/test/messages/add_request.test.js b/test/messages/add_request.test.js index 1def8e4..1c287ca 100644 --- a/test/messages/add_request.test.js +++ b/test/messages/add_request.test.js @@ -1,118 +1,118 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { AddRequest, Attribute, dn } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { AddRequest, Attribute, dn } = require('../../lib') test('new no args', t => { - t.ok(new AddRequest()); - t.end(); -}); + t.ok(new AddRequest()) + t.end() +}) test('new with args', t => { const req = new AddRequest({ entry: dn.parse('cn=foo, o=test'), - attributes: [new Attribute({type: 'cn', vals: ['foo']}), - new Attribute({type: 'objectclass', vals: ['person']})] - }); - t.ok(req); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.attributes.length, 2); - t.equal(req.attributes[0].type, 'cn'); - t.equal(req.attributes[0].vals[0], 'foo'); - t.equal(req.attributes[1].type, 'objectclass'); - t.equal(req.attributes[1].vals[0], 'person'); - t.end(); -}); + attributes: [new Attribute({ type: 'cn', vals: ['foo'] }), + new Attribute({ type: 'objectclass', vals: ['person'] })] + }) + t.ok(req) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.attributes.length, 2) + t.equal(req.attributes[0].type, 'cn') + t.equal(req.attributes[0].vals[0], 'foo') + t.equal(req.attributes[1].type, 'objectclass') + t.equal(req.attributes[1].vals[0], 'person') + t.end() +}) test('parse', t => { - const ber = new BerWriter(); - ber.writeString('cn=foo, o=test'); + const ber = new BerWriter() + ber.writeString('cn=foo, o=test') - ber.startSequence(); + ber.startSequence() - ber.startSequence(); - ber.writeString('cn'); - ber.startSequence(0x31); - ber.writeString('foo'); - ber.endSequence(); - ber.endSequence(); + ber.startSequence() + ber.writeString('cn') + ber.startSequence(0x31) + ber.writeString('foo') + ber.endSequence() + ber.endSequence() - ber.startSequence(); - ber.writeString('objectclass'); - ber.startSequence(0x31); - ber.writeString('person'); - ber.endSequence(); - ber.endSequence(); + ber.startSequence() + ber.writeString('objectclass') + ber.startSequence(0x31) + ber.writeString('person') + ber.endSequence() + ber.endSequence() - ber.endSequence(); + ber.endSequence() - const req = new AddRequest(); - t.ok(req._parse(new BerReader(ber.buffer))); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.attributes.length, 2); - t.equal(req.attributes[0].type, 'cn'); - t.equal(req.attributes[0].vals[0], 'foo'); - t.equal(req.attributes[1].type, 'objectclass'); - t.equal(req.attributes[1].vals[0], 'person'); - t.end(); -}); + const req = new AddRequest() + t.ok(req._parse(new BerReader(ber.buffer))) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.attributes.length, 2) + t.equal(req.attributes[0].type, 'cn') + t.equal(req.attributes[0].vals[0], 'foo') + t.equal(req.attributes[1].type, 'objectclass') + t.equal(req.attributes[1].vals[0], 'person') + t.end() +}) test('toBer', t => { const req = new AddRequest({ messageID: 123, entry: dn.parse('cn=foo, o=test'), - attributes: [new Attribute({type: 'cn', vals: ['foo']}), - new Attribute({type: 'objectclass', vals: ['person']})] - }); + attributes: [new Attribute({ type: 'cn', vals: ['foo'] }), + new Attribute({ type: 'objectclass', vals: ['person'] })] + }) - t.ok(req); + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x68); - t.equal(ber.readString(), 'cn=foo, o=test'); - t.ok(ber.readSequence()); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x68) + t.equal(ber.readString(), 'cn=foo, o=test') + t.ok(ber.readSequence()) - t.ok(ber.readSequence()); - t.equal(ber.readString(), 'cn'); - t.equal(ber.readSequence(), 0x31); - t.equal(ber.readString(), 'foo'); + t.ok(ber.readSequence()) + t.equal(ber.readString(), 'cn') + t.equal(ber.readSequence(), 0x31) + t.equal(ber.readString(), 'foo') - t.ok(ber.readSequence()); - t.equal(ber.readString(), 'objectclass'); - t.equal(ber.readSequence(), 0x31); - t.equal(ber.readString(), 'person'); + t.ok(ber.readSequence()) + t.equal(ber.readString(), 'objectclass') + t.equal(ber.readSequence(), 0x31) + t.equal(ber.readString(), 'person') - t.end(); -}); + t.end() +}) test('toObject', t => { const req = new AddRequest({ entry: dn.parse('cn=foo, o=test'), - attributes: [new Attribute({type: 'cn', vals: ['foo', 'bar']}), - new Attribute({type: 'objectclass', vals: ['person']})] - }); + attributes: [new Attribute({ type: 'cn', vals: ['foo', 'bar'] }), + new Attribute({ type: 'objectclass', vals: ['person'] })] + }) - t.ok(req); + t.ok(req) - const obj = req.toObject(); - t.ok(obj); + const obj = req.toObject() + t.ok(obj) - t.ok(obj.dn); - t.equal(obj.dn, 'cn=foo, o=test'); - t.ok(obj.attributes); - t.ok(obj.attributes.cn); - t.ok(Array.isArray(obj.attributes.cn)); - t.equal(obj.attributes.cn.length, 2); - t.equal(obj.attributes.cn[0], 'foo'); - t.equal(obj.attributes.cn[1], 'bar'); - t.ok(obj.attributes.objectclass); - t.ok(Array.isArray(obj.attributes.objectclass)); - t.equal(obj.attributes.objectclass.length, 1); - t.equal(obj.attributes.objectclass[0], 'person'); + t.ok(obj.dn) + t.equal(obj.dn, 'cn=foo, o=test') + t.ok(obj.attributes) + t.ok(obj.attributes.cn) + t.ok(Array.isArray(obj.attributes.cn)) + t.equal(obj.attributes.cn.length, 2) + t.equal(obj.attributes.cn[0], 'foo') + t.equal(obj.attributes.cn[1], 'bar') + t.ok(obj.attributes.objectclass) + t.ok(Array.isArray(obj.attributes.objectclass)) + t.equal(obj.attributes.objectclass.length, 1) + t.equal(obj.attributes.objectclass[0], 'person') - t.end(); -}); + t.end() +}) diff --git a/test/messages/add_response.test.js b/test/messages/add_response.test.js index 5727aad..cb06d16 100644 --- a/test/messages/add_response.test.js +++ b/test/messages/add_response.test.js @@ -1,38 +1,38 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { AddResponse } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { AddResponse } = require('../../lib') test('new no args', function (t) { - t.ok(new AddResponse()); - t.end(); -}); + t.ok(new AddResponse()) + t.end() +}) test('new with args', function (t) { const res = new AddResponse({ messageID: 123, status: 0 - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.status, 0); - t.end(); -}); + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.status, 0) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeEnumeration(0); - ber.writeString('cn=root'); - ber.writeString('foo'); + const ber = new BerWriter() + ber.writeEnumeration(0) + ber.writeString('cn=root') + ber.writeString('foo') - const res = new AddResponse(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.status, 0); - t.equal(res.matchedDN, 'cn=root'); - t.equal(res.errorMessage, 'foo'); - t.end(); -}); + const res = new AddResponse() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.status, 0) + t.equal(res.matchedDN, 'cn=root') + t.equal(res.errorMessage, 'foo') + t.end() +}) test('toBer', function (t) { const res = new AddResponse({ @@ -40,17 +40,17 @@ test('toBer', function (t) { status: 3, matchedDN: 'cn=root', errorMessage: 'foo' - }); - t.ok(res); + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x69); - t.equal(ber.readEnumeration(), 3); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(), 'foo'); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x69) + t.equal(ber.readEnumeration(), 3) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(), 'foo') - t.end(); -}); + t.end() +}) diff --git a/test/messages/bind_request.test.js b/test/messages/bind_request.test.js index 9cc2926..f0639c9 100644 --- a/test/messages/bind_request.test.js +++ b/test/messages/bind_request.test.js @@ -1,40 +1,40 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { BindRequest, dn } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { BindRequest, dn } = require('../../lib') test('new no args', function (t) { - t.ok(new BindRequest()); - t.end(); -}); + t.ok(new BindRequest()) + t.end() +}) test('new with args', function (t) { const req = new BindRequest({ version: 3, name: dn.parse('cn=root'), credentials: 'secret' - }); - t.ok(req); - t.equal(req.version, 3); - t.equal(req.name.toString(), 'cn=root'); - t.equal(req.credentials, 'secret'); - t.end(); -}); + }) + t.ok(req) + t.equal(req.version, 3) + t.equal(req.name.toString(), 'cn=root') + t.equal(req.credentials, 'secret') + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeInt(3); - ber.writeString('cn=root'); - ber.writeString('secret', 0x80); + const ber = new BerWriter() + ber.writeInt(3) + ber.writeString('cn=root') + ber.writeString('secret', 0x80) - const req = new BindRequest(); - t.ok(req._parse(new BerReader(ber.buffer))); - t.equal(req.version, 3); - t.equal(req.dn.toString(), 'cn=root'); - t.equal(req.credentials, 'secret'); - t.end(); -}); + const req = new BindRequest() + t.ok(req._parse(new BerReader(ber.buffer))) + t.equal(req.version, 3) + t.equal(req.dn.toString(), 'cn=root') + t.equal(req.credentials, 'secret') + t.end() +}) test('toBer', function (t) { const req = new BindRequest({ @@ -42,17 +42,17 @@ test('toBer', function (t) { version: 3, name: dn.parse('cn=root'), credentials: 'secret' - }); - t.ok(req); + }) + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x60); - t.equal(ber.readInt(), 0x03); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(0x80), 'secret'); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x60) + t.equal(ber.readInt(), 0x03) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(0x80), 'secret') - t.end(); -}); + t.end() +}) diff --git a/test/messages/bind_response.test.js b/test/messages/bind_response.test.js index c9f8493..e9a8edd 100644 --- a/test/messages/bind_response.test.js +++ b/test/messages/bind_response.test.js @@ -1,38 +1,38 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { BindResponse } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { BindResponse } = require('../../lib') test('new no args', function (t) { - t.ok(new BindResponse()); - t.end(); -}); + t.ok(new BindResponse()) + t.end() +}) test('new with args', function (t) { const res = new BindResponse({ messageID: 123, status: 0 - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.status, 0); - t.end(); -}); + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.status, 0) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeEnumeration(0); - ber.writeString('cn=root'); - ber.writeString('foo'); + const ber = new BerWriter() + ber.writeEnumeration(0) + ber.writeString('cn=root') + ber.writeString('foo') - const res = new BindResponse(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.status, 0); - t.equal(res.matchedDN, 'cn=root'); - t.equal(res.errorMessage, 'foo'); - t.end(); -}); + const res = new BindResponse() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.status, 0) + t.equal(res.matchedDN, 'cn=root') + t.equal(res.errorMessage, 'foo') + t.end() +}) test('toBer', function (t) { const res = new BindResponse({ @@ -40,17 +40,17 @@ test('toBer', function (t) { status: 3, matchedDN: 'cn=root', errorMessage: 'foo' - }); - t.ok(res); + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x61); - t.equal(ber.readEnumeration(), 3); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(), 'foo'); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x61) + t.equal(ber.readEnumeration(), 3) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(), 'foo') - t.end(); -}); + t.end() +}) diff --git a/test/messages/compare_request.test.js b/test/messages/compare_request.test.js index 744fc60..06d3565 100644 --- a/test/messages/compare_request.test.js +++ b/test/messages/compare_request.test.js @@ -1,43 +1,43 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { CompareRequest, dn } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { CompareRequest, dn } = require('../../lib') test('new no args', function (t) { - t.ok(new CompareRequest()); - t.end(); -}); + t.ok(new CompareRequest()) + t.end() +}) test('new with args', function (t) { const req = new CompareRequest({ entry: dn.parse('cn=foo, o=test'), attribute: 'sn', value: 'testy' - }); - t.ok(req); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.attribute, 'sn'); - t.equal(req.value, 'testy'); - t.end(); -}); + }) + t.ok(req) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.attribute, 'sn') + t.equal(req.value, 'testy') + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeString('cn=foo, o=test'); + const ber = new BerWriter() + ber.writeString('cn=foo, o=test') - ber.startSequence(); - ber.writeString('sn'); - ber.writeString('testy'); - ber.endSequence(); + ber.startSequence() + ber.writeString('sn') + ber.writeString('testy') + ber.endSequence() - const req = new CompareRequest(); - t.ok(req._parse(new BerReader(ber.buffer))); - t.equal(req.dn, 'cn=foo, o=test'); - t.equal(req.attribute, 'sn'); - t.equal(req.value, 'testy'); - t.end(); -}); + const req = new CompareRequest() + t.ok(req._parse(new BerReader(ber.buffer))) + t.equal(req.dn, 'cn=foo, o=test') + t.equal(req.attribute, 'sn') + t.equal(req.value, 'testy') + t.end() +}) test('toBer', function (t) { const req = new CompareRequest({ @@ -45,20 +45,20 @@ test('toBer', function (t) { entry: dn.parse('cn=foo, o=test'), attribute: 'sn', value: 'testy' - }); + }) - t.ok(req); + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x6e); - t.equal(ber.readString(), 'cn=foo, o=test'); - t.ok(ber.readSequence()); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x6e) + t.equal(ber.readString(), 'cn=foo, o=test') + t.ok(ber.readSequence()) - t.equal(ber.readString(), 'sn'); - t.equal(ber.readString(), 'testy'); + t.equal(ber.readString(), 'sn') + t.equal(ber.readString(), 'testy') - t.end(); -}); + t.end() +}) diff --git a/test/messages/compare_response.test.js b/test/messages/compare_response.test.js index f7945af..92ad3af 100644 --- a/test/messages/compare_response.test.js +++ b/test/messages/compare_response.test.js @@ -1,38 +1,38 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { CompareResponse } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { CompareResponse } = require('../../lib') test('new no args', function (t) { - t.ok(new CompareResponse()); - t.end(); -}); + t.ok(new CompareResponse()) + t.end() +}) test('new with args', function (t) { const res = new CompareResponse({ messageID: 123, status: 0 - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.status, 0); - t.end(); -}); + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.status, 0) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeEnumeration(0); - ber.writeString('cn=root'); - ber.writeString('foo'); + const ber = new BerWriter() + ber.writeEnumeration(0) + ber.writeString('cn=root') + ber.writeString('foo') - const res = new CompareResponse(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.status, 0); - t.equal(res.matchedDN, 'cn=root'); - t.equal(res.errorMessage, 'foo'); - t.end(); -}); + const res = new CompareResponse() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.status, 0) + t.equal(res.matchedDN, 'cn=root') + t.equal(res.errorMessage, 'foo') + t.end() +}) test('toBer', function (t) { const res = new CompareResponse({ @@ -40,17 +40,17 @@ test('toBer', function (t) { status: 3, matchedDN: 'cn=root', errorMessage: 'foo' - }); - t.ok(res); + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x6f); - t.equal(ber.readEnumeration(), 3); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(), 'foo'); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x6f) + t.equal(ber.readEnumeration(), 3) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(), 'foo') - t.end(); -}); + t.end() +}) diff --git a/test/messages/del_request.test.js b/test/messages/del_request.test.js index d7c59d3..9de2a6e 100644 --- a/test/messages/del_request.test.js +++ b/test/messages/del_request.test.js @@ -1,47 +1,47 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { DeleteRequest, dn } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { DeleteRequest, dn } = require('../../lib') test('new no args', function (t) { - t.ok(new DeleteRequest()); - t.end(); -}); + t.ok(new DeleteRequest()) + t.end() +}) test('new with args', function (t) { const req = new DeleteRequest({ entry: dn.parse('cn=test') - }); - t.ok(req); - t.equal(req.dn.toString(), 'cn=test'); - t.end(); -}); + }) + t.ok(req) + t.equal(req.dn.toString(), 'cn=test') + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeString('cn=test', 0x4a); + const ber = new BerWriter() + ber.writeString('cn=test', 0x4a) - const req = new DeleteRequest(); - const reader = new BerReader(ber.buffer); - reader.readSequence(0x4a); - t.ok(req.parse(reader, reader.length)); - t.equal(req.dn.toString(), 'cn=test'); - t.end(); -}); + const req = new DeleteRequest() + const reader = new BerReader(ber.buffer) + reader.readSequence(0x4a) + t.ok(req.parse(reader, reader.length)) + t.equal(req.dn.toString(), 'cn=test') + t.end() +}) test('toBer', function (t) { const req = new DeleteRequest({ messageID: 123, entry: dn.parse('cn=test') - }); - t.ok(req); + }) + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readString(0x4a), 'cn=test'); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readString(0x4a), 'cn=test') - t.end(); -}); + t.end() +}) diff --git a/test/messages/del_response.test.js b/test/messages/del_response.test.js index 33e3f00..b45e13f 100644 --- a/test/messages/del_response.test.js +++ b/test/messages/del_response.test.js @@ -1,38 +1,38 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { DeleteResponse } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { DeleteResponse } = require('../../lib') test('new no args', function (t) { - t.ok(new DeleteResponse()); - t.end(); -}); + t.ok(new DeleteResponse()) + t.end() +}) test('new with args', function (t) { const res = new DeleteResponse({ messageID: 123, status: 0 - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.status, 0); - t.end(); -}); + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.status, 0) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeEnumeration(0); - ber.writeString('cn=root'); - ber.writeString('foo'); + const ber = new BerWriter() + ber.writeEnumeration(0) + ber.writeString('cn=root') + ber.writeString('foo') - const res = new DeleteResponse(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.status, 0); - t.equal(res.matchedDN, 'cn=root'); - t.equal(res.errorMessage, 'foo'); - t.end(); -}); + const res = new DeleteResponse() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.status, 0) + t.equal(res.matchedDN, 'cn=root') + t.equal(res.errorMessage, 'foo') + t.end() +}) test('toBer', function (t) { const res = new DeleteResponse({ @@ -40,17 +40,17 @@ test('toBer', function (t) { status: 3, matchedDN: 'cn=root', errorMessage: 'foo' - }); - t.ok(res); + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x6b); - t.equal(ber.readEnumeration(), 3); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(), 'foo'); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x6b) + t.equal(ber.readEnumeration(), 3) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(), 'foo') - t.end(); -}); + t.end() +}) diff --git a/test/messages/ext_request.test.js b/test/messages/ext_request.test.js index c0da1ad..351924e 100644 --- a/test/messages/ext_request.test.js +++ b/test/messages/ext_request.test.js @@ -1,133 +1,125 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { ExtendedRequest } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { ExtendedRequest } = require('../../lib') test('new no args', function (t) { - t.ok(new ExtendedRequest()); - t.end(); -}); - + t.ok(new ExtendedRequest()) + t.end() +}) test('new with args', function (t) { const req = new ExtendedRequest({ requestName: '1.2.3.4', requestValue: 'test' - }); - t.ok(req); - t.equal(req.requestName, '1.2.3.4'); - t.equal(req.requestValue, 'test'); - t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); - t.equal(req.value, 'test'); - t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); - t.end(); -}); - + }) + t.ok(req) + t.equal(req.requestName, '1.2.3.4') + t.equal(req.requestValue, 'test') + t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0) + t.equal(req.value, 'test') + t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0) + t.end() +}) test('new with buffer args', function (t) { const req = new ExtendedRequest({ requestName: '1.2.3.4', requestValue: Buffer.from('test', 'utf8') - }); - t.ok(req); - t.equal(req.requestName, '1.2.3.4'); - t.equal(req.requestValue, req.requestValueBuffer); - t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); - t.equal(req.value, req.valueBuffer); - t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); - t.end(); -}); - + }) + t.ok(req) + t.equal(req.requestName, '1.2.3.4') + t.equal(req.requestValue, req.requestValueBuffer) + t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0) + t.equal(req.value, req.valueBuffer) + t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0) + t.end() +}) test('new no args set args', function (t) { - const req = new ExtendedRequest(); - t.ok(req); + const req = new ExtendedRequest() + t.ok(req) - req.name = '1.2.3.4'; - t.equal(req.requestName, '1.2.3.4'); + req.name = '1.2.3.4' + t.equal(req.requestName, '1.2.3.4') - req.value = 'test'; - t.equal(req.requestValue, 'test'); - t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); - t.equal(req.value, 'test'); - t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); - - t.end(); -}); + req.value = 'test' + t.equal(req.requestValue, 'test') + t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0) + t.equal(req.value, 'test') + t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0) + t.end() +}) test('new no args set args buffer', function (t) { - const req = new ExtendedRequest(); - t.ok(req); + const req = new ExtendedRequest() + t.ok(req) - req.name = '1.2.3.4'; - t.equal(req.requestName, '1.2.3.4'); + req.name = '1.2.3.4' + t.equal(req.requestName, '1.2.3.4') - req.value = Buffer.from('test', 'utf8'); - t.equal(req.requestValue, req.requestValueBuffer); - t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); - t.equal(req.value, req.valueBuffer); - t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); - - t.end(); -}); + req.value = Buffer.from('test', 'utf8') + t.equal(req.requestValue, req.requestValueBuffer) + t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0) + t.equal(req.value, req.valueBuffer) + t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeString('1.2.3.4', 0x80); - ber.writeString('test', 0x81); - - - const req = new ExtendedRequest(); - t.ok(req._parse(new BerReader(ber.buffer))); - t.equal(req.requestName, '1.2.3.4'); - t.equal(req.requestValue, 'test'); - t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); - t.equal(req.value, 'test'); - t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); - t.end(); -}); + const ber = new BerWriter() + ber.writeString('1.2.3.4', 0x80) + ber.writeString('test', 0x81) + const req = new ExtendedRequest() + t.ok(req._parse(new BerReader(ber.buffer))) + t.equal(req.requestName, '1.2.3.4') + t.equal(req.requestValue, 'test') + t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0) + t.equal(req.value, 'test') + t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0) + t.end() +}) test('toBer', function (t) { const req = new ExtendedRequest({ messageID: 123, requestName: '1.2.3.4', requestValue: 'test' - }); + }) - t.ok(req); + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x77); - t.equal(ber.readString(0x80), '1.2.3.4'); - t.equal(ber.readString(0x81), 'test'); - - t.end(); -}); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x77) + t.equal(ber.readString(0x80), '1.2.3.4') + t.equal(ber.readString(0x81), 'test') + t.end() +}) test('toBer from buffer', function (t) { const req = new ExtendedRequest({ messageID: 123, requestName: '1.2.3.4', requestValue: Buffer.from('test', 'utf8') - }); + }) - t.ok(req); + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x77); - t.equal(ber.readString(0x80), '1.2.3.4'); - t.equal(ber.readString(0x81), 'test'); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x77) + t.equal(ber.readString(0x80), '1.2.3.4') + t.equal(ber.readString(0x81), 'test') - t.end(); -}); + t.end() +}) diff --git a/test/messages/ext_response.test.js b/test/messages/ext_response.test.js index 577ffa6..00f2272 100644 --- a/test/messages/ext_response.test.js +++ b/test/messages/ext_response.test.js @@ -1,13 +1,13 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { ExtendedResponse } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { ExtendedResponse } = require('../../lib') test('new no args', function (t) { - t.ok(new ExtendedResponse()); - t.end(); -}); + t.ok(new ExtendedResponse()) + t.end() +}) test('new with args', function (t) { const res = new ExtendedResponse({ @@ -15,32 +15,32 @@ test('new with args', function (t) { status: 0, responseName: '1.2.3.4', responseValue: 'test' - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.status, 0); - t.equal(res.responseName, '1.2.3.4'); - t.equal(res.responseValue, 'test'); - t.end(); -}); + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.status, 0) + t.equal(res.responseName, '1.2.3.4') + t.equal(res.responseValue, 'test') + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeEnumeration(0); - ber.writeString('cn=root'); - ber.writeString('foo'); - ber.writeString('1.2.3.4', 0x8a); - ber.writeString('test', 0x8b); + const ber = new BerWriter() + ber.writeEnumeration(0) + ber.writeString('cn=root') + ber.writeString('foo') + ber.writeString('1.2.3.4', 0x8a) + ber.writeString('test', 0x8b) - const res = new ExtendedResponse(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.status, 0); - t.equal(res.matchedDN, 'cn=root'); - t.equal(res.errorMessage, 'foo'); - t.equal(res.responseName, '1.2.3.4'); - t.equal(res.responseValue, 'test'); - t.end(); -}); + const res = new ExtendedResponse() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.status, 0) + t.equal(res.matchedDN, 'cn=root') + t.equal(res.errorMessage, 'foo') + t.equal(res.responseName, '1.2.3.4') + t.equal(res.responseValue, 'test') + t.end() +}) test('toBer', function (t) { const res = new ExtendedResponse({ @@ -50,19 +50,19 @@ test('toBer', function (t) { errorMessage: 'foo', responseName: '1.2.3.4', responseValue: 'test' - }); - t.ok(res); + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x78); - t.equal(ber.readEnumeration(), 3); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(), 'foo'); - t.equal(ber.readString(0x8a), '1.2.3.4'); - t.equal(ber.readString(0x8b), 'test'); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x78) + t.equal(ber.readEnumeration(), 3) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(), 'foo') + t.equal(ber.readString(0x8a), '1.2.3.4') + t.equal(ber.readString(0x8b), 'test') - t.end(); -}); + t.end() +}) diff --git a/test/messages/moddn_request.test.js b/test/messages/moddn_request.test.js index f252cc5..5d6035a 100644 --- a/test/messages/moddn_request.test.js +++ b/test/messages/moddn_request.test.js @@ -1,41 +1,41 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { ModifyDNRequest, dn } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { ModifyDNRequest, dn } = require('../../lib') test('new no args', function (t) { - t.ok(new ModifyDNRequest()); - t.end(); -}); + t.ok(new ModifyDNRequest()) + t.end() +}) test('new with args', function (t) { const req = new ModifyDNRequest({ entry: dn.parse('cn=foo, o=test'), newRdn: dn.parse('cn=foo2'), deleteOldRdn: true - }); - t.ok(req); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.newRdn.toString(), 'cn=foo2'); - t.equal(req.deleteOldRdn, true); - t.end(); -}); + }) + t.ok(req) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.newRdn.toString(), 'cn=foo2') + t.equal(req.deleteOldRdn, true) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeString('cn=foo, o=test'); - ber.writeString('cn=foo2'); - ber.writeBoolean(true); + const ber = new BerWriter() + ber.writeString('cn=foo, o=test') + ber.writeString('cn=foo2') + ber.writeBoolean(true) - const req = new ModifyDNRequest(); - t.ok(req._parse(new BerReader(ber.buffer))); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.newRdn.toString(), 'cn=foo2'); - t.equal(req.deleteOldRdn, true); + const req = new ModifyDNRequest() + t.ok(req._parse(new BerReader(ber.buffer))) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.newRdn.toString(), 'cn=foo2') + t.equal(req.deleteOldRdn, true) - t.end(); -}); + t.end() +}) test('toBer', function (t) { const req = new ModifyDNRequest({ @@ -43,18 +43,18 @@ test('toBer', function (t) { entry: dn.parse('cn=foo, o=test'), newRdn: dn.parse('cn=foo2'), deleteOldRdn: true - }); + }) - t.ok(req); + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x6c); - t.equal(ber.readString(), 'cn=foo, o=test'); - t.equal(ber.readString(), 'cn=foo2'); - t.equal(ber.readBoolean(), true); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x6c) + t.equal(ber.readString(), 'cn=foo, o=test') + t.equal(ber.readString(), 'cn=foo2') + t.equal(ber.readBoolean(), true) - t.end(); -}); + t.end() +}) diff --git a/test/messages/moddn_response.test.js b/test/messages/moddn_response.test.js index 783a317..162df1b 100644 --- a/test/messages/moddn_response.test.js +++ b/test/messages/moddn_response.test.js @@ -1,38 +1,38 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { ModifyDNResponse } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { ModifyDNResponse } = require('../../lib') test('new no args', function (t) { - t.ok(new ModifyDNResponse()); - t.end(); -}); + t.ok(new ModifyDNResponse()) + t.end() +}) test('new with args', function (t) { const res = new ModifyDNResponse({ messageID: 123, status: 0 - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.status, 0); - t.end(); -}); + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.status, 0) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeEnumeration(0); - ber.writeString('cn=root'); - ber.writeString('foo'); + const ber = new BerWriter() + ber.writeEnumeration(0) + ber.writeString('cn=root') + ber.writeString('foo') - const res = new ModifyDNResponse(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.status, 0); - t.equal(res.matchedDN, 'cn=root'); - t.equal(res.errorMessage, 'foo'); - t.end(); -}); + const res = new ModifyDNResponse() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.status, 0) + t.equal(res.matchedDN, 'cn=root') + t.equal(res.errorMessage, 'foo') + t.end() +}) test('toBer', function (t) { const res = new ModifyDNResponse({ @@ -40,17 +40,17 @@ test('toBer', function (t) { status: 3, matchedDN: 'cn=root', errorMessage: 'foo' - }); - t.ok(res); + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x6d); - t.equal(ber.readEnumeration(), 3); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(), 'foo'); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x6d) + t.equal(ber.readEnumeration(), 3) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(), 'foo') - t.end(); -}); + t.end() +}) diff --git a/test/messages/modify_request.test.js b/test/messages/modify_request.test.js index c2f598b..22e8d1f 100644 --- a/test/messages/modify_request.test.js +++ b/test/messages/modify_request.test.js @@ -1,59 +1,59 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { ModifyRequest, Attribute, Change, dn } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { ModifyRequest, Attribute, Change, dn } = require('../../lib') test('new no args', function (t) { - t.ok(new ModifyRequest()); - t.end(); -}); + t.ok(new ModifyRequest()) + t.end() +}) test('new with args', function (t) { const req = new ModifyRequest({ object: dn.parse('cn=foo, o=test'), changes: [new Change({ operation: 'Replace', - modification: new Attribute({type: 'objectclass', vals: ['person']}) + modification: new Attribute({ type: 'objectclass', vals: ['person'] }) })] - }); - t.ok(req); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.changes.length, 1); - t.equal(req.changes[0].operation, 'replace'); - t.equal(req.changes[0].modification.type, 'objectclass'); - t.equal(req.changes[0].modification.vals[0], 'person'); - t.end(); -}); + }) + t.ok(req) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.changes.length, 1) + t.equal(req.changes[0].operation, 'replace') + t.equal(req.changes[0].modification.type, 'objectclass') + t.equal(req.changes[0].modification.vals[0], 'person') + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeString('cn=foo, o=test'); - ber.startSequence(); + const ber = new BerWriter() + ber.writeString('cn=foo, o=test') + ber.startSequence() - ber.startSequence(); - ber.writeEnumeration(0x02); + ber.startSequence() + ber.writeEnumeration(0x02) - ber.startSequence(); - ber.writeString('objectclass'); - ber.startSequence(0x31); - ber.writeString('person'); - ber.endSequence(); - ber.endSequence(); + ber.startSequence() + ber.writeString('objectclass') + ber.startSequence(0x31) + ber.writeString('person') + ber.endSequence() + ber.endSequence() - ber.endSequence(); + ber.endSequence() - ber.endSequence(); + ber.endSequence() - const req = new ModifyRequest(); - t.ok(req._parse(new BerReader(ber.buffer))); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.changes.length, 1); - t.equal(req.changes[0].operation, 'replace'); - t.equal(req.changes[0].modification.type, 'objectclass'); - t.equal(req.changes[0].modification.vals[0], 'person'); - t.end(); -}); + const req = new ModifyRequest() + t.ok(req._parse(new BerReader(ber.buffer))) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.changes.length, 1) + t.equal(req.changes[0].operation, 'replace') + t.equal(req.changes[0].modification.type, 'objectclass') + t.equal(req.changes[0].modification.vals[0], 'person') + t.end() +}) test('toBer', function (t) { const req = new ModifyRequest({ @@ -61,26 +61,26 @@ test('toBer', function (t) { object: dn.parse('cn=foo, o=test'), changes: [new Change({ operation: 'Replace', - modification: new Attribute({type: 'objectclass', vals: ['person']}) + modification: new Attribute({ type: 'objectclass', vals: ['person'] }) })] - }); + }) - t.ok(req); + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x66); - t.equal(ber.readString(), 'cn=foo, o=test'); - t.ok(ber.readSequence()); - t.ok(ber.readSequence()); - t.equal(ber.readEnumeration(), 0x02); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x66) + t.equal(ber.readString(), 'cn=foo, o=test') + t.ok(ber.readSequence()) + t.ok(ber.readSequence()) + t.equal(ber.readEnumeration(), 0x02) - t.ok(ber.readSequence()); - t.equal(ber.readString(), 'objectclass'); - t.equal(ber.readSequence(), 0x31); - t.equal(ber.readString(), 'person'); + t.ok(ber.readSequence()) + t.equal(ber.readString(), 'objectclass') + t.equal(ber.readSequence(), 0x31) + t.equal(ber.readString(), 'person') - t.end(); -}); + t.end() +}) diff --git a/test/messages/modify_response.test.js b/test/messages/modify_response.test.js index af9ba5d..37e0b22 100644 --- a/test/messages/modify_response.test.js +++ b/test/messages/modify_response.test.js @@ -1,38 +1,38 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { ModifyResponse } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { ModifyResponse } = require('../../lib') test('new no args', function (t) { - t.ok(new ModifyResponse()); - t.end(); -}); + t.ok(new ModifyResponse()) + t.end() +}) test('new with args', function (t) { const res = new ModifyResponse({ messageID: 123, status: 0 - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.status, 0); - t.end(); -}); + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.status, 0) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeEnumeration(0); - ber.writeString('cn=root'); - ber.writeString('foo'); + const ber = new BerWriter() + ber.writeEnumeration(0) + ber.writeString('cn=root') + ber.writeString('foo') - const res = new ModifyResponse(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.status, 0); - t.equal(res.matchedDN, 'cn=root'); - t.equal(res.errorMessage, 'foo'); - t.end(); -}); + const res = new ModifyResponse() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.status, 0) + t.equal(res.matchedDN, 'cn=root') + t.equal(res.errorMessage, 'foo') + t.end() +}) test('toBer', function (t) { const res = new ModifyResponse({ @@ -40,17 +40,17 @@ test('toBer', function (t) { status: 3, matchedDN: 'cn=root', errorMessage: 'foo' - }); - t.ok(res); + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x67); - t.equal(ber.readEnumeration(), 3); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(), 'foo'); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x67) + t.equal(ber.readEnumeration(), 3) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(), 'foo') - t.end(); -}); + t.end() +}) diff --git a/test/messages/parser.test.js b/test/messages/parser.test.js index 7dca311..35eb8cd 100644 --- a/test/messages/parser.test.js +++ b/test/messages/parser.test.js @@ -1,49 +1,49 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { Parser, LDAPMessage, LDAP_REQ_EXTENSION } = require('../../lib'); +const { test } = require('tap') +const { Parser, LDAPMessage, LDAP_REQ_EXTENSION } = require('../../lib') test('wrong protocol error', function (t) { - const p = new Parser(); + const p = new Parser() p.once('error', function (err) { - t.ok(err); - t.end(); - }); + t.ok(err) + t.end() + }) // Send some bogus data to incur an error - p.write(Buffer.from([16, 1, 4])); -}); + p.write(Buffer.from([16, 1, 4])) +}) test('bad protocol op', function (t) { - const p = new Parser(); + const p = new Parser() const message = new LDAPMessage({ protocolOp: 254 // bogus (at least today) - }); + }) p.once('error', function (err) { - t.ok(err); - t.ok(/not supported$/.test(err.message)); - t.end(); - }); - p.write(message.toBer()); -}); + t.ok(err) + t.ok(/not supported$/.test(err.message)) + t.end() + }) + p.write(message.toBer()) +}) test('bad message structure', function (t) { - const p = new Parser(); + const p = new Parser() // message with bogus structure const message = new LDAPMessage({ protocolOp: LDAP_REQ_EXTENSION - }); + }) message._toBer = function (writer) { - writer.writeBuffer(Buffer.from([16, 1, 4]), 80); - return writer; - }; + writer.writeBuffer(Buffer.from([16, 1, 4]), 80) + return writer + } p.once('error', function (err) { - t.ok(err); - t.end(); - }); + t.ok(err) + t.end() + }) - p.write(message.toBer()); -}); + p.write(message.toBer()) +}) diff --git a/test/messages/search_entry.test.js b/test/messages/search_entry.test.js index cf5ddd7..a166ae0 100644 --- a/test/messages/search_entry.test.js +++ b/test/messages/search_entry.test.js @@ -1,91 +1,91 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { SearchEntry, Attribute, dn } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { SearchEntry, Attribute, dn } = require('../../lib') test('new no args', function (t) { - t.ok(new SearchEntry()); - t.end(); -}); + t.ok(new SearchEntry()) + t.end() +}) test('new with args', function (t) { const res = new SearchEntry({ messageID: 123, objectName: dn.parse('cn=foo, o=test'), - attributes: [new Attribute({type: 'cn', vals: ['foo']}), - new Attribute({type: 'objectclass', vals: ['person']})] - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.dn.toString(), 'cn=foo, o=test'); - t.equal(res.attributes.length, 2); - t.equal(res.attributes[0].type, 'cn'); - t.equal(res.attributes[0].vals[0], 'foo'); - t.equal(res.attributes[1].type, 'objectclass'); - t.equal(res.attributes[1].vals[0], 'person'); - t.end(); -}); + attributes: [new Attribute({ type: 'cn', vals: ['foo'] }), + new Attribute({ type: 'objectclass', vals: ['person'] })] + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.dn.toString(), 'cn=foo, o=test') + t.equal(res.attributes.length, 2) + t.equal(res.attributes[0].type, 'cn') + t.equal(res.attributes[0].vals[0], 'foo') + t.equal(res.attributes[1].type, 'objectclass') + t.equal(res.attributes[1].vals[0], 'person') + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeString('cn=foo, o=test'); + const ber = new BerWriter() + ber.writeString('cn=foo, o=test') - ber.startSequence(); + ber.startSequence() - ber.startSequence(); - ber.writeString('cn'); - ber.startSequence(0x31); - ber.writeString('foo'); - ber.endSequence(); - ber.endSequence(); + ber.startSequence() + ber.writeString('cn') + ber.startSequence(0x31) + ber.writeString('foo') + ber.endSequence() + ber.endSequence() - ber.startSequence(); - ber.writeString('objectclass'); - ber.startSequence(0x31); - ber.writeString('person'); - ber.endSequence(); - ber.endSequence(); + ber.startSequence() + ber.writeString('objectclass') + ber.startSequence(0x31) + ber.writeString('person') + ber.endSequence() + ber.endSequence() - ber.endSequence(); + ber.endSequence() - const res = new SearchEntry(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.dn, 'cn=foo, o=test'); - t.equal(res.attributes.length, 2); - t.equal(res.attributes[0].type, 'cn'); - t.equal(res.attributes[0].vals[0], 'foo'); - t.equal(res.attributes[1].type, 'objectclass'); - t.equal(res.attributes[1].vals[0], 'person'); - t.end(); -}); + const res = new SearchEntry() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.dn, 'cn=foo, o=test') + t.equal(res.attributes.length, 2) + t.equal(res.attributes[0].type, 'cn') + t.equal(res.attributes[0].vals[0], 'foo') + t.equal(res.attributes[1].type, 'objectclass') + t.equal(res.attributes[1].vals[0], 'person') + t.end() +}) test('toBer', function (t) { const res = new SearchEntry({ messageID: 123, objectName: dn.parse('cn=foo, o=test'), - attributes: [new Attribute({type: 'cn', vals: ['foo']}), - new Attribute({type: 'objectclass', vals: ['person']})] - }); - t.ok(res); + attributes: [new Attribute({ type: 'cn', vals: ['foo'] }), + new Attribute({ type: 'objectclass', vals: ['person'] })] + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x64); - t.equal(ber.readString(), 'cn=foo, o=test'); - t.ok(ber.readSequence()); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x64) + t.equal(ber.readString(), 'cn=foo, o=test') + t.ok(ber.readSequence()) - t.ok(ber.readSequence()); - t.equal(ber.readString(), 'cn'); - t.equal(ber.readSequence(), 0x31); - t.equal(ber.readString(), 'foo'); + t.ok(ber.readSequence()) + t.equal(ber.readString(), 'cn') + t.equal(ber.readSequence(), 0x31) + t.equal(ber.readString(), 'foo') - t.ok(ber.readSequence()); - t.equal(ber.readString(), 'objectclass'); - t.equal(ber.readSequence(), 0x31); - t.equal(ber.readString(), 'person'); + t.ok(ber.readSequence()) + t.equal(ber.readString(), 'objectclass') + t.equal(ber.readSequence(), 0x31) + t.equal(ber.readString(), 'person') - t.end(); -}); + t.end() +}) diff --git a/test/messages/search_request.test.js b/test/messages/search_request.test.js index 455b90d..81f181e 100644 --- a/test/messages/search_request.test.js +++ b/test/messages/search_request.test.js @@ -1,13 +1,13 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { SearchRequest, EqualityFilter, dn } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { SearchRequest, EqualityFilter, dn } = require('../../lib') test('new no args', function (t) { - t.ok(new SearchRequest()); - t.end(); -}); + t.ok(new SearchRequest()) + t.end() +}) test('new with args', function (t) { const req = new SearchRequest({ @@ -17,43 +17,43 @@ test('new with args', function (t) { value: 'foo@bar.com' }), attributes: ['cn', 'sn'] - }); - t.ok(req); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.filter.toString(), '(email=foo@bar.com)'); - t.equal(req.attributes.length, 2); - t.equal(req.attributes[0], 'cn'); - t.equal(req.attributes[1], 'sn'); - t.end(); -}); + }) + t.ok(req) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.filter.toString(), '(email=foo@bar.com)') + t.equal(req.attributes.length, 2) + t.equal(req.attributes[0], 'cn') + t.equal(req.attributes[1], 'sn') + t.end() +}) test('parse', function (t) { const f = new EqualityFilter({ attribute: 'email', value: 'foo@bar.com' - }); + }) - let ber = new BerWriter(); - ber.writeString('cn=foo, o=test'); - ber.writeEnumeration(0); - ber.writeEnumeration(0); - ber.writeInt(1); - ber.writeInt(2); - ber.writeBoolean(false); - ber = f.toBer(ber); + let ber = new BerWriter() + ber.writeString('cn=foo, o=test') + ber.writeEnumeration(0) + ber.writeEnumeration(0) + ber.writeInt(1) + ber.writeInt(2) + ber.writeBoolean(false) + ber = f.toBer(ber) - const req = new SearchRequest(); - t.ok(req._parse(new BerReader(ber.buffer))); - t.equal(req.dn.toString(), 'cn=foo, o=test'); - t.equal(req.scope, 'base'); - t.equal(req.derefAliases, 0); - t.equal(req.sizeLimit, 1); - t.equal(req.timeLimit, 2); - t.equal(req.typesOnly, false); - t.equal(req.filter.toString(), '(email=foo@bar.com)'); - t.equal(req.attributes.length, 0); - t.end(); -}); + const req = new SearchRequest() + t.ok(req._parse(new BerReader(ber.buffer))) + t.equal(req.dn.toString(), 'cn=foo, o=test') + t.equal(req.scope, 'base') + t.equal(req.derefAliases, 0) + t.equal(req.sizeLimit, 1) + t.equal(req.timeLimit, 2) + t.equal(req.typesOnly, false) + t.equal(req.filter.toString(), '(email=foo@bar.com)') + t.equal(req.attributes.length, 0) + t.end() +}) test('toBer', function (t) { const req = new SearchRequest({ @@ -69,27 +69,27 @@ test('toBer', function (t) { value: 'foo@bar.com' }), attributes: ['cn', 'sn'] - }); + }) - t.ok(req); + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x63); - t.equal(ber.readString(), 'cn=foo, o=test'); - t.equal(ber.readEnumeration(), 1); - t.equal(ber.readEnumeration(), 2); - t.equal(ber.readInt(), 10); - t.equal(ber.readInt(), 20); - t.ok(ber.readBoolean()); - t.equal(ber.readSequence(), 0xa3); - t.equal(ber.readString(), 'email'); - t.equal(ber.readString(), 'foo@bar.com'); - t.ok(ber.readSequence()); - t.equal(ber.readString(), 'cn'); - t.equal(ber.readString(), 'sn'); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x63) + t.equal(ber.readString(), 'cn=foo, o=test') + t.equal(ber.readEnumeration(), 1) + t.equal(ber.readEnumeration(), 2) + t.equal(ber.readInt(), 10) + t.equal(ber.readInt(), 20) + t.ok(ber.readBoolean()) + t.equal(ber.readSequence(), 0xa3) + t.equal(ber.readString(), 'email') + t.equal(ber.readString(), 'foo@bar.com') + t.ok(ber.readSequence()) + t.equal(ber.readString(), 'cn') + t.equal(ber.readString(), 'sn') - t.end(); -}); + t.end() +}) diff --git a/test/messages/search_response.test.js b/test/messages/search_response.test.js index 1dc1d6c..dbfdb90 100644 --- a/test/messages/search_response.test.js +++ b/test/messages/search_response.test.js @@ -1,39 +1,38 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { SearchResponse } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { SearchResponse } = require('../../lib') test('new no args', function (t) { - t.ok(new SearchResponse()); - t.end(); -}); + t.ok(new SearchResponse()) + t.end() +}) test('new with args', function (t) { const res = new SearchResponse({ messageID: 123, status: 0 - }); - t.ok(res); - t.equal(res.messageID, 123); - t.equal(res.status, 0); - t.end(); -}); + }) + t.ok(res) + t.equal(res.messageID, 123) + t.equal(res.status, 0) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); - ber.writeEnumeration(0); - ber.writeString('cn=root'); - ber.writeString('foo'); - - const res = new SearchResponse(); - t.ok(res._parse(new BerReader(ber.buffer))); - t.equal(res.status, 0); - t.equal(res.matchedDN, 'cn=root'); - t.equal(res.errorMessage, 'foo'); - t.end(); -}); + const ber = new BerWriter() + ber.writeEnumeration(0) + ber.writeString('cn=root') + ber.writeString('foo') + const res = new SearchResponse() + t.ok(res._parse(new BerReader(ber.buffer))) + t.equal(res.status, 0) + t.equal(res.matchedDN, 'cn=root') + t.equal(res.errorMessage, 'foo') + t.end() +}) test('toBer', function (t) { const res = new SearchResponse({ @@ -41,17 +40,17 @@ test('toBer', function (t) { status: 3, matchedDN: 'cn=root', errorMessage: 'foo' - }); - t.ok(res); + }) + t.ok(res) - const ber = new BerReader(res.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.equal(ber.readSequence(), 0x65); - t.equal(ber.readEnumeration(), 3); - t.equal(ber.readString(), 'cn=root'); - t.equal(ber.readString(), 'foo'); + const ber = new BerReader(res.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.equal(ber.readSequence(), 0x65) + t.equal(ber.readEnumeration(), 3) + t.equal(ber.readString(), 'cn=root') + t.equal(ber.readString(), 'foo') - t.end(); -}); + t.end() +}) diff --git a/test/messages/unbind_request.test.js b/test/messages/unbind_request.test.js index 10ee45d..5834a61 100644 --- a/test/messages/unbind_request.test.js +++ b/test/messages/unbind_request.test.js @@ -1,37 +1,37 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { BerReader, BerWriter } = require('asn1'); -const { UnbindRequest } = require('../../lib'); +const { test } = require('tap') +const { BerReader, BerWriter } = require('asn1') +const { UnbindRequest } = require('../../lib') test('new no args', function (t) { - t.ok(new UnbindRequest()); - t.end(); -}); + t.ok(new UnbindRequest()) + t.end() +}) test('new with args', function (t) { - const req = new UnbindRequest({}); - t.ok(req); - t.end(); -}); + const req = new UnbindRequest({}) + t.ok(req) + t.end() +}) test('parse', function (t) { - const ber = new BerWriter(); + const ber = new BerWriter() - const req = new UnbindRequest(); - t.ok(req._parse(new BerReader(ber.buffer))); - t.end(); -}); + const req = new UnbindRequest() + t.ok(req._parse(new BerReader(ber.buffer))) + t.end() +}) test('toBer', function (t) { const req = new UnbindRequest({ messageID: 123 - }); - t.ok(req); + }) + t.ok(req) - const ber = new BerReader(req.toBer()); - t.ok(ber); - t.equal(ber.readSequence(), 0x30); - t.equal(ber.readInt(), 123); - t.end(); -}); + const ber = new BerReader(req.toBer()) + t.ok(ber) + t.equal(ber.readSequence(), 0x30) + t.equal(ber.readInt(), 123) + t.end() +}) diff --git a/test/server.test.js b/test/server.test.js index 59571a1..22bd828 100644 --- a/test/server.test.js +++ b/test/server.test.js @@ -1,12 +1,12 @@ -'use strict'; +'use strict' -const tap = require('tap'); -const vasync = require('vasync'); -const { getSock } = require('./utils'); -const ldap = require('../lib'); +const tap = require('tap') +const vasync = require('vasync') +const { getSock } = require('./utils') +const ldap = require('../lib') -const SERVER_PORT = process.env.SERVER_PORT || 1389; -const SUFFIX = 'dc=test'; +const SERVER_PORT = process.env.SERVER_PORT || 1389 +const SUFFIX = 'dc=test' tap.beforeEach(function (done, t) { // We do not need a `.afterEach` to clean up the sock files because that @@ -16,294 +16,295 @@ tap.beforeEach(function (done, t) { }) tap.test('basic create', function (t) { - const server = ldap.createServer(); - t.ok(server); - t.end(); -}); + const server = ldap.createServer() + t.ok(server) + t.end() +}) tap.test('properties', function (t) { - const server = ldap.createServer(); - t.equal(server.name, 'LDAPServer'); + const server = ldap.createServer() + t.equal(server.name, 'LDAPServer') // TODO: better test - server.maxConnections = 10; - t.equal(server.maxConnections, 10); + server.maxConnections = 10 + t.equal(server.maxConnections, 10) - t.equal(server.url, null, 'url empty before bind'); + t.equal(server.url, null, 'url empty before bind') // listen on a random port so we have a url server.listen(0, 'localhost', function () { - t.ok(server.url); + t.ok(server.url) - server.close(() => t.end()); - }); -}); + server.close(() => t.end()) + }) +}) tap.test('listen on unix/named socket', function (t) { - const server = ldap.createServer(); + const server = ldap.createServer() server.listen(t.context.sock, function () { - t.ok(server.url); - t.equal(server.url.split(':')[0], 'ldapi'); - server.close(() => t.end()); - }); -}); + t.ok(server.url) + t.equal(server.url.split(':')[0], 'ldapi') + server.close(() => t.end()) + }) +}) tap.test('listen on static port', function (t) { - const server = ldap.createServer(); + const server = ldap.createServer() server.listen(SERVER_PORT, '127.0.0.1', function () { - const addr = server.address(); - t.equal(addr.port, parseInt(SERVER_PORT, 10)); - t.equals(server.url, `ldap://127.0.0.1:${SERVER_PORT}`); - server.close(() => t.end()); - }); -}); + const addr = server.address() + t.equal(addr.port, parseInt(SERVER_PORT, 10)) + t.equals(server.url, `ldap://127.0.0.1:${SERVER_PORT}`) + server.close(() => t.end()) + }) +}) tap.test('listen on ephemeral port', function (t) { - const server = ldap.createServer(); + const server = ldap.createServer() server.listen(0, 'localhost', function () { - const addr = server.address(); - t.ok(addr.port > 0); - t.ok(addr.port < 65535); - server.close(() => t.end()); - }); -}); + const addr = server.address() + t.ok(addr.port > 0) + t.ok(addr.port < 65535) + server.close(() => t.end()) + }) +}) tap.test('route order', function (t) { - function generateHandler(response) { - const func = function handler(req, res, next) { + function generateHandler (response) { + const func = function handler (req, res, next) { res.send({ dn: response, attributes: { } - }); - res.end(); - return next(); - }; - return func; + }) + res.end() + return next() + } + return func } - const server = ldap.createServer(); - const sock = t.context.sock; - const dnShort = SUFFIX; - const dnMed = 'dc=sub, ' + SUFFIX; - const dnLong = 'dc=long, dc=sub, ' + SUFFIX; + const server = ldap.createServer() + const sock = t.context.sock + const dnShort = SUFFIX + const dnMed = 'dc=sub, ' + SUFFIX + const dnLong = 'dc=long, dc=sub, ' + SUFFIX // Mount routes out of order - server.search(dnMed, generateHandler(dnMed)); - server.search(dnShort, generateHandler(dnShort)); - server.search(dnLong, generateHandler(dnLong)); + server.search(dnMed, generateHandler(dnMed)) + server.search(dnShort, generateHandler(dnShort)) + server.search(dnLong, generateHandler(dnLong)) server.listen(sock, function () { - t.ok(true, 'server listen'); - const client = ldap.createClient({ socketPath: sock }); + t.ok(true, 'server listen') + const client = ldap.createClient({ socketPath: sock }) client.on('connect', () => { vasync.forEachParallel({ - 'func': runSearch, - 'inputs': [dnShort, dnMed, dnLong] + func: runSearch, + inputs: [dnShort, dnMed, dnLong] }, function (err, results) { - t.error(err); - client.unbind(); - server.close(() => t.end()); - }); + t.error(err) + client.unbind() + server.close(() => t.end()) + }) }) - function runSearch(value, cb) { + function runSearch (value, cb) { client.search(value, '(objectclass=*)', function (err, res) { - t.error(err); - t.ok(res); + t.error(err) + t.ok(res) res.on('searchEntry', function (entry) { - t.equal(entry.dn.toString(), value); - }); + t.equal(entry.dn.toString(), value) + }) res.on('end', function () { - cb(); - }); - }); + cb() + }) + }) } - }); -}); + }) +}) tap.test('route absent', function (t) { - const server = ldap.createServer(); - const DN_ROUTE = 'dc=base'; - const DN_MISSING = 'dc=absent'; + const server = ldap.createServer() + const DN_ROUTE = 'dc=base' + const DN_MISSING = 'dc=absent' server.bind(DN_ROUTE, function (req, res, next) { - res.end(); - return next(); - }); + res.end() + return next() + }) server.listen(t.context.sock, function () { - t.ok(true, 'server startup'); + t.ok(true, 'server startup') vasync.parallel({ funcs: [ - function presentBind(cb) { - const clt = ldap.createClient({ socketPath: t.context.sock }); + function presentBind (cb) { + const clt = ldap.createClient({ socketPath: t.context.sock }) clt.bind(DN_ROUTE, '', function (err) { - t.notOk(err); - clt.unbind(); - cb(); - }); + t.notOk(err) + clt.unbind() + cb() + }) }, - function absentBind(cb) { - const clt = ldap.createClient({ socketPath: t.context.sock }); + function absentBind (cb) { + const clt = ldap.createClient({ socketPath: t.context.sock }) clt.bind(DN_MISSING, '', function (err) { - t.ok(err); - t.equal(err.code, ldap.LDAP_NO_SUCH_OBJECT); - clt.unbind(); - cb(); - }); + t.ok(err) + t.equal(err.code, ldap.LDAP_NO_SUCH_OBJECT) + clt.unbind() + cb() + }) } ] }, function (err, result) { - t.notOk(err); - server.close(() => t.end()); - }); - }); -}); + t.notOk(err) + server.close(() => t.end()) + }) + }) +}) tap.test('route unbind', function (t) { - const server = ldap.createServer(); + const server = ldap.createServer() server.unbind(function (req, res, next) { - t.ok(true, 'server unbind successful'); - res.end(); - return next(); - }); + t.ok(true, 'server unbind successful') + res.end() + return next() + }) server.listen(t.context.sock, function () { - t.ok(true, 'server startup'); - const client = ldap.createClient({ socketPath: t.context.sock }); + t.ok(true, 'server startup') + const client = ldap.createClient({ socketPath: t.context.sock }) client.bind('', '', function (err) { - t.error(err, 'client bind error'); + t.error(err, 'client bind error') client.unbind(function (err) { - t.error(err, 'client unbind error'); - server.close(() => t.end()); - }); - }); - }); -}); + t.error(err, 'client unbind error') + server.close(() => t.end()) + }) + }) + }) +}) tap.test('strict routing', function (t) { - const testDN = 'cn=valid'; - let clt; - let server; - const sock = t.context.sock; + const testDN = 'cn=valid' + let clt + let server + const sock = t.context.sock vasync.pipeline({ funcs: [ - function setup(_, cb) { + function setup (_, cb) { server = ldap.createServer({ // strictDN: true - on by default - }); + }) // invalid DNs would go to default handler server.search('', function (req, res, next) { - t.ok(req.dn); - t.equal(typeof (req.dn), 'object'); - t.equal(req.dn.toString(), testDN); - res.end(); - next(); - }); + t.ok(req.dn) + t.equal(typeof (req.dn), 'object') + t.equal(req.dn.toString(), testDN) + res.end() + next() + }) server.listen(sock, function () { - t.ok(true, 'server startup'); + t.ok(true, 'server startup') clt = ldap.createClient({ socketPath: sock, strictDN: false - }); - cb(); - }); + }) + cb() + }) }, - function testBad(_, cb) { - clt.search('not a dn', {scope: 'base'}, function (err, res) { - t.error(err); + function testBad (_, cb) { + clt.search('not a dn', { scope: 'base' }, function (err, res) { + t.error(err) res.once('error', function (err2) { - t.ok(err2); - t.equal(err2.code, ldap.LDAP_INVALID_DN_SYNTAX); - cb(); - }); + t.ok(err2) + t.equal(err2.code, ldap.LDAP_INVALID_DN_SYNTAX) + cb() + }) res.once('end', function () { - t.fail('accepted invalid dn'); - cb('bogus'); - }); - }); + t.fail('accepted invalid dn') + cb(Error('bogus')) + }) + }) }, - function testGood(_, cb) { - clt.search(testDN, {scope: 'base'}, function (err, res) { - t.error(err); + function testGood (_, cb) { + clt.search(testDN, { scope: 'base' }, function (err, res) { + t.error(err) res.once('error', function (err2) { - t.error(err2); - cb(err2); - }); + t.error(err2) + cb(err2) + }) res.once('end', function (result) { - t.ok(result, 'accepted invalid dn'); - cb(); - }); - }); + t.ok(result, 'accepted invalid dn') + cb() + }) + }) } ] - }, function (err, res) { + }, function (err) { + t.error(err) if (clt) { - clt.destroy(); + clt.destroy() } - server.close(() => t.end()); - }); -}); + server.close(() => t.end()) + }) +}) tap.test('non-strict routing', function (t) { const server = ldap.createServer({ strictDN: false - }); - const testDN = 'this ain\'t a DN'; + }) + const testDN = 'this ain\'t a DN' // invalid DNs go to default handler server.search('', function (req, res, next) { - t.ok(req.dn); - t.equal(typeof (req.dn), 'string'); - t.equal(req.dn, testDN); - res.end(); - next(); - }); + t.ok(req.dn) + t.equal(typeof (req.dn), 'string') + t.equal(req.dn, testDN) + res.end() + next() + }) server.listen(t.context.sock, function () { - t.ok(true, 'server startup'); + t.ok(true, 'server startup') const clt = ldap.createClient({ socketPath: t.context.sock, strictDN: false - }); - clt.search(testDN, {scope: 'base'}, function (err, res) { - t.error(err); + }) + clt.search(testDN, { scope: 'base' }, function (err, res) { + t.error(err) res.on('end', function () { - clt.destroy(); - server.close(() => t.end()); - }); - }); - }); -}); + clt.destroy() + server.close(() => t.end()) + }) + }) + }) +}) tap.test('close accept a callback', function (t) { - const server = ldap.createServer(); + const server = ldap.createServer() // callback is called when the server is closed - server.listen(0, function(err) { - t.error(err); - server.close(function(err){ + server.listen(0, function (err) { + t.error(err) + server.close(function (err) { t.error(err) - t.end(); - }); + t.end() + }) }) -}); +}) tap.test('close without error calls callback', function (t) { - const server = ldap.createServer(); + const server = ldap.createServer() // when the server is closed without error, the callback parameter is undefined - server.listen(1389,'127.0.0.1',function(err){ - t.error(err); - server.close(function(err){ - t.error(err); - t.end(); - }); - }); -}); + server.listen(1389, '127.0.0.1', function (err) { + t.error(err) + server.close(function (err) { + t.error(err) + t.end() + }) + }) +}) tap.test('close passes error to callback', function (t) { - const server = ldap.createServer(); + const server = ldap.createServer() // when the server is closed with an error, the error is the first parameter of the callback - server.close(function(err){ - t.ok(err); - t.end(); - }); -}); + server.close(function (err) { + t.ok(err) + t.end() + }) +}) diff --git a/test/url.test.js b/test/url.test.js index c59c1a1..3b5e91e 100644 --- a/test/url.test.js +++ b/test/url.test.js @@ -1,56 +1,58 @@ -'use strict'; +'use strict' -const { test } = require('tap'); -const { parseURL } = require('../lib'); +const { test } = require('tap') +const { parseURL } = require('../lib') test('parse empty', function (t) { - const u = parseURL('ldap:///'); - t.equal(u.hostname, 'localhost'); - t.equal(u.port, 389); - t.ok(!u.DN); - t.ok(!u.attributes); - t.equal(u.secure, false); - t.end(); -}); - + const u = parseURL('ldap:///') + t.equal(u.hostname, 'localhost') + t.equal(u.port, 389) + t.ok(!u.DN) + t.ok(!u.attributes) + t.equal(u.secure, false) + t.end() +}) test('parse hostname', function (t) { - const u = parseURL('ldap://example.com/'); - t.equal(u.hostname, 'example.com'); - t.equal(u.port, 389); - t.ok(!u.DN); - t.ok(!u.attributes); - t.equal(u.secure, false); - t.end(); -}); - + const u = parseURL('ldap://example.com/') + t.equal(u.hostname, 'example.com') + t.equal(u.port, 389) + t.ok(!u.DN) + t.ok(!u.attributes) + t.equal(u.secure, false) + t.end() +}) test('parse host and port', function (t) { - const u = parseURL('ldap://example.com:1389/'); - t.equal(u.hostname, 'example.com'); - t.equal(u.port, 1389); - t.ok(!u.DN); - t.ok(!u.attributes); - t.equal(u.secure, false); - t.end(); -}); - + const u = parseURL('ldap://example.com:1389/') + t.equal(u.hostname, 'example.com') + t.equal(u.port, 1389) + t.ok(!u.DN) + t.ok(!u.attributes) + t.equal(u.secure, false) + t.end() +}) test('parse full', function (t) { - const u = parseURL('ldaps://ldap.example.com:1389/dc=example%20,dc=com' + - '?cn,sn?sub?(cn=Babs%20Jensen)'); + '?cn,sn?sub?(cn=Babs%20Jensen)') - t.equal(u.secure, true); - t.equal(u.hostname, 'ldap.example.com'); - t.equal(u.port, 1389); - t.equal(u.DN, 'dc=example ,dc=com'); - t.ok(u.attributes); - t.equal(u.attributes.length, 2); - t.equal(u.attributes[0], 'cn'); - t.equal(u.attributes[1], 'sn'); - t.equal(u.scope, 'sub'); - t.equal(u.filter.toString(), '(cn=Babs Jensen)'); + t.equal(u.secure, true) + t.equal(u.hostname, 'ldap.example.com') + t.equal(u.port, 1389) + t.equal(u.DN, 'dc=example ,dc=com') + t.ok(u.attributes) + t.equal(u.attributes.length, 2) + t.equal(u.attributes[0], 'cn') + t.equal(u.attributes[1], 'sn') + t.equal(u.scope, 'sub') + t.equal(u.filter.toString(), '(cn=Babs Jensen)') - t.end(); -}); + t.end() +}) + +test('supports href', function (t) { + const u = parseURL('ldaps://ldap.example.com:1389/dc=example%20,dc=com?cn,sn?sub?(cn=Babs%20Jensen)') + t.equal(u.href, 'ldaps://ldap.example.com:1389/dc=example%20,dc=com?cn,sn?sub?(cn=Babs%20Jensen)') + t.end() +}) diff --git a/test/utils.js b/test/utils.js index 54336d1..6d5598b 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,14 +1,14 @@ -'use strict'; +'use strict' -const os = require('os'); -const path = require('path'); -const uuid = require('uuid'); +const os = require('os') +const path = require('path') +const uuid = require('uuid') -function getSock() { +function getSock () { if (process.platform === 'win32') { - return '\\\\.\\pipe\\' + uuid(); + return '\\\\.\\pipe\\' + uuid() } else { - return path.join(os.tmpdir(), uuid()); + return path.join(os.tmpdir(), uuid()) } }