Apply standard linting to the code base (#539)

* Apply standard linting to the code base

* Specify files to lint

* Run lint as first stage

* Update travis config
This commit is contained in:
James Sumners 2019-08-27 17:11:49 -04:00 committed by GitHub
parent 332de11211
commit e2c9b12430
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
110 changed files with 7084 additions and 7500 deletions

View File

@ -14,13 +14,14 @@ cache:
npm: true npm: true
stages: stages:
- lint
- test - test
jobs: jobs:
include: include:
# - stage: lint ✨ - stage: lint ✨
# script: npm run lint script: npm run lint:ci
# node_js: lts/* node_js: lts/*
- stage: test 👩🏽‍💻 - stage: test 👩🏽‍💻
script: npm run test:cov script: npm run test:cov

View File

@ -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 */ /* Any user may search after bind, only cn=root has full power */
var isSearch = (req instanceof ldap.SearchRequest); var isSearch = (req instanceof ldap.SearchRequest)
if (!req.connection.ldap.bindDN.equals('cn=root') && !isSearch) if (!req.connection.ldap.bindDN.equals('cn=root') && !isSearch) { return next(new ldap.InsufficientAccessRightsError()) }
return next(new ldap.InsufficientAccessRightsError());
return next(); return next()
} }
/// --- Globals
///--- Globals var SUFFIX = 'o=smartdc'
var db = {}
var SUFFIX = 'o=smartdc'; var server = ldap.createServer()
var db = {};
var server = ldap.createServer();
server.bind('cn=root', function (req, res, next) { server.bind('cn=root', function (req, res, next) {
if (req.dn.toString() !== 'cn=root' || req.credentials !== 'secret') if (req.dn.toString() !== 'cn=root' || req.credentials !== 'secret') { return next(new ldap.InvalidCredentialsError()) }
return next(new ldap.InvalidCredentialsError());
res.end(); res.end()
return next(); return next()
}); })
server.add(SUFFIX, authorize, function (req, res, next) { server.add(SUFFIX, authorize, function (req, res, next) {
var dn = req.dn.toString(); var dn = req.dn.toString()
if (db[dn]) if (db[dn]) { return next(new ldap.EntryAlreadyExistsError(dn)) }
return next(new ldap.EntryAlreadyExistsError(dn));
db[dn] = req.toObject().attributes; db[dn] = req.toObject().attributes
res.end(); res.end()
return next(); return next()
}); })
server.bind(SUFFIX, function (req, res, next) { server.bind(SUFFIX, function (req, res, next) {
var dn = req.dn.toString(); var dn = req.dn.toString()
if (!db[dn]) if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) }
return next(new ldap.NoSuchObjectError(dn));
if (!db[dn].userpassword) if (!db[dn].userpassword) { return next(new ldap.NoSuchAttributeError('userPassword')) }
return next(new ldap.NoSuchAttributeError('userPassword'));
if (db[dn].userpassword.indexOf(req.credentials) === -1) if (db[dn].userpassword.indexOf(req.credentials) === -1) { return next(new ldap.InvalidCredentialsError()) }
return next(new ldap.InvalidCredentialsError());
res.end(); res.end()
return next(); return next()
}); })
server.compare(SUFFIX, authorize, function (req, res, next) { server.compare(SUFFIX, authorize, function (req, res, next) {
var dn = req.dn.toString(); var dn = req.dn.toString()
if (!db[dn]) if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) }
return next(new ldap.NoSuchObjectError(dn));
if (!db[dn][req.attribute]) if (!db[dn][req.attribute]) { return next(new ldap.NoSuchAttributeError(req.attribute)) }
return next(new ldap.NoSuchAttributeError(req.attribute));
var matches = false; var matches = false
var vals = db[dn][req.attribute]; var vals = db[dn][req.attribute]
for (var i = 0; i < vals.length; i++) { for (var i = 0; i < vals.length; i++) {
if (vals[i] === req.value) { if (vals[i] === req.value) {
matches = true; matches = true
break; break
} }
} }
res.end(matches); res.end(matches)
return next(); return next()
}); })
server.del(SUFFIX, authorize, function (req, res, next) { server.del(SUFFIX, authorize, function (req, res, next) {
var dn = req.dn.toString(); var dn = req.dn.toString()
if (!db[dn]) if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) }
return next(new ldap.NoSuchObjectError(dn));
delete db[dn]; delete db[dn]
res.end(); res.end()
return next(); return next()
}); })
server.modify(SUFFIX, authorize, function (req, res, next) { server.modify(SUFFIX, authorize, function (req, res, next) {
var dn = req.dn.toString(); var dn = req.dn.toString()
if (!req.changes.length) if (!req.changes.length) { return next(new ldap.ProtocolError('changes required')) }
return next(new ldap.ProtocolError('changes required')); if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) }
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++) { for (var i = 0; i < req.changes.length; i++) {
mod = req.changes[i].modification; mod = req.changes[i].modification
switch (req.changes[i].operation) { switch (req.changes[i].operation) {
case 'replace': case 'replace':
if (!entry[mod.type]) if (!entry[mod.type]) { return next(new ldap.NoSuchAttributeError(mod.type)) }
return next(new ldap.NoSuchAttributeError(mod.type));
if (!mod.vals || !mod.vals.length) { if (!mod.vals || !mod.vals.length) {
delete entry[mod.type]; delete entry[mod.type]
} else { } else {
entry[mod.type] = mod.vals; entry[mod.type] = mod.vals
} }
break; break
case 'add': case 'add':
if (!entry[mod.type]) { if (!entry[mod.type]) {
entry[mod.type] = mod.vals; entry[mod.type] = mod.vals
} else { } else {
mod.vals.forEach(function (v) { mod.vals.forEach(function (v) {
if (entry[mod.type].indexOf(v) === -1) if (entry[mod.type].indexOf(v) === -1) { entry[mod.type].push(v) }
entry[mod.type].push(v); })
}); }
}
break; break
case 'delete': case 'delete':
if (!entry[mod.type]) if (!entry[mod.type]) { return next(new ldap.NoSuchAttributeError(mod.type)) }
return next(new ldap.NoSuchAttributeError(mod.type));
delete entry[mod.type]; delete entry[mod.type]
break; break
} }
} }
res.end(); res.end()
return next(); return next()
}); })
server.search(SUFFIX, authorize, function (req, res, next) { server.search(SUFFIX, authorize, function (req, res, next) {
var dn = req.dn.toString(); var dn = req.dn.toString()
if (!db[dn]) if (!db[dn]) { return next(new ldap.NoSuchObjectError(dn)) }
return next(new ldap.NoSuchObjectError(dn));
var scopeCheck; var scopeCheck
switch (req.scope) { switch (req.scope) {
case 'base': case 'base':
if (req.filter.matches(db[dn])) { if (req.filter.matches(db[dn])) {
res.send({ res.send({
dn: dn, dn: dn,
attributes: db[dn] attributes: db[dn]
}); })
} }
res.end(); res.end()
return next(); return next()
case 'one': case 'one':
scopeCheck = function (k) { scopeCheck = function (k) {
if (req.dn.equals(k)) if (req.dn.equals(k)) { return true }
return true;
var parent = ldap.parseDN(k).parent(); var parent = ldap.parseDN(k).parent()
return (parent ? parent.equals(req.dn) : false); return (parent ? parent.equals(req.dn) : false)
}; }
break; break
case 'sub': case 'sub':
scopeCheck = function (k) { scopeCheck = function (k) {
return (req.dn.equals(k) || req.dn.parentOf(k)); return (req.dn.equals(k) || req.dn.parentOf(k))
}; }
break; break
} }
Object.keys(db).forEach(function (key) { Object.keys(db).forEach(function (key) {
if (!scopeCheck(key)) if (!scopeCheck(key)) { return }
return;
if (req.filter.matches(db[key])) { if (req.filter.matches(db[key])) {
res.send({ res.send({
dn: key, dn: key,
attributes: db[key] attributes: db[key]
}); })
} }
}); })
res.end(); res.end()
return next(); return next()
}); })
/// --- Fire it up
///--- Fire it up
server.listen(1389, function () { server.listen(1389, function () {
console.log('LDAP server up at: %s', server.url); console.log('LDAP server up at: %s', server.url)
}); })

View File

@ -1,61 +1,54 @@
// Copyright 2015 Joyent, Inc. // Copyright 2015 Joyent, Inc.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); var util = require('util')
var isDN = require('./dn').DN.isDN; var isDN = require('./dn').DN.isDN
var isAttribute = require('./attribute').isAttribute; var isAttribute = require('./attribute').isAttribute
/// --- Helpers
///--- Helpers
// Copied from mcavage/node-assert-plus // Copied from mcavage/node-assert-plus
function _assert(arg, type, name) { function _assert (arg, type, name) {
name = name || type; name = name || type
throw new assert.AssertionError({ throw new assert.AssertionError({
message: util.format('%s (%s) required', name, type), message: util.format('%s (%s) required', name, type),
actual: typeof (arg), actual: typeof (arg),
expected: type, expected: type,
operator: '===', operator: '===',
stackStartFunction: _assert.caller stackStartFunction: _assert.caller
}); })
} }
/// --- API
///--- API function stringDN (input, name) {
if (isDN(input) || typeof (input) === 'string') { return }
function stringDN(input, name) { _assert(input, 'DN or string', name)
if (isDN(input) || typeof (input) === 'string')
return;
_assert(input, 'DN or string', name);
} }
function optionalStringDN(input, name) { function optionalStringDN (input, name) {
if (input === undefined || isDN(input) || typeof (input) === 'string') if (input === undefined || isDN(input) || typeof (input) === 'string') { return }
return; _assert(input, 'DN or string', name)
_assert(input, 'DN or string', name);
} }
function optionalDN(input, name) { function optionalDN (input, name) {
if (input !== undefined && !isDN(input)) if (input !== undefined && !isDN(input)) { _assert(input, 'DN', name) }
_assert(input, 'DN', name);
} }
function optionalArrayOfAttribute(input, name) { function optionalArrayOfAttribute (input, name) {
if (input === undefined) if (input === undefined) { return }
return;
if (!Array.isArray(input) || if (!Array.isArray(input) ||
input.some(function (v) { return !isAttribute(v); })) { input.some(function (v) { return !isAttribute(v) })) {
_assert(input, 'array of Attribute', name); _assert(input, 'array of Attribute', name)
} }
} }
/// --- Exports
///--- Exports
module.exports = { module.exports = {
stringDN: stringDN, stringDN: stringDN,
optionalStringDN: optionalStringDN, optionalStringDN: optionalStringDN,
optionalDN: optionalDN, optionalDN: optionalDN,
optionalArrayOfAttribute: optionalArrayOfAttribute optionalArrayOfAttribute: optionalArrayOfAttribute
}; }

View File

@ -1,174 +1,160 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // 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 (options) {
if (typeof (options) !== 'object') if (typeof (options) !== 'object') { throw new TypeError('options must be an 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 (options.type && typeof (options.type) !== 'string')
throw new TypeError('options.type must be a string');
} else { } else {
options = {}; options = {}
} }
this.type = options.type || ''; this.type = options.type || ''
this._vals = []; this._vals = []
if (options.vals !== undefined && options.vals !== null) if (options.vals !== undefined && options.vals !== null) { this.vals = options.vals }
this.vals = options.vals;
} }
module.exports = Attribute; module.exports = Attribute
Object.defineProperties(Attribute.prototype, { Object.defineProperties(Attribute.prototype, {
buffers: { buffers: {
get: function getBuffers() { get: function getBuffers () {
return this._vals; return this._vals
}, },
configurable: false configurable: false
}, },
json: { json: {
get: function getJson() { get: function getJson () {
return { return {
type: this.type, type: this.type,
vals: this.vals vals: this.vals
}; }
}, },
configurable: false configurable: false
}, },
vals: { vals: {
get: function getVals() { get: function getVals () {
var eType = _bufferEncoding(this.type); var eType = _bufferEncoding(this.type)
return this._vals.map(function (v) { return this._vals.map(function (v) {
return v.toString(eType); return v.toString(eType)
}); })
}, },
set: function setVals(vals) { set: function setVals (vals) {
var self = this; var self = this
this._vals = []; this._vals = []
if (Array.isArray(vals)) { if (Array.isArray(vals)) {
vals.forEach(function (v) { vals.forEach(function (v) {
self.addValue(v); self.addValue(v)
}); })
} else { } else {
self.addValue(vals); self.addValue(vals)
} }
}, },
configurable: false configurable: false
} }
}); })
Attribute.prototype.addValue = function addValue (val) {
Attribute.prototype.addValue = function addValue(val) {
if (Buffer.isBuffer(val)) { if (Buffer.isBuffer(val)) {
this._vals.push(val); this._vals.push(val)
} else { } else {
this._vals.push(Buffer.from(val + '', _bufferEncoding(this.type))); this._vals.push(Buffer.from(val + '', _bufferEncoding(this.type)))
} }
}; }
/* BEGIN JSSTYLED */ /* BEGIN JSSTYLED */
Attribute.compare = function compare(a, b) { Attribute.compare = function compare (a, b) {
if (!(Attribute.isAttribute(a)) || !(Attribute.isAttribute(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.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.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++) { 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 */ /* END JSSTYLED */
Attribute.prototype.parse = function parse (ber) {
assert.ok(ber)
Attribute.prototype.parse = function parse(ber) { ber.readSequence()
assert.ok(ber); this.type = ber.readString()
ber.readSequence();
this.type = ber.readString();
if (ber.peek() === Protocol.LBER_SET) { if (ber.peek() === Protocol.LBER_SET) {
if (ber.readSequence(Protocol.LBER_SET)) { if (ber.readSequence(Protocol.LBER_SET)) {
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) while (ber.offset < end) { this._vals.push(ber.readString(asn1.Ber.OctetString, true)) }
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) { ber.startSequence()
assert.ok(ber); ber.writeString(this.type)
ber.startSequence(Protocol.LBER_SET)
ber.startSequence();
ber.writeString(this.type);
ber.startSequence(Protocol.LBER_SET);
if (this._vals.length) { if (this._vals.length) {
this._vals.forEach(function (b) { this._vals.forEach(function (b) {
ber.writeByte(asn1.Ber.OctetString); ber.writeByte(asn1.Ber.OctetString)
ber.writeLength(b.length); ber.writeLength(b.length)
for (var i = 0; i < b.length; i++) for (var i = 0; i < b.length; i++) { ber.writeByte(b[i]) }
ber.writeByte(b[i]); })
});
} else { } else {
ber.writeStringArray([]); ber.writeStringArray([])
} }
ber.endSequence(); ber.endSequence()
ber.endSequence(); ber.endSequence()
return ber;
};
return ber
}
Attribute.prototype.toString = function () { Attribute.prototype.toString = function () {
return JSON.stringify(this.json); return JSON.stringify(this.json)
}; }
Attribute.toBer = function (attr, ber) { 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') { if (!attr || typeof (attr) !== 'object') {
return false; return false
} }
if (attr instanceof Attribute) { if (attr instanceof Attribute) {
return true; return true
} }
if ((typeof (attr.toBer) === 'function') && if ((typeof (attr.toBer) === 'function') &&
(typeof (attr.type) === 'string') && (typeof (attr.type) === 'string') &&
(Array.isArray(attr.vals)) && (Array.isArray(attr.vals)) &&
(attr.vals.filter(function (item) { (attr.vals.filter(function (item) {
return (typeof (item) === 'string' || return (typeof (item) === 'string' ||
Buffer.isBuffer(item)); Buffer.isBuffer(item))
}).length === attr.vals.length)) { }).length === attr.vals.length)) {
return true; return true
} }
return false; return false
}; }
function _bufferEncoding (type) {
function _bufferEncoding(type) { /* JSSTYLED */
/* JSSTYLED */ return /;binary$/.test(type) ? 'base64' : 'utf8'
return /;binary$/.test(type) ? 'base64' : 'utf8';
} }

View File

@ -1,129 +1,125 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var Attribute = require('./attribute'); var Attribute = require('./attribute')
var Protocol = require('./protocol'); // var Protocol = require('./protocol')
/// --- API
///--- API function Change (options) {
function Change(options) {
if (options) { if (options) {
assert.object(options); assert.object(options)
assert.optionalString(options.operation); assert.optionalString(options.operation)
} else { } else {
options = {}; options = {}
} }
this._modification = false; this._modification = false
this.operation = options.operation || options.type || 'add'; this.operation = options.operation || options.type || 'add'
this.modification = options.modification || {}; this.modification = options.modification || {}
} }
Object.defineProperties(Change.prototype, { Object.defineProperties(Change.prototype, {
operation: { operation: {
get: function getOperation() { get: function getOperation () {
switch (this._operation) { switch (this._operation) {
case 0x00: return 'add'; case 0x00: return 'add'
case 0x01: return 'delete'; case 0x01: return 'delete'
case 0x02: return 'replace'; case 0x02: return 'replace'
default: default:
throw new Error('0x' + this._operation.toString(16) + ' is invalid'); throw new Error('0x' + this._operation.toString(16) + ' is invalid')
} }
}, },
set: function setOperation(val) { set: function setOperation (val) {
assert.string(val); assert.string(val)
switch (val.toLowerCase()) { switch (val.toLowerCase()) {
case 'add': case 'add':
this._operation = 0x00; this._operation = 0x00
break; break
case 'delete': case 'delete':
this._operation = 0x01; this._operation = 0x01
break; break
case 'replace': case 'replace':
this._operation = 0x02; this._operation = 0x02
break; break
default: default:
throw new Error('Invalid operation type: 0x' + val.toString(16)); throw new Error('Invalid operation type: 0x' + val.toString(16))
} }
}, },
configurable: false configurable: false
}, },
modification: { modification: {
get: function getModification() { get: function getModification () {
return this._modification; return this._modification
}, },
set: function setModification(val) { set: function setModification (val) {
if (Attribute.isAttribute(val)) { if (Attribute.isAttribute(val)) {
this._modification = val; this._modification = val
return; return
} }
// Does it have an attribute-like structure // Does it have an attribute-like structure
if (Object.keys(val).length == 2 && if (Object.keys(val).length === 2 &&
typeof (val.type) === 'string' && typeof (val.type) === 'string' &&
Array.isArray(val.vals)) { Array.isArray(val.vals)) {
this._modification = new Attribute({ this._modification = new Attribute({
type: val.type, type: val.type,
vals: val.vals vals: val.vals
}); })
return; return
} }
var keys = Object.keys(val); var keys = Object.keys(val)
if (keys.length > 1) { 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) { } else if (keys.length === 0) {
return; return
} }
var k = keys[0]; var k = keys[0]
var _attr = new Attribute({type: k}); var _attr = new Attribute({ type: k })
if (Array.isArray(val[k])) { if (Array.isArray(val[k])) {
val[k].forEach(function (v) { val[k].forEach(function (v) {
_attr.addValue(v.toString()); _attr.addValue(v.toString())
}); })
} else if (val[k] !== undefined && val[k] !== null) { } 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 configurable: false
}, },
json: { json: {
get: function getJSON() { get: function getJSON () {
return { return {
operation: this.operation, operation: this.operation,
modification: this._modification ? this._modification.json : {} modification: this._modification ? this._modification.json : {}
}; }
}, },
configurable: false configurable: false
} }
}); })
Change.isChange = function isChange(change) { Change.isChange = function isChange (change) {
if (!change || typeof (change) !== 'object') { if (!change || typeof (change) !== 'object') {
return false; return false
} }
if ((change instanceof Change) || if ((change instanceof Change) ||
((typeof (change.toBer) === 'function') && ((typeof (change.toBer) === 'function') &&
(change.modification !== undefined) && (change.modification !== undefined) &&
(change.operation !== undefined))) { (change.operation !== undefined))) {
return true; return true
} }
return false; return false
}; }
Change.compare = function (a, b) { Change.compare = function (a, b) {
if (!Change.isChange(a) || !Change.isChange(b)) if (!Change.isChange(a) || !Change.isChange(b)) { throw new TypeError('can only compare Changes') }
throw new TypeError('can only compare Changes');
if (a.operation < b.operation) if (a.operation < b.operation) { return -1 }
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. * 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 {Object} obj the object to apply it to.
* @param {Boolean} scalar convert single-item arrays to scalars. Default: false * @param {Boolean} scalar convert single-item arrays to scalars. Default: false
*/ */
Change.apply = function apply(change, obj, scalar) { Change.apply = function apply (change, obj, scalar) {
assert.string(change.operation); assert.string(change.operation)
assert.string(change.modification.type); assert.string(change.modification.type)
assert.ok(Array.isArray(change.modification.vals)); assert.ok(Array.isArray(change.modification.vals))
assert.object(obj); assert.object(obj)
var type = change.modification.type; var type = change.modification.type
var vals = change.modification.vals; var vals = change.modification.vals
var data = obj[type]; var data = obj[type]
if (data !== undefined) { if (data !== undefined) {
if (!Array.isArray(data)) { if (!Array.isArray(data)) {
data = [data]; data = [data]
} }
} else { } else {
data = []; data = []
} }
switch (change.operation) { switch (change.operation) {
case 'replace': case 'replace':
if (vals.length === 0) { if (vals.length === 0) {
// replace empty is a delete // replace empty is a delete
delete obj[type]; delete obj[type]
return obj; return obj
} else { } else {
data = vals; data = vals
} }
break; break
case 'add': case 'add':
// add only new unique entries // add only new unique entries
var newValues = vals.filter(function (entry) { var newValues = vals.filter(function (entry) {
return (data.indexOf(entry) === -1); return (data.indexOf(entry) === -1)
}); })
data = data.concat(newValues); data = data.concat(newValues)
break; break
case 'delete': case 'delete':
data = data.filter(function (entry) { data = data.filter(function (entry) {
return (vals.indexOf(entry) === -1); return (vals.indexOf(entry) === -1)
}); })
if (data.length === 0) { if (data.length === 0) {
// Erase the attribute if empty // Erase the attribute if empty
delete obj[type]; delete obj[type]
return obj; return obj
} }
break; break
default: default:
break; break
} }
if (scalar && data.length === 1) { if (scalar && data.length === 1) {
// store single-value outputs as scalars, if requested // store single-value outputs as scalars, if requested
obj[type] = data[0]; obj[type] = data[0]
} else { } else {
obj[type] = data; obj[type] = data
} }
return obj; return obj
}; }
Change.prototype.parse = function (ber) { Change.prototype.parse = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.readSequence(); ber.readSequence()
this._operation = ber.readEnumeration(); this._operation = ber.readEnumeration()
this._modification = new Attribute(); this._modification = new Attribute()
this._modification.parse(ber); this._modification.parse(ber)
return true;
};
return true
}
Change.prototype.toBer = function (ber) { Change.prototype.toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.startSequence(); ber.startSequence()
ber.writeEnumeration(this._operation); ber.writeEnumeration(this._operation)
ber = this._modification.toBer(ber); ber = this._modification.toBer(ber)
ber.endSequence(); ber.endSequence()
return ber; return ber
}; }
/// --- Exports
///--- Exports module.exports = Change
module.exports = Change;

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +1,35 @@
// Copyright 2012 Mark Cavage, Inc. All rights reserved. // Copyright 2012 Mark Cavage, Inc. All rights reserved.
const logger = require('../logger'); const logger = require('../logger')
const Client = require('./client'); const Client = require('./client')
/// --- Functions
function xor () {
///--- Functions var b = false
function xor() {
var b = false;
for (var i = 0; i < arguments.length; i++) { for (var i = 0; i < arguments.length; i++) {
if (arguments[i] && !b) { if (arguments[i] && !b) {
b = true; b = true
} else if (arguments[i] && b) { } else if (arguments[i] && b) {
return false; return false
} }
} }
return b; return b
} }
/// --- Exports
///--- Exports
module.exports = { module.exports = {
Client: Client, Client: Client,
createClient: function createClient(options) { createClient: function createClient (options) {
if (typeof (options) !== 'object') if (typeof (options) !== 'object') { throw new TypeError('options (object) required') }
throw new TypeError('options (object) required'); if (options.url && typeof (options.url) !== 'string') { throw new TypeError('options.url (string) required') }
if (options.url && typeof (options.url) !== 'string') if (options.socketPath && typeof (options.socketPath) !== 'string') { throw new TypeError('options.socketPath must be a string') }
throw new TypeError('options.url (string) required'); if (!xor(options.url, options.socketPath)) { throw new TypeError('options.url ^ options.socketPath (String) required') }
if (options.socketPath && typeof (options.socketPath) !== 'string') if (!options.log) { options.log = logger }
throw new TypeError('options.socketPath must be a string'); if (!options.log.child) { options.log.child = function () { return options.log } }
if (!xor(options.url, options.socketPath)) if (typeof (options.log) !== 'object') { throw new TypeError('options.log must be an object') }
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)
} }
}; }

View File

@ -1,18 +1,16 @@
// Copyright 2014 Joyent, Inc. All rights reserved. 'use strict'
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter
var util = require('util'); var util = require('util')
var assert = require('assert-plus'); var assert = require('assert-plus')
var dn = require('../dn'); // var dn = require('../dn')
var messages = require('../messages/index'); // var messages = require('../messages/index')
var Protocol = require('../protocol'); // var Protocol = require('../protocol')
var PagedControl = require('../controls/paged_results_control.js'); var PagedControl = require('../controls/paged_results_control.js')
///--- API
/// --- API
/** /**
* Handler object for paged search operations. * Handler object for paged search operations.
@ -33,140 +31,140 @@ var PagedControl = require('../controls/paged_results_control.js');
* able to emit 'end'. * able to emit 'end'.
* 3. search - Emitted as an internal event to trigger another client search. * 3. search - Emitted as an internal event to trigger another client search.
*/ */
function SearchPager(opts) { function SearchPager (opts) {
assert.object(opts); assert.object(opts)
assert.func(opts.callback); assert.func(opts.callback)
assert.number(opts.pageSize); assert.number(opts.pageSize)
EventEmitter.call(this, {}); EventEmitter.call(this, {})
this.callback = opts.callback; this.callback = opts.callback
this.controls = opts.controls; this.controls = opts.controls
this.pageSize = opts.pageSize; this.pageSize = opts.pageSize
this.pagePause = opts.pagePause; this.pagePause = opts.pagePause
this.controls.forEach(function (control) { this.controls.forEach(function (control) {
if (control.type === PagedControl.OID) { if (control.type === PagedControl.OID) {
// The point of using SearchPager is not having to do this. // The point of using SearchPager is not having to do this.
// Toss an error if the pagedResultsControl is present // Toss an error if the pagedResultsControl is present
throw new Error('redundant pagedResultControl'); throw new Error('redundant pagedResultControl')
} }
}); })
this.finished = false; this.finished = false
this.started = false; this.started = false
var emitter = new EventEmitter(); var emitter = new EventEmitter()
emitter.on('searchEntry', this.emit.bind(this, 'searchEntry')); emitter.on('searchEntry', this.emit.bind(this, 'searchEntry'))
emitter.on('end', this._onEnd.bind(this)); emitter.on('end', this._onEnd.bind(this))
emitter.on('error', this._onError.bind(this)); emitter.on('error', this._onError.bind(this))
this.childEmitter = emitter; this.childEmitter = emitter
} }
util.inherits(SearchPager, EventEmitter); util.inherits(SearchPager, EventEmitter)
module.exports = SearchPager; module.exports = SearchPager
/** /**
* Start the paged search. * Start the paged search.
*/ */
SearchPager.prototype.begin = function begin() { SearchPager.prototype.begin = function begin () {
// Starting first page // Starting first page
this._nextPage(null); this._nextPage(null)
}; }
SearchPager.prototype._onEnd = function _onEnd(res) { SearchPager.prototype._onEnd = function _onEnd (res) {
var self = this; var self = this
var cookie = null; var cookie = null
res.controls.forEach(function (control) { res.controls.forEach(function (control) {
if (control.type === PagedControl.OID) { if (control.type === PagedControl.OID) {
cookie = control.value.cookie; cookie = control.value.cookie
} }
}); })
// Pass a noop callback by default for page events // Pass a noop callback by default for page events
var nullCb = function () { }; var nullCb = function () { }
if (cookie === null) { if (cookie === null) {
// paged search not supported // paged search not supported
this.finished = true; this.finished = true
this.emit('page', res, nullCb); this.emit('page', res, nullCb)
var err = new Error('missing paged control'); var err = new Error('missing paged control')
err.name = 'PagedError'; err.name = 'PagedError'
if (this.listeners('pageError').length > 0) { if (this.listeners('pageError').length > 0) {
this.emit('pageError', err); this.emit('pageError', err)
// If the consumer as subscribed to pageError, SearchPager is absolved // If the consumer as subscribed to pageError, SearchPager is absolved
// from deliverying the fault via the 'error' event. Emitting an 'end' // from deliverying the fault via the 'error' event. Emitting an 'end'
// event after 'error' breaks the contract that the standard client // event after 'error' breaks the contract that the standard client
// provides, so it's only a possibility if 'pageError' is used instead. // provides, so it's only a possibility if 'pageError' is used instead.
this.emit('end', res); this.emit('end', res)
} else { } else {
this.emit('error', err); this.emit('error', err)
// No end event possible per explaination above. // No end event possible per explaination above.
} }
return; return
} }
if (cookie.length === 0) { if (cookie.length === 0) {
// end of paged results // end of paged results
this.finished = true; this.finished = true
this.emit('page', nullCb); this.emit('page', nullCb)
this.emit('end', res); this.emit('end', res)
} else { } else {
if (this.pagePause) { if (this.pagePause) {
// Wait to fetch next page until callback is invoked // Wait to fetch next page until callback is invoked
// Halt page fetching if called with error // Halt page fetching if called with error
this.emit('page', res, function (err) { this.emit('page', res, function (err) {
if (!err) { if (!err) {
self._nextPage(cookie); self._nextPage(cookie)
} else { } else {
// the paged search has been canceled so emit an end // the paged search has been canceled so emit an end
self.emit('end', res); self.emit('end', res)
} }
}); })
} else { } else {
this.emit('page', res, nullCb); this.emit('page', res, nullCb)
this._nextPage(cookie); this._nextPage(cookie)
} }
} }
}; }
SearchPager.prototype._onError = function _onError(err) { SearchPager.prototype._onError = function _onError (err) {
this.finished = true; this.finished = true
this.emit('error', err); this.emit('error', err)
}; }
/** /**
* Initiate a search for the next page using the returned cookie value. * Initiate a search for the next page using the returned cookie value.
*/ */
SearchPager.prototype._nextPage = function _nextPage(cookie) { SearchPager.prototype._nextPage = function _nextPage (cookie) {
var controls = this.controls.slice(0); var controls = this.controls.slice(0)
controls.push(new PagedControl({ controls.push(new PagedControl({
value: { value: {
size: this.pageSize, size: this.pageSize,
cookie: cookie cookie: cookie
} }
})); }))
this.emit('search', controls, this.childEmitter, this.emit('search', controls, this.childEmitter,
this._sendCallback.bind(this)); this._sendCallback.bind(this))
}; }
/** /**
* Callback provided to the client API for successful transmission. * 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) { if (err) {
this.finished = true; this.finished = true
if (!this.started) { if (!this.started) {
// EmitSend error during the first page, bail via callback // EmitSend error during the first page, bail via callback
this.callback(err, null); this.callback(err, null)
} else { } else {
this.emit('error', err); this.emit('error', err)
} }
} else { } else {
// search successfully send // search successfully send
if (!this.started) { if (!this.started) {
this.started = true; this.started = true
// send self as emitter as the client would // send self as emitter as the client would
this.callback(null, this); this.callback(null, this)
} }
} }
}; }

View File

@ -1,67 +1,61 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util');
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
function Control (options) {
///--- API assert.optionalObject(options)
options = options || {}
function Control(options) { assert.optionalString(options.type)
assert.optionalObject(options); assert.optionalBool(options.criticality)
options = options || {};
assert.optionalString(options.type);
assert.optionalBool(options.criticality);
if (options.value) { if (options.value) {
assert.buffer(options.value); assert.buffer(options.value)
} }
this.type = options.type || ''; this.type = options.type || ''
this.criticality = options.critical || options.criticality || false; this.criticality = options.critical || options.criticality || false
this.value = options.value || null; this.value = options.value || null
} }
Object.defineProperties(Control.prototype, { Object.defineProperties(Control.prototype, {
json: { json: {
get: function getJson() { get: function getJson () {
var obj = { var obj = {
controlType: this.type, controlType: this.type,
criticality: this.criticality, criticality: this.criticality,
controlValue: this.value 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) { Control.prototype.toBer = function toBer (ber) {
assert.ok(ber); assert.ok(ber)
ber.startSequence(); ber.startSequence()
ber.writeString(this.type || ''); ber.writeString(this.type || '')
ber.writeBoolean(this.criticality); ber.writeBoolean(this.criticality)
if (typeof (this._toBer) === 'function') { if (typeof (this._toBer) === 'function') {
this._toBer(ber); this._toBer(ber)
} else { } else {
if (this.value) if (this.value) { ber.writeString(this.value) }
ber.writeString(this.value);
} }
ber.endSequence(); ber.endSequence()
return; }
};
Control.prototype.toString = function toString() { Control.prototype.toString = function toString () {
return this.json; return this.json
}; }
/// --- Exports
///--- Exports module.exports = Control
module.exports = Control;

View File

@ -1,89 +1,83 @@
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); 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; /// --- API
var BerWriter = asn1.BerWriter;
function EntryChangeNotificationControl (options) {
///--- API assert.optionalObject(options)
options = options || {}
function EntryChangeNotificationControl(options) { options.type = EntryChangeNotificationControl.OID
assert.optionalObject(options);
options = options || {};
options.type = EntryChangeNotificationControl.OID;
if (options.value) { if (options.value) {
if (Buffer.isBuffer(options.value)) { if (Buffer.isBuffer(options.value)) {
this.parse(options.value); this.parse(options.value)
} else if (typeof (options.value) === 'object') { } else if (typeof (options.value) === 'object') {
this._value = options.value; this._value = options.value
} else { } 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, { Object.defineProperties(EntryChangeNotificationControl.prototype, {
value: { value: {
get: function () { return this._value || {}; }, get: function () { return this._value || {} },
configurable: false configurable: false
} }
}); })
EntryChangeNotificationControl.prototype.parse = function parse(buffer) { EntryChangeNotificationControl.prototype.parse = function parse (buffer) {
assert.ok(buffer); assert.ok(buffer)
var ber = new BerReader(buffer); var ber = new BerReader(buffer)
if (ber.readSequence()) { if (ber.readSequence()) {
this._value = { this._value = {
changeType: ber.readInt() changeType: ber.readInt()
}; }
// if the operation was moddn, then parse the optional previousDN attr // if the operation was moddn, then parse the optional previousDN attr
if (this._value.changeType === 8) if (this._value.changeType === 8) { this._value.previousDN = ber.readString() }
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) { EntryChangeNotificationControl.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
if (!this._value) if (!this._value) { return }
return;
var writer = new BerWriter(); var writer = new BerWriter()
writer.startSequence(); writer.startSequence()
writer.writeInt(this.value.changeType); writer.writeInt(this.value.changeType)
if (this.value.previousDN) if (this.value.previousDN) { writer.writeString(this.value.previousDN) }
writer.writeString(this.value.previousDN);
writer.writeInt(parseInt(this.value.changeNumber, 10)); writer.writeInt(parseInt(this.value.changeNumber, 10))
writer.endSequence(); writer.endSequence()
ber.writeBuffer(writer.buffer, 0x04); ber.writeBuffer(writer.buffer, 0x04)
}; }
EntryChangeNotificationControl.prototype._json = function (obj) { EntryChangeNotificationControl.prototype._json = function (obj) {
obj.controlValue = this.value; obj.controlValue = this.value
return obj; return obj
}; }
EntryChangeNotificationControl.OID = '2.16.840.1.113730.3.4.7'; EntryChangeNotificationControl.OID = '2.16.840.1.113730.3.4.7'
/// --- Exports
///--- Exports module.exports = EntryChangeNotificationControl
module.exports = EntryChangeNotificationControl;

View File

@ -1,73 +1,68 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var Ber = require('asn1').Ber; var Ber = require('asn1').Ber
var Control = require('./control'); var Control = require('./control')
var EntryChangeNotificationControl = var EntryChangeNotificationControl =
require('./entry_change_notification_control'); require('./entry_change_notification_control')
var PersistentSearchControl = require('./persistent_search_control'); var PersistentSearchControl = require('./persistent_search_control')
var PagedResultsControl = require('./paged_results_control'); var PagedResultsControl = require('./paged_results_control')
var ServerSideSortingRequestControl = var ServerSideSortingRequestControl =
require('./server_side_sorting_request_control.js'); require('./server_side_sorting_request_control.js')
var ServerSideSortingResponseControl = var ServerSideSortingResponseControl =
require('./server_side_sorting_response_control.js'); require('./server_side_sorting_response_control.js')
/// --- API
///--- API
module.exports = { module.exports = {
getControl: function getControl(ber) { getControl: function getControl (ber) {
assert.ok(ber); assert.ok(ber)
if (ber.readSequence() === null) if (ber.readSequence() === null) { return null }
return null;
var type; var type
var opts = { var opts = {
criticality: false, criticality: false,
value: null value: null
}; }
if (ber.length) { 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.offset < end) {
if (ber.peek() === Ber.Boolean) if (ber.peek() === Ber.Boolean) { opts.criticality = ber.readBoolean() }
opts.criticality = ber.readBoolean();
} }
if (ber.offset < end) if (ber.offset < end) { opts.value = ber.readString(Ber.OctetString, true) }
opts.value = ber.readString(Ber.OctetString, true);
} }
var control; var control
switch (type) { switch (type) {
case PersistentSearchControl.OID: case PersistentSearchControl.OID:
control = new PersistentSearchControl(opts); control = new PersistentSearchControl(opts)
break; break
case EntryChangeNotificationControl.OID: case EntryChangeNotificationControl.OID:
control = new EntryChangeNotificationControl(opts); control = new EntryChangeNotificationControl(opts)
break; break
case PagedResultsControl.OID: case PagedResultsControl.OID:
control = new PagedResultsControl(opts); control = new PagedResultsControl(opts)
break; break
case ServerSideSortingRequestControl.OID: case ServerSideSortingRequestControl.OID:
control = new ServerSideSortingRequestControl(opts); control = new ServerSideSortingRequestControl(opts)
break; break
case ServerSideSortingResponseControl.OID: case ServerSideSortingResponseControl.OID:
control = new ServerSideSortingResponseControl(opts); control = new ServerSideSortingResponseControl(opts)
break; break
default: default:
opts.type = type; opts.type = type
control = new Control(opts); control = new Control(opts)
break; break
} }
return control; return control
}, },
Control: Control, Control: Control,
@ -76,4 +71,4 @@ module.exports = {
PersistentSearchControl: PersistentSearchControl, PersistentSearchControl: PersistentSearchControl,
ServerSideSortingRequestControl: ServerSideSortingRequestControl, ServerSideSortingRequestControl: ServerSideSortingRequestControl,
ServerSideSortingResponseControl: ServerSideSortingResponseControl ServerSideSortingResponseControl: ServerSideSortingResponseControl
}; }

View File

@ -1,87 +1,82 @@
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); 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; /// --- API
var BerWriter = asn1.BerWriter;
function PagedResultsControl (options) {
///--- API assert.optionalObject(options)
options = options || {}
function PagedResultsControl(options) { options.type = PagedResultsControl.OID
assert.optionalObject(options);
options = options || {};
options.type = PagedResultsControl.OID;
if (options.value) { if (options.value) {
if (Buffer.isBuffer(options.value)) { if (Buffer.isBuffer(options.value)) {
this.parse(options.value); this.parse(options.value)
} else if (typeof (options.value) === 'object') { } else if (typeof (options.value) === 'object') {
this._value = options.value; this._value = options.value
} else { } 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, { Object.defineProperties(PagedResultsControl.prototype, {
value: { value: {
get: function () { return this._value || {}; }, get: function () { return this._value || {} },
configurable: false configurable: false
} }
}); })
PagedResultsControl.prototype.parse = function parse(buffer) { PagedResultsControl.prototype.parse = function parse (buffer) {
assert.ok(buffer); assert.ok(buffer)
var ber = new BerReader(buffer); var ber = new BerReader(buffer)
if (ber.readSequence()) { if (ber.readSequence()) {
this._value = {}; this._value = {}
this._value.size = ber.readInt(); this._value.size = ber.readInt()
this._value.cookie = ber.readString(asn1.Ber.OctetString, true); this._value.cookie = ber.readString(asn1.Ber.OctetString, true)
//readString returns '' instead of a zero-length buffer // readString returns '' instead of a zero-length buffer
if (!this._value.cookie) if (!this._value.cookie) { this._value.cookie = Buffer.alloc(0) }
this._value.cookie = Buffer.alloc(0);
return true; return true
} }
return false; return false
}; }
PagedResultsControl.prototype._toBer = function (ber) { PagedResultsControl.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
if (!this._value) if (!this._value) { return }
return;
var writer = new BerWriter(); var writer = new BerWriter()
writer.startSequence(); writer.startSequence()
writer.writeInt(this.value.size); writer.writeInt(this.value.size)
if (this.value.cookie && this.value.cookie.length > 0) { 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 { } 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) { PagedResultsControl.prototype._json = function (obj) {
obj.controlValue = this.value; obj.controlValue = this.value
return obj; return obj
}; }
PagedResultsControl.OID = '1.2.840.113556.1.4.319'; PagedResultsControl.OID = '1.2.840.113556.1.4.319'
/// --- Exports
///--- Exports module.exports = PagedResultsControl
module.exports = PagedResultsControl;

View File

@ -1,85 +1,82 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); 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; /// --- API
var BerWriter = asn1.BerWriter;
function PersistentSearchControl (options) {
///--- API assert.optionalObject(options)
options = options || {}
function PersistentSearchControl(options) { options.type = PersistentSearchControl.OID
assert.optionalObject(options);
options = options || {};
options.type = PersistentSearchControl.OID;
if (options.value) { if (options.value) {
if (Buffer.isBuffer(options.value)) { if (Buffer.isBuffer(options.value)) {
this.parse(options.value); this.parse(options.value)
} else if (typeof (options.value) === 'object') { } else if (typeof (options.value) === 'object') {
this._value = options.value; this._value = options.value
} else { } 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, { Object.defineProperties(PersistentSearchControl.prototype, {
value: { value: {
get: function () { return this._value || {}; }, get: function () { return this._value || {} },
configurable: false configurable: false
} }
}); })
PersistentSearchControl.prototype.parse = function parse(buffer) { PersistentSearchControl.prototype.parse = function parse (buffer) {
assert.ok(buffer); assert.ok(buffer)
var ber = new BerReader(buffer); var ber = new BerReader(buffer)
if (ber.readSequence()) { if (ber.readSequence()) {
this._value = { this._value = {
changeTypes: ber.readInt(), changeTypes: ber.readInt(),
changesOnly: ber.readBoolean(), changesOnly: ber.readBoolean(),
returnECs: ber.readBoolean() returnECs: ber.readBoolean()
}; }
return true; return true
} }
return false; return false
}; }
PersistentSearchControl.prototype._toBer = function (ber) { PersistentSearchControl.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
if (!this._value) if (!this._value) { return }
return;
var writer = new BerWriter(); var writer = new BerWriter()
writer.startSequence(); writer.startSequence()
writer.writeInt(this.value.changeTypes); writer.writeInt(this.value.changeTypes)
writer.writeBoolean(this.value.changesOnly); writer.writeBoolean(this.value.changesOnly)
writer.writeBoolean(this.value.returnECs); writer.writeBoolean(this.value.returnECs)
writer.endSequence(); writer.endSequence()
ber.writeBuffer(writer.buffer, 0x04); ber.writeBuffer(writer.buffer, 0x04)
}; }
PersistentSearchControl.prototype._json = function (obj) { PersistentSearchControl.prototype._json = function (obj) {
obj.controlValue = this.value; obj.controlValue = this.value
return obj; return obj
}; }
PersistentSearchControl.OID = '2.16.840.1.113730.3.4.3'; PersistentSearchControl.OID = '2.16.840.1.113730.3.4.3'
///--- Exports /// --- Exports
module.exports = PersistentSearchControl; module.exports = PersistentSearchControl

View File

@ -1,112 +1,108 @@
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); 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; /// --- API
var BerWriter = asn1.BerWriter;
function ServerSideSortingRequestControl (options) {
///--- API assert.optionalObject(options)
options = options || {}
function ServerSideSortingRequestControl(options) { options.type = ServerSideSortingRequestControl.OID
assert.optionalObject(options);
options = options || {};
options.type = ServerSideSortingRequestControl.OID;
if (options.value) { if (options.value) {
if (Buffer.isBuffer(options.value)) { if (Buffer.isBuffer(options.value)) {
this.parse(options.value); this.parse(options.value)
} else if (Array.isArray(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++) { for (var i = 0; i < options.value.length; i++) {
if (!options.value[i].hasOwnProperty('attributeType')) { if (Object.prototype.hasOwnProperty.call(options.value[i], 'attributeType') === false) {
throw new Error('Missing required key: attributeType'); throw new Error('Missing required key: attributeType')
} }
} }
this._value = options.value; this._value = options.value
} else if (typeof (options.value) === 'object') { } else if (typeof (options.value) === 'object') {
if (!options.value.hasOwnProperty('attributeType')) { if (Object.prototype.hasOwnProperty.call(options.value, 'attributeType') === false) {
throw new Error('Missing required key: attributeType'); throw new Error('Missing required key: attributeType')
} }
this._value = [options.value]; this._value = [options.value]
} else { } 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, { Object.defineProperties(ServerSideSortingRequestControl.prototype, {
value: { value: {
get: function () { return this._value || []; }, get: function () { return this._value || [] },
configurable: false configurable: false
} }
}); })
ServerSideSortingRequestControl.prototype.parse = function parse(buffer) { ServerSideSortingRequestControl.prototype.parse = function parse (buffer) {
assert.ok(buffer); assert.ok(buffer)
var ber = new BerReader(buffer); var ber = new BerReader(buffer)
var item; var item
if (ber.readSequence(0x30)) { if (ber.readSequence(0x30)) {
this._value = []; this._value = []
while (ber.readSequence(0x30)) { while (ber.readSequence(0x30)) {
item = {}; item = {}
item.attributeType = ber.readString(asn1.Ber.OctetString); item.attributeType = ber.readString(asn1.Ber.OctetString)
if (ber.peek() == 0x80) { if (ber.peek() === 0x80) {
item.orderingRule = ber.readString(0x80); item.orderingRule = ber.readString(0x80)
} }
if (ber.peek() == 0x81) { if (ber.peek() === 0x81) {
item.reverseOrder = (ber._readTag(0x81) === 0 ? false : true); 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) { ServerSideSortingRequestControl.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
if (!this._value || this.value.length === 0) if (!this._value || this.value.length === 0) { return }
return;
var writer = new BerWriter(); var writer = new BerWriter()
writer.startSequence(0x30); writer.startSequence(0x30)
for (var i = 0; i < this.value.length; i++) { for (var i = 0; i < this.value.length; i++) {
var item = this.value[i]; var item = this.value[i]
writer.startSequence(0x30); writer.startSequence(0x30)
if (item.attributeType) { if (item.attributeType) {
writer.writeString(item.attributeType, asn1.Ber.OctetString); writer.writeString(item.attributeType, asn1.Ber.OctetString)
} }
if (item.orderingRule) { if (item.orderingRule) {
writer.writeString(item.orderingRule, 0x80); writer.writeString(item.orderingRule, 0x80)
} }
if (item.reverseOrder) { if (item.reverseOrder) {
writer.writeBoolean(item.reverseOrder, 0x81); writer.writeBoolean(item.reverseOrder, 0x81)
} }
writer.endSequence(); writer.endSequence()
} }
writer.endSequence(); writer.endSequence()
ber.writeBuffer(writer.buffer, 0x04); ber.writeBuffer(writer.buffer, 0x04)
}; }
ServerSideSortingRequestControl.prototype._json = function (obj) { ServerSideSortingRequestControl.prototype._json = function (obj) {
obj.controlValue = this.value; obj.controlValue = this.value
return obj; 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;

View File

@ -1,16 +1,15 @@
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var asn1 = require('asn1'); var asn1 = require('asn1')
var Control = require('./control'); var Control = require('./control')
var CODES = require('../errors/codes'); 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 = [ var VALID_CODES = [
CODES.LDAP_SUCCESS, CODES.LDAP_SUCCESS,
@ -24,80 +23,78 @@ var VALID_CODES = [
CODES.LDAP_BUSY, CODES.LDAP_BUSY,
CODES.LDAP_UNWILLING_TO_PERFORM, CODES.LDAP_UNWILLING_TO_PERFORM,
CODES.LDAP_OTHER CODES.LDAP_OTHER
]; ]
function ServerSideSortingResponseControl(options) { function ServerSideSortingResponseControl (options) {
assert.optionalObject(options); assert.optionalObject(options)
options = options || {}; options = options || {}
options.type = ServerSideSortingResponseControl.OID; options.type = ServerSideSortingResponseControl.OID
options.criticality = false; options.criticality = false
if (options.value) { if (options.value) {
if (Buffer.isBuffer(options.value)) { if (Buffer.isBuffer(options.value)) {
this.parse(options.value); this.parse(options.value)
} else if (typeof (options.value) === 'object') { } else if (typeof (options.value) === 'object') {
if (VALID_CODES.indexOf(options.value.result) === -1) { if (VALID_CODES.indexOf(options.value.result) === -1) {
throw new Error('Invalid result code'); throw new Error('Invalid result code')
} }
if (options.value.failedAttribute && if (options.value.failedAttribute &&
typeof (options.value.failedAttribute) !== 'string') { 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 { } 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, { Object.defineProperties(ServerSideSortingResponseControl.prototype, {
value: { value: {
get: function () { return this._value || {}; }, get: function () { return this._value || {} },
configurable: false configurable: false
} }
}); })
ServerSideSortingResponseControl.prototype.parse = function parse(buffer) { ServerSideSortingResponseControl.prototype.parse = function parse (buffer) {
assert.ok(buffer); assert.ok(buffer)
var ber = new BerReader(buffer); var ber = new BerReader(buffer)
if (ber.readSequence(0x30)) { if (ber.readSequence(0x30)) {
this._value = {}; this._value = {}
this._value.result = ber.readEnumeration(); this._value.result = ber.readEnumeration()
if (ber.peek() == 0x80) { if (ber.peek() === 0x80) {
this._value.failedAttribute = ber.readString(0x80); this._value.failedAttribute = ber.readString(0x80)
} }
return true; return true
} }
return false; return false
}; }
ServerSideSortingResponseControl.prototype._toBer = function (ber) { ServerSideSortingResponseControl.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
if (!this._value || this.value.length === 0) if (!this._value || this.value.length === 0) { return }
return;
var writer = new BerWriter(); var writer = new BerWriter()
writer.startSequence(0x30); writer.startSequence(0x30)
writer.writeEnumeration(this.value.result); writer.writeEnumeration(this.value.result)
if (this.value.result !== CODES.LDAP_SUCCESS && this.value.failedAttribute) { if (this.value.result !== CODES.LDAP_SUCCESS && this.value.failedAttribute) {
writer.writeString(this.value.failedAttribute, 0x80); writer.writeString(this.value.failedAttribute, 0x80)
} }
writer.endSequence(); writer.endSequence()
ber.writeBuffer(writer.buffer, 0x04); ber.writeBuffer(writer.buffer, 0x04)
}; }
ServerSideSortingResponseControl.prototype._json = function (obj) { ServerSideSortingResponseControl.prototype._json = function (obj) {
obj.controlValue = this.value; obj.controlValue = this.value
return obj; return obj
}; }
ServerSideSortingResponseControl.OID = '1.2.840.113556.1.4.474'; ServerSideSortingResponseControl.OID = '1.2.840.113556.1.4.474'
/// --- Exports
///--- Exports module.exports = ServerSideSortingResponseControl
module.exports = ServerSideSortingResponseControl;

525
lib/dn.js
View File

@ -1,336 +1,317 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus')
var assert = require('assert-plus'); /// --- Helpers
function invalidDN (name) {
///--- Helpers var e = new Error()
e.name = 'InvalidDistinguishedNameError'
function invalidDN(name) { e.message = name
var e = new Error(); return e
e.name = 'InvalidDistinguishedNameError';
e.message = name;
return e;
} }
function isAlphaNumeric(c) { function isAlphaNumeric (c) {
var re = /[A-Za-z0-9]/; var re = /[A-Za-z0-9]/
return re.test(c); return re.test(c)
} }
function isWhitespace(c) { function isWhitespace (c) {
var re = /\s/; var re = /\s/
return re.test(c); return re.test(c)
} }
function repeatChar(c, n) { function repeatChar (c, n) {
var out = ''; var out = ''
var max = n ? n : 0; var max = n || 0
for (var i = 0; i < max; i++) for (var i = 0; i < max; i++) { out += c }
out += c; return out
return out;
} }
///--- API /// --- API
function RDN(obj) { function RDN (obj) {
var self = this; var self = this
this.attrs = {}; this.attrs = {}
if (obj) { if (obj) {
Object.keys(obj).forEach(function (k) { Object.keys(obj).forEach(function (k) {
self.set(k, obj[k]); self.set(k, obj[k])
}); })
} }
} }
RDN.prototype.set = function rdnSet(name, value, opts) { RDN.prototype.set = function rdnSet (name, value, opts) {
assert.string(name, 'name (string) required'); assert.string(name, 'name (string) required')
assert.string(value, 'value (string) required'); assert.string(value, 'value (string) required')
var self = this; var self = this
var lname = name.toLowerCase(); var lname = name.toLowerCase()
this.attrs[lname] = { this.attrs[lname] = {
value: value, value: value,
name: name name: name
}; }
if (opts && typeof (opts) === 'object') { if (opts && typeof (opts) === 'object') {
Object.keys(opts).forEach(function (k) { Object.keys(opts).forEach(function (k) {
if (k !== 'value') if (k !== 'value') { self.attrs[lname][k] = opts[k] }
self.attrs[lname][k] = opts[k]; })
});
} }
}; }
RDN.prototype.equals = function rdnEquals(rdn) { RDN.prototype.equals = function rdnEquals (rdn) {
if (typeof (rdn) !== 'object') if (typeof (rdn) !== 'object') { return false }
return false;
var ourKeys = Object.keys(this.attrs); var ourKeys = Object.keys(this.attrs)
var theirKeys = Object.keys(rdn.attrs); var theirKeys = Object.keys(rdn.attrs)
if (ourKeys.length !== theirKeys.length) if (ourKeys.length !== theirKeys.length) { return false }
return false;
ourKeys.sort(); ourKeys.sort()
theirKeys.sort(); theirKeys.sort()
for (var i = 0; i < ourKeys.length; i++) { for (var i = 0; i < ourKeys.length; i++) {
if (ourKeys[i] !== theirKeys[i]) if (ourKeys[i] !== theirKeys[i]) { return false }
return false; if (this.attrs[ourKeys[i]].value !== rdn.attrs[ourKeys[i]].value) { 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. * Convert RDN to string according to specified formatting options.
* (see: DN.format for option details) * (see: DN.format for option details)
*/ */
RDN.prototype.format = function rdnFormat(options) { RDN.prototype.format = function rdnFormat (options) {
assert.optionalObject(options, 'options must be an object'); assert.optionalObject(options, 'options must be an object')
options = options || {}; options = options || {}
var self = this; var self = this
var str = ''; var str = ''
function escapeValue(val, forceQuote) { function escapeValue (val, forceQuote) {
var out = ''; var out = ''
var cur = 0; var cur = 0
var len = val.length; var len = val.length
var quoted = false; var quoted = false
/* BEGIN JSSTYLED */ /* BEGIN JSSTYLED */
var escaped = /[\\\"]/; // TODO: figure out what this regex is actually trying to test for and
var special = /[,=+<>#;]/; // fix it to appease the linter.
/* eslint-disable-next-line no-useless-escape */
var escaped = /[\\\"]/
var special = /[,=+<>#;]/
/* END JSSTYLED */ /* END JSSTYLED */
if (len > 0) { if (len > 0) {
// Wrap strings with trailing or leading spaces in quotes // 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) { while (cur < len) {
if (escaped.test(val[cur]) || (!quoted && special.test(val[cur]))) { if (escaped.test(val[cur]) || (!quoted && special.test(val[cur]))) {
out += '\\'; out += '\\'
} }
out += val[cur++]; out += val[cur++]
} }
if (quoted) if (quoted) { out = '"' + out + '"' }
out = '"' + out + '"'; return out
return out;
} }
function sortParsed(a, b) { function sortParsed (a, b) {
return self.attrs[a].order - self.attrs[b].order; return self.attrs[a].order - self.attrs[b].order
} }
function sortStandard(a, b) { function sortStandard (a, b) {
var nameCompare = a.localeCompare(b); var nameCompare = a.localeCompare(b)
if (nameCompare === 0) { if (nameCompare === 0) {
// TODO: Handle binary values // 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 { } else {
return nameCompare; return nameCompare
} }
} }
var keys = Object.keys(this.attrs); var keys = Object.keys(this.attrs)
if (options.keepOrder) { if (options.keepOrder) {
keys.sort(sortParsed); keys.sort(sortParsed)
} else { } else {
keys.sort(sortStandard); keys.sort(sortStandard)
} }
keys.forEach(function (key) { keys.forEach(function (key) {
var attr = self.attrs[key]; var attr = self.attrs[key]
if (str.length) if (str.length) { str += '+' }
str += '+';
if (options.keepCase) { if (options.keepCase) {
str += attr.name; str += attr.name
} else { } else {
if (options.upperName) if (options.upperName) { str += key.toUpperCase() } else { str += key }
str += key.toUpperCase();
else
str += key;
} }
str += '=' + escapeValue(attr.value, (options.keepQuote && attr.quoted)); str += '=' + escapeValue(attr.value, (options.keepQuote && attr.quoted))
}); })
return str; return str
}; }
RDN.prototype.toString = function rdnToString() {
return this.format();
};
RDN.prototype.toString = function rdnToString () {
return this.format()
}
// Thank you OpenJDK! // Thank you OpenJDK!
function parse(name) { function parse (name) {
if (typeof (name) !== 'string') if (typeof (name) !== 'string') { throw new TypeError('name (string) required') }
throw new TypeError('name (string) required');
var cur = 0; var cur = 0
var len = name.length; var len = name.length
function parseRdn() { function parseRdn () {
var rdn = new RDN(); var rdn = new RDN()
var order = 0; var order = 0
rdn.spLead = trim(); rdn.spLead = trim()
while (cur < len) { while (cur < len) {
var opts = { var opts = {
order: order order: order
}; }
var attr = parseAttrType(); var attr = parseAttrType()
trim(); trim()
if (cur >= len || name[cur++] !== '=') if (cur >= len || name[cur++] !== '=') { throw invalidDN(name) }
throw invalidDN(name);
trim(); trim()
// Parameters about RDN value are set in 'opts' by parseAttrValue // Parameters about RDN value are set in 'opts' by parseAttrValue
var value = parseAttrValue(opts); var value = parseAttrValue(opts)
rdn.set(attr, value, opts); rdn.set(attr, value, opts)
rdn.spTrail = trim(); rdn.spTrail = trim()
if (cur >= len || name[cur] !== '+') if (cur >= len || name[cur] !== '+') { break }
break; ++cur
++cur; ++order
++order;
} }
return rdn; return rdn
} }
function trim () {
function trim() { var count = 0
var count = 0;
while ((cur < len) && isWhitespace(name[cur])) { while ((cur < len) && isWhitespace(name[cur])) {
++cur; ++cur
count++; count++
} }
return count; return count
} }
function parseAttrType() { function parseAttrType () {
var beg = cur; var beg = cur
while (cur < len) { while (cur < len) {
var c = name[cur]; var c = name[cur]
if (isAlphaNumeric(c) || if (isAlphaNumeric(c) ||
c == '.' || c === '.' ||
c == '-' || c === '-' ||
c == ' ') { c === ' ') {
++cur; ++cur
} else { } else {
break; break
} }
} }
// Back out any trailing spaces. // Back out any trailing spaces.
while ((cur > beg) && (name[cur - 1] == ' ')) while ((cur > beg) && (name[cur - 1] === ' ')) { --cur }
--cur;
if (beg == cur) if (beg === cur) { throw invalidDN(name) }
throw invalidDN(name);
return name.slice(beg, cur); return name.slice(beg, cur)
} }
function parseAttrValue(opts) { function parseAttrValue (opts) {
if (cur < len && name[cur] == '#') { if (cur < len && name[cur] === '#') {
opts.binary = true; opts.binary = true
return parseBinaryAttrValue(); return parseBinaryAttrValue()
} else if (cur < len && name[cur] == '"') { } else if (cur < len && name[cur] === '"') {
opts.quoted = true; opts.quoted = true
return parseQuotedAttrValue(); return parseQuotedAttrValue()
} else { } else {
return parseStringAttrValue(); return parseStringAttrValue()
} }
} }
function parseBinaryAttrValue() { function parseBinaryAttrValue () {
var beg = cur++; var beg = cur++
while (cur < len && isAlphaNumeric(name[cur])) while (cur < len && isAlphaNumeric(name[cur])) { ++cur }
++cur;
return name.slice(beg, cur); return name.slice(beg, cur)
} }
function parseQuotedAttrValue() { function parseQuotedAttrValue () {
var str = ''; var str = ''
++cur; // Consume the first quote ++cur // Consume the first quote
while ((cur < len) && name[cur] != '"') { while ((cur < len) && name[cur] !== '"') {
if (name[cur] === '\\') if (name[cur] === '\\') { cur++ }
cur++; str += name[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() { function parseStringAttrValue () {
var beg = cur; var beg = cur
var str = ''; var str = ''
var esc = -1; var esc = -1
while ((cur < len) && !atTerminator()) { while ((cur < len) && !atTerminator()) {
if (name[cur] === '\\') { if (name[cur] === '\\') {
// Consume the backslash and mark its place just in case it's escaping // Consume the backslash and mark its place just in case it's escaping
// whitespace which needs to be preserved. // whitespace which needs to be preserved.
esc = cur++; esc = cur++
} }
if (cur === len) // backslash followed by nothing if (cur === len) {
throw invalidDN(name); // backslash followed by nothing
str += name[cur++]; throw invalidDN(name)
}
str += name[cur++]
} }
// Trim off (unescaped) trailing whitespace and rewind cursor to the end of // Trim off (unescaped) trailing whitespace and rewind cursor to the end of
// the AttrValue to record whitespace length. // the AttrValue to record whitespace length.
for (; cur > beg; cur--) { for (; cur > beg; cur--) {
if (!isWhitespace(name[cur - 1]) || (esc === (cur - 1))) if (!isWhitespace(name[cur - 1]) || (esc === (cur - 1))) { break }
break;
} }
return str.slice(0, cur - beg); return str.slice(0, cur - beg)
} }
function atTerminator() { function atTerminator () {
return (cur < len && return (cur < len &&
(name[cur] === ',' || (name[cur] === ',' ||
name[cur] === ';' || name[cur] === ';' ||
name[cur] === '+')); name[cur] === '+'))
} }
var rdns = []; var rdns = []
// Short-circuit for empty DNs // Short-circuit for empty DNs
if (len === 0) if (len === 0) { return new DN(rdns) }
return new DN(rdns);
rdns.push(parseRdn()); rdns.push(parseRdn())
while (cur < len) { while (cur < len) {
if (name[cur] === ',' || name[cur] === ';') { if (name[cur] === ',' || name[cur] === ';') {
++cur; ++cur
rdns.push(parseRdn()); rdns.push(parseRdn())
} else { } 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) { this.rdns = rdns ? rdns.slice() : []
assert.optionalArrayOfObject(rdns, '[object] required'); this._format = {}
this.rdns = rdns ? rdns.slice() : [];
this._format = {};
} }
Object.defineProperties(DN.prototype, { Object.defineProperties(DN.prototype, {
length: { length: {
get: function getLength() { return this.rdns.length; }, get: function getLength () { return this.rdns.length },
configurable: false configurable: false
} }
}); })
/** /**
* Convert DN to string according to specified formatting options. * 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. * - upperName: RDN names will be uppercased instead of lowercased.
* - skipSpace: Disable trailing space after RDN separators * - skipSpace: Disable trailing space after RDN separators
*/ */
DN.prototype.format = function dnFormat(options) { DN.prototype.format = function dnFormat (options) {
assert.optionalObject(options, 'options must be an object'); assert.optionalObject(options, 'options must be an object')
options = options || this._format; options = options || this._format
var str = ''; var str = ''
this.rdns.forEach(function (rdn) { this.rdns.forEach(function (rdn) {
var rdnString = rdn.format(options); var rdnString = rdn.format(options)
if (str.length !== 0) { if (str.length !== 0) {
str += ','; str += ','
} }
if (options.keepSpace) { if (options.keepSpace) {
str += (repeatChar(' ', rdn.spLead) + str += (repeatChar(' ', rdn.spLead) +
rdnString + repeatChar(' ', rdn.spTrail)); rdnString + repeatChar(' ', rdn.spTrail))
} else if (options.skipSpace === true || str.length === 0) { } else if (options.skipSpace === true || str.length === 0) {
str += rdnString; str += rdnString
} else { } else {
str += ' ' + rdnString; str += ' ' + rdnString
} }
}); })
return str; return str
}; }
/** /**
* Set default string formatting options. * Set default string formatting options.
*/ */
DN.prototype.setFormat = function setFormat(options) { DN.prototype.setFormat = function setFormat (options) {
assert.object(options, 'options must be an object'); assert.object(options, 'options must be an object')
this._format = options; this._format = options
}; }
DN.prototype.toString = function dnToString() { DN.prototype.toString = function dnToString () {
return this.format(); return this.format()
}; }
DN.prototype.parentOf = function parentOf(dn) { DN.prototype.parentOf = function parentOf (dn) {
if (typeof (dn) !== 'object') if (typeof (dn) !== 'object') { dn = parse(dn) }
dn = parse(dn);
if (this.rdns.length >= dn.rdns.length) if (this.rdns.length >= dn.rdns.length) { return false }
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--) { for (var i = this.rdns.length - 1; i >= 0; i--) {
var myRDN = this.rdns[i]; var myRDN = this.rdns[i]
var theirRDN = dn.rdns[i + diff]; var theirRDN = dn.rdns[i + diff]
if (!myRDN.equals(theirRDN)) if (!myRDN.equals(theirRDN)) { return false }
return false;
} }
return true; return true
}; }
DN.prototype.childOf = function childOf(dn) { DN.prototype.childOf = function childOf (dn) {
if (typeof (dn) !== 'object') if (typeof (dn) !== 'object') { dn = parse(dn) }
dn = parse(dn); return dn.parentOf(this)
return dn.parentOf(this); }
};
DN.prototype.isEmpty = function isEmpty() { DN.prototype.isEmpty = function isEmpty () {
return (this.rdns.length === 0); return (this.rdns.length === 0)
}; }
DN.prototype.equals = function dnEquals(dn) { DN.prototype.equals = function dnEquals (dn) {
if (typeof (dn) !== 'object') if (typeof (dn) !== 'object') { dn = parse(dn) }
dn = parse(dn);
if (this.rdns.length !== dn.rdns.length) if (this.rdns.length !== dn.rdns.length) { return false }
return false;
for (var i = 0; i < this.rdns.length; i++) { for (var i = 0; i < this.rdns.length; i++) {
if (!this.rdns[i].equals(dn.rdns[i])) if (!this.rdns[i].equals(dn.rdns[i])) { return false }
return false;
} }
return true; return true
}; }
DN.prototype.parent = function dnParent() { DN.prototype.parent = function dnParent () {
if (this.rdns.length !== 0) { if (this.rdns.length !== 0) {
var save = this.rdns.shift(); var save = this.rdns.shift()
var dn = new DN(this.rdns); var dn = new DN(this.rdns)
this.rdns.unshift(save); this.rdns.unshift(save)
return dn; return dn
} }
return null; return null
}; }
DN.prototype.clone = function dnClone() { DN.prototype.clone = function dnClone () {
var dn = new DN(this.rdns); var dn = new DN(this.rdns)
dn._format = this._format; dn._format = this._format
return dn; return dn
}; }
DN.prototype.reverse = function dnReverse() { DN.prototype.reverse = function dnReverse () {
this.rdns.reverse(); this.rdns.reverse()
return this; return this
}; }
DN.prototype.pop = function dnPop() { DN.prototype.pop = function dnPop () {
return this.rdns.pop(); return this.rdns.pop()
}; }
DN.prototype.push = function dnPush(rdn) { DN.prototype.push = function dnPush (rdn) {
assert.object(rdn, 'rdn (RDN) required'); assert.object(rdn, 'rdn (RDN) required')
return this.rdns.push(rdn); return this.rdns.push(rdn)
}; }
DN.prototype.shift = function dnShift() { DN.prototype.shift = function dnShift () {
return this.rdns.shift(); return this.rdns.shift()
}; }
DN.prototype.unshift = function dnUnshift(rdn) { DN.prototype.unshift = function dnUnshift (rdn) {
assert.object(rdn, 'rdn (RDN) required'); 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') { if (!dn || typeof (dn) !== 'object') {
return false; return false
} }
if (dn instanceof DN) { if (dn instanceof DN) {
return true; return true
} }
if (Array.isArray(dn.rdns)) { if (Array.isArray(dn.rdns)) {
// Really simple duck-typing for now // Really simple duck-typing for now
return true; return true
} }
return false; return false
}; }
/// --- Exports
///--- Exports
module.exports = { module.exports = {
parse: parse, parse: parse,
DN: DN, DN: DN,
RDN: RDN RDN: RDN
}; }

View File

@ -1,12 +1,10 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved.s // Copyright 2011 Mark Cavage, Inc. All rights reserved.s
/// --- Globals
var SERVER_PROVIDER
///--- Globals var DTRACE_ID = 0
var MAX_INT = 4294967295
var SERVER_PROVIDER;
var DTRACE_ID = 0;
var MAX_INT = 4294967295;
/* /*
* Args: * Args:
@ -37,7 +35,7 @@ var SERVER_PROBES = {
// 4: attribute, 5: value // 4: attribute, 5: value
'server-compare-start': ['int', 'char *', 'char *', 'char *', 'server-compare-start': ['int', 'char *', 'char *', 'char *',
'char *', 'char *'], 'char *', 'char *'],
'server-compare-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'], 'server-compare-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'],
'server-delete-start': ['int', 'char *', 'char *', 'char *'], 'server-delete-start': ['int', 'char *', 'char *', 'char *'],
@ -45,7 +43,7 @@ var SERVER_PROBES = {
// 4: requestName, 5: requestValue // 4: requestName, 5: requestValue
'server-exop-start': ['int', 'char *', 'char *', 'char *', 'char *', 'server-exop-start': ['int', 'char *', 'char *', 'char *', 'char *',
'char *'], 'char *'],
'server-exop-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'], 'server-exop-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'],
// 4: changes.length // 4: changes.length
@ -54,13 +52,13 @@ var SERVER_PROBES = {
// 4: newRdn, 5: newSuperior // 4: newRdn, 5: newSuperior
'server-modifydn-start': ['int', 'char *', 'char *', 'char *', 'char *', 'server-modifydn-start': ['int', 'char *', 'char *', 'char *', 'char *',
'char *'], 'char *'],
'server-modifydn-done': ['int', 'char *', 'char *', 'char *', 'int', 'server-modifydn-done': ['int', 'char *', 'char *', 'char *', 'int',
'char *'], 'char *'],
// 4: scope, 5: filter // 4: scope, 5: filter
'server-search-start': ['int', 'char *', 'char *', 'char *', 'char *', 'server-search-start': ['int', 'char *', 'char *', 'char *', 'char *',
'char *'], 'char *'],
'server-search-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'], 'server-search-done': ['int', 'char *', 'char *', 'char *', 'int', 'char *'],
// Last two are searchEntry.DN and seachEntry.attributes.length // Last two are searchEntry.DN and seachEntry.attributes.length
'server-search-entry': ['int', 'char *', 'char *', 'char *', 'char *', 'int'], 'server-search-entry': ['int', 'char *', 'char *', 'char *', 'char *', 'int'],
@ -73,52 +71,50 @@ var SERVER_PROBES = {
// remote IP // remote IP
'server-connection': ['char *'] 'server-connection': ['char *']
}; }
/// --- API
///--- API module.exports = (function () {
module.exports = function () {
if (!SERVER_PROVIDER) { if (!SERVER_PROVIDER) {
try { try {
var dtrace = require('dtrace-provider'); var dtrace = require('dtrace-provider')
SERVER_PROVIDER = dtrace.createDTraceProvider('ldapjs'); SERVER_PROVIDER = dtrace.createDTraceProvider('ldapjs')
Object.keys(SERVER_PROBES).forEach(function (p) { Object.keys(SERVER_PROBES).forEach(function (p) {
var args = SERVER_PROBES[p].splice(0); var args = SERVER_PROBES[p].splice(0)
args.unshift(p); args.unshift(p)
dtrace.DTraceProvider.prototype.addProbe.apply(SERVER_PROVIDER, args); dtrace.DTraceProvider.prototype.addProbe.apply(SERVER_PROVIDER, args)
}); })
} catch (e) { } catch (e) {
SERVER_PROVIDER = { SERVER_PROVIDER = {
fire: function () { fire: function () {
}, },
enable: function () { enable: function () {
}, },
addProbe: function () { addProbe: function () {
var p = { var p = {
fire: function () { fire: function () {
} }
};
return (p);
},
removeProbe: function () {
},
disable: function () {
} }
}; return (p)
},
removeProbe: function () {
},
disable: function () {
}
}
} }
SERVER_PROVIDER.enable(); SERVER_PROVIDER.enable()
SERVER_PROVIDER._nextId = function () { SERVER_PROVIDER._nextId = function () {
if (DTRACE_ID === MAX_INT) if (DTRACE_ID === MAX_INT) { DTRACE_ID = 0 }
DTRACE_ID = 0;
return ++DTRACE_ID; return ++DTRACE_ID
}; }
} }
return SERVER_PROVIDER; return SERVER_PROVIDER
}(); }())

View File

@ -1,4 +1,4 @@
// Copyright 2014 Joyent, Inc. All rights reserved. 'use strict'
module.exports = { module.exports = {
LDAP_SUCCESS: 0, LDAP_SUCCESS: 0,
@ -41,4 +41,4 @@ module.exports = {
LDAP_AFFECTS_MULTIPLE_DSAS: 71, LDAP_AFFECTS_MULTIPLE_DSAS: 71,
LDAP_OTHER: 80, LDAP_OTHER: 80,
LDAP_PROXIED_AUTHORIZATION_DENIED: 123 LDAP_PROXIED_AUTHORIZATION_DENIED: 123
}; }

View File

@ -1,151 +1,144 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. 'use strict'
var util = require('util'); var util = require('util')
var assert = require('assert-plus'); 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'); /// --- Error Base class
var ERRORS = [];
function LDAPError (message, dn, caller) {
if (Error.captureStackTrace) { Error.captureStackTrace(this, caller || LDAPError) }
///--- Error Base class this.lde_message = message
this.lde_dn = dn
function LDAPError(message, dn, caller) {
if (Error.captureStackTrace)
Error.captureStackTrace(this, caller || LDAPError);
this.lde_message = message;
this.lde_dn = dn;
} }
util.inherits(LDAPError, Error); util.inherits(LDAPError, Error)
Object.defineProperties(LDAPError.prototype, { Object.defineProperties(LDAPError.prototype, {
name: { name: {
get: function getName() { return 'LDAPError'; }, get: function getName () { return 'LDAPError' },
configurable: false configurable: false
}, },
code: { code: {
get: function getCode() { return CODES.LDAP_OTHER; }, get: function getCode () { return CODES.LDAP_OTHER },
configurable: false configurable: false
}, },
message: { message: {
get: function getMessage() { get: function getMessage () {
return this.lde_message || this.name; return this.lde_message || this.name
}, },
configurable: false configurable: false
}, },
dn: { dn: {
get: function getDN() { get: function getDN () {
return (this.lde_dn ? this.lde_dn.toString() : ''); return (this.lde_dn ? this.lde_dn.toString() : '')
}, },
configurable: false 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 // Some whacky games here to make sure all the codes are exported
Object.keys(CODES).forEach(function (code) { Object.keys(CODES).forEach(function (code) {
module.exports[code] = CODES[code]; module.exports[code] = CODES[code]
if (code === 'LDAP_SUCCESS') if (code === 'LDAP_SUCCESS') { return }
return;
var err = ''; var err = ''
var msg = ''; var msg = ''
var pieces = code.split('_').slice(1); var pieces = code.split('_').slice(1)
for (var i = 0; i < pieces.length; i++) { for (var i = 0; i < pieces.length; i++) {
var lc = pieces[i].toLowerCase(); var lc = pieces[i].toLowerCase()
var key = lc.charAt(0).toUpperCase() + lc.slice(1); var key = lc.charAt(0).toUpperCase() + lc.slice(1)
err += key; err += key
msg += key + ((i + 1) < pieces.length ? ' ' : ''); msg += key + ((i + 1) < pieces.length ? ' ' : '')
} }
if (!/\w+Error$/.test(err)) if (!/\w+Error$/.test(err)) { err += 'Error' }
err += 'Error';
// At this point LDAP_OPERATIONS_ERROR is now OperationsError in $err // At this point LDAP_OPERATIONS_ERROR is now OperationsError in $err
// and 'Operations Error' in $msg // and 'Operations Error' in $msg
module.exports[err] = function (message, dn, caller) { module.exports[err] = function (message, dn, caller) {
LDAPError.call(this, message, dn, caller || module.exports[err]); LDAPError.call(this, message, dn, caller || module.exports[err])
}; }
module.exports[err].constructor = module.exports[err]; module.exports[err].constructor = module.exports[err]
util.inherits(module.exports[err], LDAPError); util.inherits(module.exports[err], LDAPError)
Object.defineProperties(module.exports[err].prototype, { Object.defineProperties(module.exports[err].prototype, {
name: { name: {
get: function getName() { return err; }, get: function getName () { return err },
configurable: false configurable: false
}, },
code: { code: {
get: function getCode() { return CODES[code]; }, get: function getCode () { return CODES[code] },
configurable: false configurable: false
} }
}); })
ERRORS[CODES[code]] = { ERRORS[CODES[code]] = {
err: err, err: err,
message: msg message: msg
}; }
}); })
module.exports.getError = function (res) { 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 errObj = ERRORS[res.status]
var E = module.exports[errObj.err]; var E = module.exports[errObj.err]
return new E(res.errorMessage || errObj.message, return new E(res.errorMessage || errObj.message,
res.matchedDN || null, res.matchedDN || null,
module.exports.getError); module.exports.getError)
}; }
module.exports.getMessage = function (code) { module.exports.getMessage = function (code) {
assert.number(code, 'code (number) required'); assert.number(code, 'code (number) required')
var errObj = ERRORS[code]; var errObj = ERRORS[code]
return (errObj && errObj.message ? errObj.message : ''); return (errObj && errObj.message ? errObj.message : '')
};
///--- Custom application errors
function ConnectionError(message) {
LDAPError.call(this, message, null, ConnectionError);
} }
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, { Object.defineProperties(ConnectionError.prototype, {
name: { name: {
get: function () { return 'ConnectionError'; }, get: function () { return 'ConnectionError' },
configurable: false configurable: false
} }
}); })
function AbandonedError(message) { function AbandonedError (message) {
LDAPError.call(this, message, null, AbandonedError); LDAPError.call(this, message, null, AbandonedError)
} }
util.inherits(AbandonedError, LDAPError); util.inherits(AbandonedError, LDAPError)
module.exports.AbandonedError = AbandonedError; module.exports.AbandonedError = AbandonedError
Object.defineProperties(AbandonedError.prototype, { Object.defineProperties(AbandonedError.prototype, {
name: { name: {
get: function () { return 'AbandonedError'; }, get: function () { return 'AbandonedError' },
configurable: false configurable: false
} }
}); })
function TimeoutError(message) { function TimeoutError (message) {
LDAPError.call(this, message, null, TimeoutError); LDAPError.call(this, message, null, TimeoutError)
} }
util.inherits(TimeoutError, LDAPError); util.inherits(TimeoutError, LDAPError)
module.exports.TimeoutError = TimeoutError; module.exports.TimeoutError = TimeoutError
Object.defineProperties(TimeoutError.prototype, { Object.defineProperties(TimeoutError.prototype, {
name: { name: {
get: function () { return 'TimeoutError'; }, get: function () { return 'TimeoutError' },
configurable: false configurable: false
} }
}); })

View File

@ -1,30 +1,27 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); var util = require('util')
var parents = require('ldap-filter'); var parents = require('ldap-filter')
var Filter = require('./filter'); var Filter = require('./filter')
/// --- API
function AndFilter (options) {
///--- API parents.AndFilter.call(this, options)
function AndFilter(options) {
parents.AndFilter.call(this, options);
} }
util.inherits(AndFilter, parents.AndFilter); util.inherits(AndFilter, parents.AndFilter)
Filter.mixin(AndFilter); Filter.mixin(AndFilter)
module.exports = AndFilter; module.exports = AndFilter
AndFilter.prototype._toBer = function (ber) { AndFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
this.filters.forEach(function (f) { this.filters.forEach(function (f) {
ber = f.toBer(ber); ber = f.toBer(ber)
}); })
return ber; return ber
}; }

View File

@ -1,39 +1,35 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); var util = require('util')
var parents = require('ldap-filter'); var parents = require('ldap-filter')
var Filter = require('./filter'); var Filter = require('./filter')
/// --- API
function ApproximateFilter (options) {
///--- API parents.ApproximateFilter.call(this, options)
function ApproximateFilter(options) {
parents.ApproximateFilter.call(this, options);
} }
util.inherits(ApproximateFilter, parents.ApproximateFilter); util.inherits(ApproximateFilter, parents.ApproximateFilter)
Filter.mixin(ApproximateFilter); Filter.mixin(ApproximateFilter)
module.exports = ApproximateFilter; module.exports = ApproximateFilter
ApproximateFilter.prototype.parse = function (ber) { ApproximateFilter.prototype.parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.attribute = ber.readString().toLowerCase(); this.attribute = ber.readString().toLowerCase()
this.value = ber.readString(); this.value = ber.readString()
return true;
};
return true
}
ApproximateFilter.prototype._toBer = function (ber) { ApproximateFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.attribute); ber.writeString(this.attribute)
ber.writeString(this.value); ber.writeString(this.value)
return ber; return ber
}; }

View File

@ -1,66 +1,60 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var ASN1 = require('asn1').Ber; var ASN1 = require('asn1').Ber
var parents = require('ldap-filter'); var parents = require('ldap-filter')
var Filter = require('./filter'); var Filter = require('./filter')
/// --- API
function EqualityFilter (options) {
///--- API parents.EqualityFilter.call(this, options)
function EqualityFilter(options) {
parents.EqualityFilter.call(this, options);
} }
util.inherits(EqualityFilter, parents.EqualityFilter); util.inherits(EqualityFilter, parents.EqualityFilter)
Filter.mixin(EqualityFilter); Filter.mixin(EqualityFilter)
module.exports = EqualityFilter; module.exports = EqualityFilter
EqualityFilter.prototype.matches = function (target, strictAttrCase) { EqualityFilter.prototype.matches = function (target, strictAttrCase) {
assert.object(target, 'target'); assert.object(target, 'target')
var tv = parents.getAttrValue(target, this.attribute, strictAttrCase); var tv = parents.getAttrValue(target, this.attribute, strictAttrCase)
var value = this.value; var value = this.value
if (this.attribute.toLowerCase() === 'objectclass') { if (this.attribute.toLowerCase() === 'objectclass') {
/* /*
* Perform case-insensitive match for objectClass since nearly every LDAP * Perform case-insensitive match for objectClass since nearly every LDAP
* implementation behaves in this manner. * implementation behaves in this manner.
*/ */
value = value.toLowerCase(); value = value.toLowerCase()
return parents.testValues(function (v) { return parents.testValues(function (v) {
return value === v.toLowerCase(); return value === v.toLowerCase()
}, tv); }, tv)
} else { } else {
return parents.testValues(function (v) { return parents.testValues(function (v) {
return value === v; return value === v
}, tv); }, tv)
} }
}; }
EqualityFilter.prototype.parse = function (ber) { EqualityFilter.prototype.parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.attribute = ber.readString().toLowerCase(); this.attribute = ber.readString().toLowerCase()
this.value = ber.readString(ASN1.OctetString, true); this.value = ber.readString(ASN1.OctetString, true)
if (this.attribute === 'objectclass') if (this.attribute === 'objectclass') { this.value = this.value.toLowerCase() }
this.value = this.value.toLowerCase();
return true;
};
return true
}
EqualityFilter.prototype._toBer = function (ber) { EqualityFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.attribute); ber.writeString(this.attribute)
ber.writeBuffer(this.raw, ASN1.OctetString); ber.writeBuffer(this.raw, ASN1.OctetString)
return ber; return ber
}; }

View File

@ -14,32 +14,31 @@
*/ */
exports.escape = function (inp) { exports.escape = function (inp) {
if (typeof (inp) === 'string') { if (typeof (inp) === 'string') {
var esc = ''; var esc = ''
for (var i = 0; i < inp.length; i++) { for (var i = 0; i < inp.length; i++) {
switch (inp[i]) { switch (inp[i]) {
case '*': case '*':
esc += '\\2a'; esc += '\\2a'
break; break
case '(': case '(':
esc += '\\28'; esc += '\\28'
break; break
case ')': case ')':
esc += '\\29'; esc += '\\29'
break; break
case '\\': case '\\':
esc += '\\5c'; esc += '\\5c'
break; break
case '\0': case '\0':
esc += '\\00'; esc += '\\00'
break; break
default: default:
esc += inp[i]; esc += inp[i]
break; break
} }
} }
return esc; return esc
} else { } else {
return inp; return inp
} }
}; }

View File

@ -1,66 +1,59 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); var util = require('util')
var parents = require('ldap-filter');
var Filter = require('./filter');
var parents = require('ldap-filter')
var Filter = require('./filter')
// THIS IS A STUB! // THIS IS A STUB!
// //
// ldapjs does not support server side extensible matching. // ldapjs does not support server side extensible matching.
// This class exists only for the client to send them. // This class exists only for the client to send them.
///--- API /// --- API
function ExtensibleFilter(options) { function ExtensibleFilter (options) {
parents.ExtensibleFilter.call(this, options); parents.ExtensibleFilter.call(this, options)
} }
util.inherits(ExtensibleFilter, parents.ExtensibleFilter); util.inherits(ExtensibleFilter, parents.ExtensibleFilter)
Filter.mixin(ExtensibleFilter); Filter.mixin(ExtensibleFilter)
module.exports = ExtensibleFilter; module.exports = ExtensibleFilter
ExtensibleFilter.prototype.parse = function (ber) { ExtensibleFilter.prototype.parse = function (ber) {
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) { while (ber.offset < end) {
var tag = ber.peek(); var tag = ber.peek()
switch (tag) { switch (tag) {
case 0x81: case 0x81:
this.rule = ber.readString(tag); this.rule = ber.readString(tag)
break; break
case 0x82: case 0x82:
this.matchType = ber.readString(tag); this.matchType = ber.readString(tag)
break; break
case 0x83: case 0x83:
this.value = ber.readString(tag); this.value = ber.readString(tag)
break; break
case 0x84: case 0x84:
this.dnAttributes = ber.readBoolean(tag); this.dnAttributes = ber.readBoolean(tag)
break; break
default: default:
throw new Error('Invalid ext_match filter type: 0x' + tag.toString(16)); throw new Error('Invalid ext_match filter type: 0x' + tag.toString(16))
} }
} }
return true; return true
}; }
ExtensibleFilter.prototype._toBer = function (ber) { ExtensibleFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
if (this.rule) if (this.rule) { ber.writeString(this.rule, 0x81) }
ber.writeString(this.rule, 0x81); if (this.matchType) { ber.writeString(this.matchType, 0x82) }
if (this.matchType)
ber.writeString(this.matchType, 0x82);
ber.writeString(this.value, 0x83); ber.writeString(this.value, 0x83)
if (this.dnAttributes) if (this.dnAttributes) { ber.writeBoolean(this.dnAttributes, 0x84) }
ber.writeBoolean(this.dnAttributes, 0x84);
return ber; return ber
}; }

View File

@ -1,58 +1,55 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // 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 = { var TYPES = {
'and': Protocol.FILTER_AND, and: Protocol.FILTER_AND,
'or': Protocol.FILTER_OR, or: Protocol.FILTER_OR,
'not': Protocol.FILTER_NOT, not: Protocol.FILTER_NOT,
'equal': Protocol.FILTER_EQUALITY, equal: Protocol.FILTER_EQUALITY,
'substring': Protocol.FILTER_SUBSTRINGS, substring: Protocol.FILTER_SUBSTRINGS,
'ge': Protocol.FILTER_GE, ge: Protocol.FILTER_GE,
'le': Protocol.FILTER_LE, le: Protocol.FILTER_LE,
'present': Protocol.FILTER_PRESENT, present: Protocol.FILTER_PRESENT,
'approx': Protocol.FILTER_APPROX, approx: Protocol.FILTER_APPROX,
'ext': Protocol.FILTER_EXT ext: Protocol.FILTER_EXT
}; }
/// --- API
///--- API function isFilter (filter) {
function isFilter(filter) {
if (!filter || typeof (filter) !== 'object') { if (!filter || typeof (filter) !== 'object') {
return false; return false
} }
// Do our best to duck-type it // Do our best to duck-type it
if (typeof (filter.toBer) === 'function' && if (typeof (filter.toBer) === 'function' &&
typeof (filter.matches) === 'function' && typeof (filter.matches) === 'function' &&
TYPES[filter.type] !== undefined) { TYPES[filter.type] !== undefined) {
return true; return true
} }
return false; return false
} }
function mixin(target) { function mixin (target) {
target.prototype.toBer = function toBer(ber) { target.prototype.toBer = function toBer (ber) {
if (!ber || !(ber instanceof BerWriter)) if (!ber || !(ber instanceof BerWriter)) { throw new TypeError('ber (BerWriter) required') }
throw new TypeError('ber (BerWriter) required');
ber.startSequence(TYPES[this.type]); ber.startSequence(TYPES[this.type])
ber = this._toBer(ber); ber = this._toBer(ber)
ber.endSequence(); ber.endSequence()
return ber; return ber
}; }
} }
module.exports = { module.exports = {
isFilter: isFilter, isFilter: isFilter,
mixin: mixin mixin: mixin
}; }

View File

@ -1,38 +1,35 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); 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); util.inherits(GreaterThanEqualsFilter, parents.GreaterThanEqualsFilter)
Filter.mixin(GreaterThanEqualsFilter); Filter.mixin(GreaterThanEqualsFilter)
module.exports = GreaterThanEqualsFilter; module.exports = GreaterThanEqualsFilter
GreaterThanEqualsFilter.prototype.parse = function (ber) { GreaterThanEqualsFilter.prototype.parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.attribute = ber.readString().toLowerCase(); this.attribute = ber.readString().toLowerCase()
this.value = ber.readString(); this.value = ber.readString()
return true;
};
return true
}
GreaterThanEqualsFilter.prototype._toBer = function (ber) { GreaterThanEqualsFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.attribute); ber.writeString(this.attribute)
ber.writeString(this.value); ber.writeString(this.value)
return ber; return ber
}; }

View File

@ -1,33 +1,30 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // 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 Filter = require('./filter')
var AndFilter = require('./and_filter'); var AndFilter = require('./and_filter')
var ApproximateFilter = require('./approx_filter'); var ApproximateFilter = require('./approx_filter')
var EqualityFilter = require('./equality_filter'); var EqualityFilter = require('./equality_filter')
var ExtensibleFilter = require('./ext_filter'); var ExtensibleFilter = require('./ext_filter')
var GreaterThanEqualsFilter = require('./ge_filter'); var GreaterThanEqualsFilter = require('./ge_filter')
var LessThanEqualsFilter = require('./le_filter'); var LessThanEqualsFilter = require('./le_filter')
var NotFilter = require('./not_filter'); var NotFilter = require('./not_filter')
var OrFilter = require('./or_filter'); var OrFilter = require('./or_filter')
var PresenceFilter = require('./presence_filter'); var PresenceFilter = require('./presence_filter')
var SubstringFilter = require('./substr_filter'); var SubstringFilter = require('./substr_filter')
/// --- Globals
var BerReader = asn1.BerReader
///--- Globals /// --- Internal Parsers
var BerReader = asn1.BerReader;
///--- Internal Parsers
/* /*
* A filter looks like this coming in: * A filter looks like this coming in:
@ -62,144 +59,138 @@ var BerReader = asn1.BerReader;
* dnAttributes [4] BOOLEAN DEFAULT FALSE * dnAttributes [4] BOOLEAN DEFAULT FALSE
* } * }
*/ */
function _parse(ber) { function _parse (ber) {
assert.ok(ber); assert.ok(ber)
function parseSet(f) { function parseSet (f) {
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) while (ber.offset < end) { f.addFilter(_parse(ber)) }
f.addFilter(_parse(ber));
} }
var f; var f
var type = ber.readSequence(); var type = ber.readSequence()
switch (type) { switch (type) {
case Protocol.FILTER_AND:
f = new AndFilter()
parseSet(f)
break
case Protocol.FILTER_AND: case Protocol.FILTER_APPROX:
f = new AndFilter(); f = new ApproximateFilter()
parseSet(f); f.parse(ber)
break; break
case Protocol.FILTER_APPROX: case Protocol.FILTER_EQUALITY:
f = new ApproximateFilter(); f = new EqualityFilter()
f.parse(ber); f.parse(ber)
break; return f
case Protocol.FILTER_EQUALITY: case Protocol.FILTER_EXT:
f = new EqualityFilter(); f = new ExtensibleFilter()
f.parse(ber); f.parse(ber)
return f; return f
case Protocol.FILTER_EXT: case Protocol.FILTER_GE:
f = new ExtensibleFilter(); f = new GreaterThanEqualsFilter()
f.parse(ber); f.parse(ber)
return f; return f
case Protocol.FILTER_GE: case Protocol.FILTER_LE:
f = new GreaterThanEqualsFilter(); f = new LessThanEqualsFilter()
f.parse(ber); f.parse(ber)
return f; return f
case Protocol.FILTER_LE: case Protocol.FILTER_NOT:
f = new LessThanEqualsFilter(); var _f = _parse(ber)
f.parse(ber); f = new NotFilter({
return f; filter: _f
})
break
case Protocol.FILTER_NOT: case Protocol.FILTER_OR:
var _f = _parse(ber); f = new OrFilter()
f = new NotFilter({ parseSet(f)
filter: _f break
});
break;
case Protocol.FILTER_OR: case Protocol.FILTER_PRESENT:
f = new OrFilter(); f = new PresenceFilter()
parseSet(f); f.parse(ber)
break; break
case Protocol.FILTER_PRESENT: case Protocol.FILTER_SUBSTRINGS:
f = new PresenceFilter(); f = new SubstringFilter()
f.parse(ber); f.parse(ber)
break; break
case Protocol.FILTER_SUBSTRINGS: default:
f = new SubstringFilter(); throw new Error('Invalid search filter type: 0x' + type.toString(16))
f.parse(ber);
break;
default:
throw new Error('Invalid search filter type: 0x' + type.toString(16));
} }
assert.ok(f)
assert.ok(f); return f
return f;
} }
function cloneFilter (input) {
function cloneFilter(input) { var child
var child;
if (input.type === 'and' || input.type === 'or') { if (input.type === 'and' || input.type === 'or') {
child = input.filters.map(cloneFilter); child = input.filters.map(cloneFilter)
} else if (input.type === 'not') { } else if (input.type === 'not') {
child = cloneFilter(input.filter); child = cloneFilter(input.filter)
} }
switch (input.type) { switch (input.type) {
case 'and': case 'and':
return new AndFilter({filters: child}); return new AndFilter({ filters: child })
case 'or': case 'or':
return new OrFilter({filters: child}); return new OrFilter({ filters: child })
case 'not': case 'not':
return new NotFilter({filter: child}); return new NotFilter({ filter: child })
case 'equal': case 'equal':
return new EqualityFilter(input); return new EqualityFilter(input)
case 'substring': case 'substring':
return new SubstringFilter(input); return new SubstringFilter(input)
case 'ge': case 'ge':
return new GreaterThanEqualsFilter(input); return new GreaterThanEqualsFilter(input)
case 'le': case 'le':
return new LessThanEqualsFilter(input); return new LessThanEqualsFilter(input)
case 'present': case 'present':
return new PresenceFilter(input); return new PresenceFilter(input)
case 'approx': case 'approx':
return new ApproximateFilter(input); return new ApproximateFilter(input)
case 'ext': case 'ext':
return new ExtensibleFilter(input); return new ExtensibleFilter(input)
default: default:
throw new Error('invalid filter type:' + input.type); 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) { return str.replace(/\\([0-9a-f][^0-9a-f]|[0-9a-f]$|[^0-9a-f]|$)/gi, function (match, p1) {
if (!p1) { if (!p1) {
return '\\5c'; return '\\5c'
} }
const hexCode = p1.charCodeAt(0).toString(16); const hexCode = p1.charCodeAt(0).toString(16)
const rest = p1.substring(1); const rest = p1.substring(1)
return '\\' + hexCode + rest; return '\\' + hexCode + rest
}); })
} }
function parseString(str) { function parseString (str) {
const hexStr = escapedToHex(str); const hexStr = escapedToHex(str)
const generic = parents.parse(hexStr); const generic = parents.parse(hexStr)
// The filter object(s) return from ldap-filter.parse lack the toBer/parse // The filter object(s) return from ldap-filter.parse lack the toBer/parse
// decoration that native ldapjs filter possess. cloneFilter adds that back. // decoration that native ldapjs filter possess. cloneFilter adds that back.
return cloneFilter(generic); return cloneFilter(generic)
} }
/// --- API
///--- API
module.exports = { module.exports = {
parse: function (ber) { parse: function (ber) {
if (!ber || !(ber instanceof BerReader)) if (!ber || !(ber instanceof BerReader)) { throw new TypeError('ber (BerReader) required') }
throw new TypeError('ber (BerReader) required');
return _parse(ber); return _parse(ber)
}, },
parseString: parseString, parseString: parseString,
@ -216,4 +207,4 @@ module.exports = {
OrFilter: OrFilter, OrFilter: OrFilter,
PresenceFilter: PresenceFilter, PresenceFilter: PresenceFilter,
SubstringFilter: SubstringFilter SubstringFilter: SubstringFilter
}; }

View File

@ -1,38 +1,35 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); 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); util.inherits(LessThanEqualsFilter, parents.LessThanEqualsFilter)
Filter.mixin(LessThanEqualsFilter); Filter.mixin(LessThanEqualsFilter)
module.exports = LessThanEqualsFilter; module.exports = LessThanEqualsFilter
LessThanEqualsFilter.prototype.parse = function (ber) { LessThanEqualsFilter.prototype.parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.attribute = ber.readString().toLowerCase(); this.attribute = ber.readString().toLowerCase()
this.value = ber.readString(); this.value = ber.readString()
return true;
};
return true
}
LessThanEqualsFilter.prototype._toBer = function (ber) { LessThanEqualsFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.attribute); ber.writeString(this.attribute)
ber.writeString(this.value); ber.writeString(this.value)
return ber; return ber
}; }

View File

@ -1,25 +1,23 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); 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); util.inherits(NotFilter, parents.NotFilter)
Filter.mixin(NotFilter); Filter.mixin(NotFilter)
module.exports = NotFilter; module.exports = NotFilter
NotFilter.prototype._toBer = function (ber) { NotFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
return this.filter.toBer(ber); return this.filter.toBer(ber)
}; }

View File

@ -1,29 +1,27 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); 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); util.inherits(OrFilter, parents.OrFilter)
Filter.mixin(OrFilter); Filter.mixin(OrFilter)
module.exports = OrFilter; module.exports = OrFilter
OrFilter.prototype._toBer = function (ber) { OrFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
this.filters.forEach(function (f) { this.filters.forEach(function (f) {
ber = f.toBer(ber); ber = f.toBer(ber)
}); })
return ber; return ber
}; }

View File

@ -1,40 +1,36 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); 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); util.inherits(PresenceFilter, parents.PresenceFilter)
Filter.mixin(PresenceFilter); Filter.mixin(PresenceFilter)
module.exports = PresenceFilter; module.exports = PresenceFilter
PresenceFilter.prototype.parse = function (ber) { PresenceFilter.prototype.parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.attribute = this.attribute =
ber.buffer.slice(0, ber.length).toString('utf8').toLowerCase(); ber.buffer.slice(0, ber.length).toString('utf8').toLowerCase()
ber._offset += ber.length; ber._offset += ber.length
return true;
};
return true
}
PresenceFilter.prototype._toBer = function (ber) { PresenceFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
for (var i = 0; i < this.attribute.length; i++) for (var i = 0; i < this.attribute.length; i++) { ber.writeByte(this.attribute.charCodeAt(i)) }
ber.writeByte(this.attribute.charCodeAt(i));
return ber; return ber
}; }

View File

@ -1,76 +1,69 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert'); var assert = require('assert')
var util = require('util'); 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); util.inherits(SubstringFilter, parents.SubstringFilter)
Filter.mixin(SubstringFilter); Filter.mixin(SubstringFilter)
module.exports = SubstringFilter; module.exports = SubstringFilter
SubstringFilter.prototype.parse = function (ber) { SubstringFilter.prototype.parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.attribute = ber.readString().toLowerCase(); this.attribute = ber.readString().toLowerCase()
ber.readSequence(); ber.readSequence()
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) { while (ber.offset < end) {
var tag = ber.peek(); var tag = ber.peek()
switch (tag) { switch (tag) {
case 0x80: // Initial case 0x80: // Initial
this.initial = ber.readString(tag); this.initial = ber.readString(tag)
if (this.attribute === 'objectclass') if (this.attribute === 'objectclass') { this.initial = this.initial.toLowerCase() }
this.initial = this.initial.toLowerCase(); break
break; case 0x81: // Any
case 0x81: // Any var anyVal = ber.readString(tag)
var anyVal = ber.readString(tag); if (this.attribute === 'objectclass') { anyVal = anyVal.toLowerCase() }
if (this.attribute === 'objectclass') this.any.push(anyVal)
anyVal = anyVal.toLowerCase(); break
this.any.push(anyVal); case 0x82: // Final
break; this.final = ber.readString(tag)
case 0x82: // Final if (this.attribute === 'objectclass') { this.final = this.final.toLowerCase() }
this.final = ber.readString(tag); break
if (this.attribute === 'objectclass') default:
this.final = this.final.toLowerCase(); throw new Error('Invalid substrings filter type: 0x' + tag.toString(16))
break;
default:
throw new Error('Invalid substrings filter type: 0x' + tag.toString(16));
} }
} }
return true; return true
}; }
SubstringFilter.prototype._toBer = function (ber) { SubstringFilter.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.attribute); ber.writeString(this.attribute)
ber.startSequence(); ber.startSequence()
if (this.initial) if (this.initial) { ber.writeString(this.initial, 0x80) }
ber.writeString(this.initial, 0x80);
if (this.any && this.any.length) if (this.any && this.any.length) {
this.any.forEach(function (s) { this.any.forEach(function (s) {
ber.writeString(s, 0x81); ber.writeString(s, 0x81)
}); })
}
if (this.final) if (this.final) { ber.writeString(this.final, 0x82) }
ber.writeString(this.final, 0x82);
ber.endSequence(); ber.endSequence()
return ber; return ber
}; }

View File

@ -1,23 +1,24 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var logger = require('./logger'); var logger = require('./logger')
var client = require('./client'); var client = require('./client')
var Attribute = require('./attribute'); var Attribute = require('./attribute')
var Change = require('./change'); var Change = require('./change')
var Protocol = require('./protocol'); var Protocol = require('./protocol')
var Server = require('./server'); var Server = require('./server')
var controls = require('./controls'); var controls = require('./controls')
var persistentSearch = require('./persistent_search'); var persistentSearch = require('./persistent_search')
var dn = require('./dn'); var dn = require('./dn')
var errors = require('./errors'); var errors = require('./errors')
var filters = require('./filters'); var filters = require('./filters')
var messages = require('./messages'); var messages = require('./messages')
var url = require('./url'); var url = require('./url')
const hasOwnProperty = (target, val) => Object.prototype.hasOwnProperty.call(target, val)
///--- API /// --- API
module.exports = { module.exports = {
Client: client.Client, Client: client.Client,
@ -25,17 +26,15 @@ module.exports = {
Server: Server, Server: Server,
createServer: function (options) { createServer: function (options) {
if (options === undefined) if (options === undefined) { options = {} }
options = {};
if (typeof (options) !== 'object') if (typeof (options) !== 'object') { throw new TypeError('options (object) required') }
throw new TypeError('options (object) required');
if (!options.log) { if (!options.log) {
options.log = logger; options.log = logger
} }
return new Server(options); return new Server(options)
}, },
Attribute: Attribute, Attribute: Attribute,
@ -54,37 +53,32 @@ module.exports = {
url: url, url: url,
parseURL: url.parse parseURL: url.parse
}; }
/// --- Export all the childrenz
///--- Export all the childrenz var k
var k;
for (k in Protocol) { for (k in Protocol) {
if (Protocol.hasOwnProperty(k)) if (hasOwnProperty(Protocol, k)) { module.exports[k] = Protocol[k] }
module.exports[k] = Protocol[k];
} }
for (k in messages) { for (k in messages) {
if (messages.hasOwnProperty(k)) if (hasOwnProperty(messages, k)) { module.exports[k] = messages[k] }
module.exports[k] = messages[k];
} }
for (k in controls) { for (k in controls) {
if (controls.hasOwnProperty(k)) if (hasOwnProperty(controls, k)) { module.exports[k] = controls[k] }
module.exports[k] = controls[k];
} }
for (k in filters) { for (k in filters) {
if (filters.hasOwnProperty(k)) { if (hasOwnProperty(filters, k)) {
if (k !== 'parse' && k !== 'parseString') if (k !== 'parse' && k !== 'parseString') { module.exports[k] = filters[k] }
module.exports[k] = filters[k];
} }
} }
for (k in errors) { for (k in errors) {
if (errors.hasOwnProperty(k)) { if (hasOwnProperty(errors, k)) {
module.exports[k] = errors[k]; module.exports[k] = errors[k]
} }
} }

View File

@ -1,4 +1,4 @@
'use strict'; 'use strict'
const logger = Object.create(require('abstract-logging')) const logger = Object.create(require('abstract-logging'))
logger.child = function () { return logger } logger.child = function () { return logger }

View File

@ -1,90 +1,87 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function AbandonRequest (options) {
options = options || {}
assert.object(options)
assert.optionalNumber(options.abandonID)
function AbandonRequest(options) { options.protocolOp = Protocol.LDAP_REQ_ABANDON
options = options || {}; LDAPMessage.call(this, options)
assert.object(options);
assert.optionalNumber(options.abandonID);
options.protocolOp = Protocol.LDAP_REQ_ABANDON; this.abandonID = options.abandonID || 0
LDAPMessage.call(this, options);
this.abandonID = options.abandonID || 0;
} }
util.inherits(AbandonRequest, LDAPMessage); util.inherits(AbandonRequest, LDAPMessage)
Object.defineProperties(AbandonRequest.prototype, { Object.defineProperties(AbandonRequest.prototype, {
type: { type: {
get: function getType() { return 'AbandonRequest'; }, get: function getType () { return 'AbandonRequest' },
configurable: false configurable: false
} }
}); })
AbandonRequest.prototype._parse = function (ber, length) { AbandonRequest.prototype._parse = function (ber, length) {
assert.ok(ber); assert.ok(ber)
assert.ok(length); assert.ok(length)
// What a PITA - have to replicate ASN.1 integer logic to work around the // 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" // way abandon is encoded and the way ldapjs framework handles "normal"
// messages // messages
var buf = ber.buffer; var buf = ber.buffer
var offset = 0; var offset = 0
var value = 0; var value = 0
var fb = buf[offset++]; var fb = buf[offset++]
value = fb & 0x7F; value = fb & 0x7F
for (var i = 1; i < length; i++) { for (var i = 1; i < length; i++) {
value <<= 8; value <<= 8
value |= (buf[offset++] & 0xff); value |= (buf[offset++] & 0xff)
} }
if ((fb & 0x80) == 0x80) if ((fb & 0x80) === 0x80) { value = -value }
value = -value;
ber._offset += length; ber._offset += length
this.abandonID = value; this.abandonID = value
return true; return true
}; }
AbandonRequest.prototype._toBer = function (ber) { AbandonRequest.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
var i = this.abandonID; var i = this.abandonID
var sz = 4; var sz = 4
while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000)) && while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000)) &&
(sz > 1)) { (sz > 1)) {
sz--; sz--
i <<= 8; i <<= 8
} }
assert.ok(sz <= 4); assert.ok(sz <= 4)
while (sz-- > 0) { while (sz-- > 0) {
ber.writeByte((i & 0xff000000) >> 24); ber.writeByte((i & 0xff000000) >> 24)
i <<= 8; i <<= 8
} }
return ber; return ber
}; }
AbandonRequest.prototype._json = function (j) { 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;

View File

@ -1,36 +1,34 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./result'); var LDAPMessage = require('./result')
var Protocol = require('../protocol'); // var Protocol = require('../protocol')
/// --- API
///--- API function AbandonResponse (options) {
options = options || {}
assert.object(options)
function AbandonResponse(options) { options.protocolOp = 0
options = options || {}; LDAPMessage.call(this, options)
assert.object(options);
options.protocolOp = 0;
LDAPMessage.call(this, options);
} }
util.inherits(AbandonResponse, LDAPMessage); util.inherits(AbandonResponse, LDAPMessage)
Object.defineProperties(AbandonResponse.prototype, { Object.defineProperties(AbandonResponse.prototype, {
type: { type: {
get: function getType() { return 'AbandonResponse'; }, get: function getType () { return 'AbandonResponse' },
configurable: false configurable: false
} }
}); })
AbandonResponse.prototype.end = function (status) {}; AbandonResponse.prototype.end = function (status) {}
AbandonResponse.prototype._json = function (j) { AbandonResponse.prototype._json = function (j) {
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = AbandonResponse
module.exports = AbandonResponse;

View File

@ -1,130 +1,122 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Attribute = require('../attribute'); var Attribute = require('../attribute')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
var lassert = require('../assert'); 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.protocolOp = Protocol.LDAP_REQ_ADD
options = options || {}; LDAPMessage.call(this, options)
assert.object(options);
lassert.optionalStringDN(options.entry);
lassert.optionalArrayOfAttribute(options.attributes);
options.protocolOp = Protocol.LDAP_REQ_ADD; this.entry = options.entry || null
LDAPMessage.call(this, options); 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, { Object.defineProperties(AddRequest.prototype, {
type: { type: {
get: function getType() { return 'AddRequest'; }, get: function getType () { return 'AddRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.entry; }, get: function getDN () { return this.entry },
configurable: false configurable: false
} }
}); })
AddRequest.prototype._parse = function (ber) { 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) { while (ber.offset < end) {
var a = new Attribute(); var a = new Attribute()
a.parse(ber); a.parse(ber)
a.type = a.type.toLowerCase(); a.type = a.type.toLowerCase()
if (a.type === 'objectclass') { if (a.type === 'objectclass') {
for (var i = 0; i < a.vals.length; i++) for (var i = 0; i < a.vals.length; i++) { a.vals[i] = a.vals[i].toLowerCase() }
a.vals[i] = a.vals[i].toLowerCase();
} }
this.attributes.push(a); this.attributes.push(a)
} }
this.attributes.sort(Attribute.compare); this.attributes.sort(Attribute.compare)
return true; return true
}; }
AddRequest.prototype._toBer = function (ber) { AddRequest.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.entry.toString()); ber.writeString(this.entry.toString())
ber.startSequence(); ber.startSequence()
this.attributes.forEach(function (a) { this.attributes.forEach(function (a) {
a.toBer(ber); a.toBer(ber)
}); })
ber.endSequence(); ber.endSequence()
return ber; return ber
}; }
AddRequest.prototype._json = function (j) { AddRequest.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.entry = this.entry.toString(); j.entry = this.entry.toString()
j.attributes = []; j.attributes = []
this.attributes.forEach(function (a) { this.attributes.forEach(function (a) {
j.attributes.push(a.json); j.attributes.push(a.json)
}); })
return j; return j
}; }
AddRequest.prototype.indexOf = function (attr) { AddRequest.prototype.indexOf = function (attr) {
if (!attr || typeof (attr) !== 'string') if (!attr || typeof (attr) !== 'string') { throw new TypeError('attr (string) required') }
throw new TypeError('attr (string) required');
for (var i = 0; i < this.attributes.length; i++) { for (var i = 0; i < this.attributes.length; i++) {
if (this.attributes[i].type === attr) if (this.attributes[i].type === attr) { return i }
return i;
} }
return -1; return -1
}; }
AddRequest.prototype.attributeNames = function () { AddRequest.prototype.attributeNames = function () {
var attrs = []; var attrs = []
for (var i = 0; i < this.attributes.length; i++) for (var i = 0; i < this.attributes.length; i++) { attrs.push(this.attributes[i].type.toLowerCase()) }
attrs.push(this.attributes[i].type.toLowerCase());
return attrs; return attrs
}; }
AddRequest.prototype.getAttribute = function (name) { AddRequest.prototype.getAttribute = function (name) {
if (!name || typeof (name) !== 'string') if (!name || typeof (name) !== 'string') { throw new TypeError('attribute name (string) required') }
throw new TypeError('attribute name (string) required');
name = name.toLowerCase(); name = name.toLowerCase()
for (var i = 0; i < this.attributes.length; i++) { for (var i = 0; i < this.attributes.length; i++) {
if (this.attributes[i].type === name) if (this.attributes[i].type === name) { return this.attributes[i] }
return this.attributes[i];
} }
return null; return null
}; }
AddRequest.prototype.addAttribute = function (attr) { AddRequest.prototype.addAttribute = function (attr) {
if (!(attr instanceof Attribute)) if (!(attr instanceof Attribute)) { throw new TypeError('attribute (Attribute) required') }
throw new TypeError('attribute (Attribute) required');
return this.attributes.push(attr); return this.attributes.push(attr)
}; }
/** /**
* Returns a "pure" JS representation of this object. * Returns a "pure" JS representation of this object.
@ -142,30 +134,26 @@ AddRequest.prototype.addAttribute = function (attr) {
* @return {Object} that looks like the above. * @return {Object} that looks like the above.
*/ */
AddRequest.prototype.toObject = function () { AddRequest.prototype.toObject = function () {
var self = this; var self = this
var obj = { var obj = {
dn: self.entry ? self.entry.toString() : '', dn: self.entry ? self.entry.toString() : '',
attributes: {} attributes: {}
}; }
if (!this.attributes || !this.attributes.length) if (!this.attributes || !this.attributes.length) { return obj }
return obj;
this.attributes.forEach(function (a) { this.attributes.forEach(function (a) {
if (!obj.attributes[a.type]) if (!obj.attributes[a.type]) { obj.attributes[a.type] = [] }
obj.attributes[a.type] = [];
a.vals.forEach(function (v) { a.vals.forEach(function (v) {
if (obj.attributes[a.type].indexOf(v) === -1) if (obj.attributes[a.type].indexOf(v) === -1) { obj.attributes[a.type].push(v) }
obj.attributes[a.type].push(v); })
}); })
});
return obj; return obj
}; }
/// --- Exports
///--- Exports module.exports = AddRequest
module.exports = AddRequest;

View File

@ -1,24 +1,22 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function AddResponse (options) {
options = options || {}
assert.object(options)
function AddResponse(options) { options.protocolOp = Protocol.LDAP_REP_ADD
options = options || {}; LDAPResult.call(this, options)
assert.object(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;

View File

@ -1,88 +1,84 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var asn1 = require('asn1'); var asn1 = require('asn1')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- Globals
///--- Globals var Ber = asn1.Ber
var LDAP_BIND_SIMPLE = 'simple'
// var LDAP_BIND_SASL = 'sasl'
var Ber = asn1.Ber; /// --- API
var LDAP_BIND_SIMPLE = 'simple';
var LDAP_BIND_SASL = 'sasl';
function BindRequest (options) {
options = options || {}
assert.object(options)
///--- API options.protocolOp = Protocol.LDAP_REQ_BIND
LDAPMessage.call(this, options)
function BindRequest(options) { this.version = options.version || 0x03
options = options || {}; this.name = options.name || null
assert.object(options); this.authentication = options.authentication || LDAP_BIND_SIMPLE
this.credentials = options.credentials || ''
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 || '';
} }
util.inherits(BindRequest, LDAPMessage); util.inherits(BindRequest, LDAPMessage)
Object.defineProperties(BindRequest.prototype, { Object.defineProperties(BindRequest.prototype, {
type: { type: {
get: function getType() { return 'BindRequest'; }, get: function getType () { return 'BindRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.name; }, get: function getDN () { return this.name },
configurable: false configurable: false
} }
}); })
BindRequest.prototype._parse = function (ber) { BindRequest.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.version = ber.readInt(); this.version = ber.readInt()
this.name = ber.readString(); this.name = ber.readString()
var t = ber.peek(); var t = ber.peek()
// TODO add support for SASL et al // TODO add support for SASL et al
if (t !== Ber.Context) if (t !== Ber.Context) { throw new Error('authentication 0x' + t.toString(16) + ' not supported') }
throw new Error('authentication 0x' + t.toString(16) + ' not supported');
this.authentication = LDAP_BIND_SIMPLE; this.authentication = LDAP_BIND_SIMPLE
this.credentials = ber.readString(Ber.Context); this.credentials = ber.readString(Ber.Context)
return true; return true
}; }
BindRequest.prototype._toBer = function (ber) { BindRequest.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeInt(this.version); ber.writeInt(this.version)
ber.writeString((this.name || '').toString()); ber.writeString((this.name || '').toString())
// TODO add support for SASL et al // 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) { BindRequest.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.version = this.version; j.version = this.version
j.name = this.name; j.name = this.name
j.authenticationType = this.authentication; j.authenticationType = this.authentication
j.credentials = this.credentials; j.credentials = this.credentials
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = BindRequest
module.exports = BindRequest;

View File

@ -1,24 +1,22 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function BindResponse (options) {
options = options || {}
assert.object(options)
function BindResponse(options) { options.protocolOp = Protocol.LDAP_REP_BIND
options = options || {}; LDAPResult.call(this, options)
assert.object(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;

View File

@ -1,76 +1,74 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
var lassert = require('../assert'); 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.protocolOp = Protocol.LDAP_REQ_COMPARE
options = options || {}; LDAPMessage.call(this, options)
assert.object(options);
assert.optionalString(options.attribute);
assert.optionalString(options.value);
lassert.optionalStringDN(options.entry);
options.protocolOp = Protocol.LDAP_REQ_COMPARE; this.entry = options.entry || null
LDAPMessage.call(this, options); 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, { Object.defineProperties(CompareRequest.prototype, {
type: { type: {
get: function getType() { return 'CompareRequest'; }, get: function getType () { return 'CompareRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.entry; }, get: function getDN () { return this.entry },
configurable: false configurable: false
} }
}); })
CompareRequest.prototype._parse = function (ber) { CompareRequest.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.entry = ber.readString(); this.entry = ber.readString()
ber.readSequence(); ber.readSequence()
this.attribute = ber.readString().toLowerCase(); this.attribute = ber.readString().toLowerCase()
this.value = ber.readString(); this.value = ber.readString()
return true; return true
}; }
CompareRequest.prototype._toBer = function (ber) { CompareRequest.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.entry.toString()); ber.writeString(this.entry.toString())
ber.startSequence(); ber.startSequence()
ber.writeString(this.attribute); ber.writeString(this.attribute)
ber.writeString(this.value); ber.writeString(this.value)
ber.endSequence(); ber.endSequence()
return ber; return ber
}; }
CompareRequest.prototype._json = function (j) { CompareRequest.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.entry = this.entry.toString(); j.entry = this.entry.toString()
j.attribute = this.attribute; j.attribute = this.attribute
j.value = this.value; j.value = this.value
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = CompareRequest
module.exports = CompareRequest;

View File

@ -1,36 +1,33 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function CompareResponse (options) {
options = options || {}
assert.object(options)
function CompareResponse(options) { options.protocolOp = Protocol.LDAP_REP_COMPARE
options = options || {}; LDAPResult.call(this, options)
assert.object(options);
options.protocolOp = Protocol.LDAP_REP_COMPARE;
LDAPResult.call(this, options);
} }
util.inherits(CompareResponse, LDAPResult); util.inherits(CompareResponse, LDAPResult)
CompareResponse.prototype.end = function (matches) { CompareResponse.prototype.end = function (matches) {
var status = 0x06; var status = 0x06
if (typeof (matches) === 'boolean') { if (typeof (matches) === 'boolean') {
if (!matches) if (!matches) { status = 0x05 } // Compare false
status = 0x05; // Compare false
} else { } 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;

View File

@ -1,65 +1,62 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
var lassert = require('../assert'); var lassert = require('../assert')
/// --- API
///--- API function DeleteRequest (options) {
options = options || {}
assert.object(options)
lassert.optionalStringDN(options.entry)
function DeleteRequest(options) { options.protocolOp = Protocol.LDAP_REQ_DELETE
options = options || {}; LDAPMessage.call(this, options)
assert.object(options);
lassert.optionalStringDN(options.entry);
options.protocolOp = Protocol.LDAP_REQ_DELETE; this.entry = options.entry || null
LDAPMessage.call(this, options);
this.entry = options.entry || null;
} }
util.inherits(DeleteRequest, LDAPMessage); util.inherits(DeleteRequest, LDAPMessage)
Object.defineProperties(DeleteRequest.prototype, { Object.defineProperties(DeleteRequest.prototype, {
type: { type: {
get: function getType() { return 'DeleteRequest'; }, get: function getType () { return 'DeleteRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.entry; }, get: function getDN () { return this.entry },
configurable: false configurable: false
} }
}); })
DeleteRequest.prototype._parse = function (ber, length) { DeleteRequest.prototype._parse = function (ber, length) {
assert.ok(ber); assert.ok(ber)
this.entry = ber.buffer.slice(0, length).toString('utf8'); this.entry = ber.buffer.slice(0, length).toString('utf8')
ber._offset += ber.length; ber._offset += ber.length
return true; return true
}; }
DeleteRequest.prototype._toBer = function (ber) { DeleteRequest.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
var buf = Buffer.from(this.entry.toString()); var buf = Buffer.from(this.entry.toString())
for (var i = 0; i < buf.length; i++) for (var i = 0; i < buf.length; i++) { ber.writeByte(buf[i]) }
ber.writeByte(buf[i]);
return ber; return ber
}; }
DeleteRequest.prototype._json = function (j) { 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;

View File

@ -1,24 +1,22 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function DeleteResponse (options) {
options = options || {}
assert.object(options)
function DeleteResponse(options) { options.protocolOp = Protocol.LDAP_REP_DELETE
options = options || {}; LDAPResult.call(this, options)
assert.object(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;

View File

@ -1,120 +1,116 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function ExtendedRequest (options) {
options = options || {}
function ExtendedRequest(options) { assert.object(options)
options = options || {}; assert.optionalString(options.requestName)
assert.object(options);
assert.optionalString(options.requestName);
if (options.requestValue && if (options.requestValue &&
!(Buffer.isBuffer(options.requestValue) || !(Buffer.isBuffer(options.requestValue) ||
typeof (options.requestValue) === 'string')) { 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; options.protocolOp = Protocol.LDAP_REQ_EXTENSION
LDAPMessage.call(this, options); LDAPMessage.call(this, options)
this.requestName = options.requestName || ''; this.requestName = options.requestName || ''
this.requestValue = options.requestValue; this.requestValue = options.requestValue
if(Buffer.isBuffer(this.requestValue)) { if (Buffer.isBuffer(this.requestValue)) {
this.requestValueBuffer = this.requestValue; this.requestValueBuffer = this.requestValue
} else { } 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, { Object.defineProperties(ExtendedRequest.prototype, {
type: { type: {
get: function getType() { return 'ExtendedRequest'; }, get: function getType () { return 'ExtendedRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.requestName; }, get: function getDN () { return this.requestName },
configurable: false configurable: false
}, },
name: { name: {
get: function getName() { return this.requestName; }, get: function getName () { return this.requestName },
set: function setName(val) { set: function setName (val) {
assert.string(val); assert.string(val)
this.requestName = val; this.requestName = val
}, },
configurable: false configurable: false
}, },
value: { value: {
get: function getValue() { return this.requestValue; }, get: function getValue () { return this.requestValue },
set: function setValue(val) { set: function setValue (val) {
if (!(Buffer.isBuffer(val) || typeof (val) === 'string')) if (!(Buffer.isBuffer(val) || typeof (val) === 'string')) { throw new TypeError('value must be a buffer or a string') }
throw new TypeError('value must be a buffer or a string');
if(Buffer.isBuffer(val)) { if (Buffer.isBuffer(val)) {
this.requestValueBuffer = val; this.requestValueBuffer = val
} else { } else {
this.requestValueBuffer = Buffer.from(val, 'utf8'); this.requestValueBuffer = Buffer.from(val, 'utf8')
} }
this.requestValue = val; this.requestValue = val
}, },
configurable: false configurable: false
}, },
valueBuffer: { valueBuffer: {
get: function getValueBuffer() { get: function getValueBuffer () {
return this.requestValueBuffer; return this.requestValueBuffer
}, },
set: function setValueBuffer(val) { set: function setValueBuffer (val) {
if(!Buffer.isBuffer(val)) if (!Buffer.isBuffer(val)) { throw new TypeError('valueBuffer must be a buffer') }
throw new TypeError('valueBuffer must be a buffer');
this.value = val; this.value = val
}, },
configurable: false configurable: false
} }
}); })
ExtendedRequest.prototype._parse = function (ber) { 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) { if (ber.peek() === 0x81) {
this.requestValueBuffer = ber.readString(0x81, true); this.requestValueBuffer = ber.readString(0x81, true)
this.requestValue = this.requestValueBuffer.toString('utf8'); this.requestValue = this.requestValueBuffer.toString('utf8')
} }
return true; return true
}; }
ExtendedRequest.prototype._toBer = function (ber) { 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)) { if (Buffer.isBuffer(this.requestValue)) {
ber.writeBuffer(this.requestValue, 0x81); ber.writeBuffer(this.requestValue, 0x81)
} else if (typeof (this.requestValue) === 'string') { } 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) { ExtendedRequest.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.requestName = this.requestName; j.requestName = this.requestName
j.requestValue = (Buffer.isBuffer(this.requestValue)) ? j.requestValue = (Buffer.isBuffer(this.requestValue))
this.requestValue.toString('hex') : this.requestValue; ? this.requestValue.toString('hex') : this.requestValue
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = ExtendedRequest
module.exports = ExtendedRequest;

View File

@ -1,94 +1,86 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Protocol = require('../protocol'); 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) { this.responseName = options.responseName || undefined
options = options || {}; this.responseValue = options.responseValue || undefined
assert.object(options);
assert.optionalString(options.responseName);
assert.optionalString(options.responsevalue);
this.responseName = options.responseName || undefined; options.protocolOp = Protocol.LDAP_REP_EXTENSION
this.responseValue = options.responseValue || undefined; 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, { Object.defineProperties(ExtendedResponse.prototype, {
type: { type: {
get: function getType() { return 'ExtendedResponse'; }, get: function getType () { return 'ExtendedResponse' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.responseName; }, get: function getDN () { return this.responseName },
configurable: false configurable: false
}, },
name: { name: {
get: function getName() { return this.responseName; }, get: function getName () { return this.responseName },
set: function setName(val) { set: function setName (val) {
assert.string(val); assert.string(val)
this.responseName = val; this.responseName = val
}, },
configurable: false configurable: false
}, },
value: { value: {
get: function getValue() { return this.responseValue; }, get: function getValue () { return this.responseValue },
set: function (val) { set: function (val) {
assert.string(val); assert.string(val)
this.responseValue = val; this.responseValue = val
}, },
configurable: false configurable: false
} }
}); })
ExtendedResponse.prototype._parse = function (ber) { ExtendedResponse.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
if (!LDAPResult.prototype._parse.call(this, ber)) if (!LDAPResult.prototype._parse.call(this, ber)) { return false }
return false;
if (ber.peek() === 0x8a) if (ber.peek() === 0x8a) { this.responseName = ber.readString(0x8a) }
this.responseName = ber.readString(0x8a); if (ber.peek() === 0x8b) { this.responseValue = ber.readString(0x8b) }
if (ber.peek() === 0x8b)
this.responseValue = ber.readString(0x8b);
return true; return true
}; }
ExtendedResponse.prototype._toBer = function (ber) { ExtendedResponse.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
if (!LDAPResult.prototype._toBer.call(this, ber)) if (!LDAPResult.prototype._toBer.call(this, ber)) { return false }
return false;
if (this.responseName) if (this.responseName) { ber.writeString(this.responseName, 0x8a) }
ber.writeString(this.responseName, 0x8a); if (this.responseValue) { ber.writeString(this.responseValue, 0x8b) }
if (this.responseValue)
ber.writeString(this.responseValue, 0x8b);
return ber; return ber
}; }
ExtendedResponse.prototype._json = function (j) { 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.responseName = this.responseName
j.responseValue = this.responseValue; j.responseValue = this.responseValue
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = ExtendedResponse
module.exports = ExtendedResponse;

View File

@ -1,34 +1,33 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Parser = require('./parser'); var Parser = require('./parser')
var AbandonRequest = require('./abandon_request'); var AbandonRequest = require('./abandon_request')
var AbandonResponse = require('./abandon_response'); var AbandonResponse = require('./abandon_response')
var AddRequest = require('./add_request'); var AddRequest = require('./add_request')
var AddResponse = require('./add_response'); var AddResponse = require('./add_response')
var BindRequest = require('./bind_request'); var BindRequest = require('./bind_request')
var BindResponse = require('./bind_response'); var BindResponse = require('./bind_response')
var CompareRequest = require('./compare_request'); var CompareRequest = require('./compare_request')
var CompareResponse = require('./compare_response'); var CompareResponse = require('./compare_response')
var DeleteRequest = require('./del_request'); var DeleteRequest = require('./del_request')
var DeleteResponse = require('./del_response'); var DeleteResponse = require('./del_response')
var ExtendedRequest = require('./ext_request'); var ExtendedRequest = require('./ext_request')
var ExtendedResponse = require('./ext_response'); var ExtendedResponse = require('./ext_response')
var ModifyRequest = require('./modify_request'); var ModifyRequest = require('./modify_request')
var ModifyResponse = require('./modify_response'); var ModifyResponse = require('./modify_response')
var ModifyDNRequest = require('./moddn_request'); var ModifyDNRequest = require('./moddn_request')
var ModifyDNResponse = require('./moddn_response'); var ModifyDNResponse = require('./moddn_response')
var SearchRequest = require('./search_request'); var SearchRequest = require('./search_request')
var SearchEntry = require('./search_entry'); var SearchEntry = require('./search_entry')
var SearchReference = require('./search_reference'); var SearchReference = require('./search_reference')
var SearchResponse = require('./search_response'); var SearchResponse = require('./search_response')
var UnbindRequest = require('./unbind_request'); var UnbindRequest = require('./unbind_request')
var UnbindResponse = require('./unbind_response'); var UnbindResponse = require('./unbind_response')
/// --- API
///--- API
module.exports = { module.exports = {
@ -59,4 +58,4 @@ module.exports = {
UnbindRequest: UnbindRequest, UnbindRequest: UnbindRequest,
UnbindResponse: UnbindResponse UnbindResponse: UnbindResponse
}; }

View File

@ -1,51 +1,48 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var asn1 = require('asn1'); var asn1 = require('asn1')
var logger = require('../logger') var logger = require('../logger')
var Control = require('../controls').Control; // var Control = require('../controls').Control
var Protocol = require('../protocol'); // var Protocol = require('../protocol')
/// --- Globals
///--- Globals // var Ber = asn1.Ber
// var BerReader = asn1.BerReader
var Ber = asn1.Ber; var BerWriter = asn1.BerWriter
var BerReader = asn1.BerReader; var getControl = require('../controls').getControl
var BerWriter = asn1.BerWriter;
var getControl = require('../controls').getControl;
///--- API
/// --- API
/** /**
* LDAPMessage structure. * LDAPMessage structure.
* *
* @param {Object} options stuff. * @param {Object} options stuff.
*/ */
function LDAPMessage(options) { function LDAPMessage (options) {
assert.object(options); assert.object(options)
this.messageID = options.messageID || 0; this.messageID = options.messageID || 0
this.protocolOp = options.protocolOp || undefined; this.protocolOp = options.protocolOp || undefined
this.controls = options.controls ? options.controls.slice(0) : []; this.controls = options.controls ? options.controls.slice(0) : []
this.log = options.log || logger; this.log = options.log || logger
} }
Object.defineProperties(LDAPMessage.prototype, { Object.defineProperties(LDAPMessage.prototype, {
id: { id: {
get: function getId() { return this.messageID; }, get: function getId () { return this.messageID },
configurable: false configurable: false
}, },
dn: { dn: {
get: function getDN() { return this._dn || ''; }, get: function getDN () { return this._dn || '' },
configurable: false configurable: false
}, },
type: { type: {
get: function getType() { return 'LDAPMessage'; }, get: function getType () { return 'LDAPMessage' },
configurable: false configurable: false
}, },
json: { json: {
@ -53,66 +50,61 @@ Object.defineProperties(LDAPMessage.prototype, {
var out = this._json({ var out = this._json({
messageID: this.messageID, messageID: this.messageID,
protocolOp: this.type protocolOp: this.type
}); })
out.controls = this.controls; out.controls = this.controls
return out; return out
}, },
configurable: false configurable: false
} }
}); })
LDAPMessage.prototype.toString = function () { LDAPMessage.prototype.toString = function () {
return JSON.stringify(this.json); return JSON.stringify(this.json)
}; }
LDAPMessage.prototype.parse = function (ber) { LDAPMessage.prototype.parse = function (ber) {
assert.ok(ber); assert.ok(ber)
if (this.log.trace()) if (this.log.trace()) { this.log.trace('parse: data=%s', util.inspect(ber.buffer)) }
this.log.trace('parse: data=%s', util.inspect(ber.buffer));
// Delegate off to the specific type to parse // Delegate off to the specific type to parse
this._parse(ber, ber.length); this._parse(ber, ber.length)
// Look for controls // Look for controls
if (ber.peek() === 0xa0) { if (ber.peek() === 0xa0) {
ber.readSequence(); ber.readSequence()
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) { while (ber.offset < end) {
var c = getControl(ber); var c = getControl(ber)
if (c) if (c) { this.controls.push(c) }
this.controls.push(c);
} }
} }
if (this.log.trace()) if (this.log.trace()) { this.log.trace('Parsing done: %j', this.json) }
this.log.trace('Parsing done: %j', this.json); return true
return true; }
};
LDAPMessage.prototype.toBer = function () { LDAPMessage.prototype.toBer = function () {
var writer = new BerWriter(); var writer = new BerWriter()
writer.startSequence(); writer.startSequence()
writer.writeInt(this.messageID); writer.writeInt(this.messageID)
writer.startSequence(this.protocolOp); writer.startSequence(this.protocolOp)
if (this._toBer) if (this._toBer) { writer = this._toBer(writer) }
writer = this._toBer(writer); writer.endSequence()
writer.endSequence();
if (this.controls && this.controls.length) { if (this.controls && this.controls.length) {
writer.startSequence(0xa0); writer.startSequence(0xa0)
this.controls.forEach(function (c) { this.controls.forEach(function (c) {
c.toBer(writer); c.toBer(writer)
}); })
writer.endSequence(); writer.endSequence()
} }
writer.endSequence(); writer.endSequence()
return writer.buffer; return writer.buffer
}; }
/// --- Exports
///--- Exports module.exports = LDAPMessage
module.exports = LDAPMessage;

View File

@ -1,88 +1,85 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
var dn = require('../dn'); var dn = require('../dn')
var lassert = require('../assert'); 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.protocolOp = Protocol.LDAP_REQ_MODRDN
options = options || {}; LDAPMessage.call(this, 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; this.entry = options.entry || null
LDAPMessage.call(this, options); this.newRdn = options.newRdn || null
this.deleteOldRdn = options.deleteOldRdn || true
this.entry = options.entry || null; this.newSuperior = options.newSuperior || 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, { Object.defineProperties(ModifyDNRequest.prototype, {
type: { type: {
get: function getType() { return 'ModifyDNRequest'; }, get: function getType () { return 'ModifyDNRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.entry; }, get: function getDN () { return this.entry },
configurable: false configurable: false
} }
}); })
ModifyDNRequest.prototype._parse = function (ber) { ModifyDNRequest.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.entry = ber.readString(); this.entry = ber.readString()
this.newRdn = dn.parse(ber.readString()); this.newRdn = dn.parse(ber.readString())
this.deleteOldRdn = ber.readBoolean(); this.deleteOldRdn = ber.readBoolean()
if (ber.peek() === 0x80) if (ber.peek() === 0x80) { this.newSuperior = dn.parse(ber.readString(0x80)) }
this.newSuperior = dn.parse(ber.readString(0x80));
return true; return true
}; }
ModifyDNRequest.prototype._toBer = function (ber) { ModifyDNRequest.prototype._toBer = function (ber) {
//assert.ok(ber); // assert.ok(ber);
ber.writeString(this.entry.toString()); ber.writeString(this.entry.toString())
ber.writeString(this.newRdn.toString()); ber.writeString(this.newRdn.toString())
ber.writeBoolean(this.deleteOldRdn); ber.writeBoolean(this.deleteOldRdn)
if (this.newSuperior) { if (this.newSuperior) {
var s = this.newSuperior.toString(); var s = this.newSuperior.toString()
var len = Buffer.byteLength(s); var len = Buffer.byteLength(s)
ber.writeByte(0x80); // MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG ber.writeByte(0x80) // MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG
ber.writeByte(len); ber.writeByte(len)
ber._ensure(len); ber._ensure(len)
ber._buf.write(s, ber._offset); ber._buf.write(s, ber._offset)
ber._offset += len; ber._offset += len
} }
return ber; return ber
}; }
ModifyDNRequest.prototype._json = function (j) { ModifyDNRequest.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.entry = this.entry.toString(); j.entry = this.entry.toString()
j.newRdn = this.newRdn.toString(); j.newRdn = this.newRdn.toString()
j.deleteOldRdn = this.deleteOldRdn; j.deleteOldRdn = this.deleteOldRdn
j.newSuperior = this.newSuperior ? this.newSuperior.toString() : ''; j.newSuperior = this.newSuperior ? this.newSuperior.toString() : ''
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = ModifyDNRequest
module.exports = ModifyDNRequest;

View File

@ -1,24 +1,22 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function ModifyDNResponse (options) {
options = options || {}
assert.object(options)
function ModifyDNResponse(options) { options.protocolOp = Protocol.LDAP_REP_MODRDN
options = options || {}; LDAPResult.call(this, options)
assert.object(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;

View File

@ -1,85 +1,83 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Change = require('../change'); var Change = require('../change')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
var lassert = require('../assert'); 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.protocolOp = Protocol.LDAP_REQ_MODIFY
options = options || {}; LDAPMessage.call(this, options)
assert.object(options);
lassert.optionalStringDN(options.object);
lassert.optionalArrayOfAttribute(options.attributes);
options.protocolOp = Protocol.LDAP_REQ_MODIFY; this.object = options.object || null
LDAPMessage.call(this, options); 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, { Object.defineProperties(ModifyRequest.prototype, {
type: { type: {
get: function getType() { return 'ModifyRequest'; }, get: function getType () { return 'ModifyRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.object; }, get: function getDN () { return this.object },
configurable: false configurable: false
} }
}); })
ModifyRequest.prototype._parse = function (ber) { ModifyRequest.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.object = ber.readString(); this.object = ber.readString()
ber.readSequence(); ber.readSequence()
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) { while (ber.offset < end) {
var c = new Change(); var c = new Change()
c.parse(ber); c.parse(ber)
c.modification.type = c.modification.type.toLowerCase(); c.modification.type = c.modification.type.toLowerCase()
this.changes.push(c); this.changes.push(c)
} }
this.changes.sort(Change.compare); this.changes.sort(Change.compare)
return true; return true
}; }
ModifyRequest.prototype._toBer = function (ber) { ModifyRequest.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.object.toString()); ber.writeString(this.object.toString())
ber.startSequence(); ber.startSequence()
this.changes.forEach(function (c) { this.changes.forEach(function (c) {
c.toBer(ber); c.toBer(ber)
}); })
ber.endSequence(); ber.endSequence()
return ber; return ber
}; }
ModifyRequest.prototype._json = function (j) { ModifyRequest.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.object = this.object; j.object = this.object
j.changes = []; j.changes = []
this.changes.forEach(function (c) { 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;

View File

@ -1,24 +1,22 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function ModifyResponse (options) {
options = options || {}
assert.object(options)
function ModifyResponse(options) { options.protocolOp = Protocol.LDAP_REP_MODIFY
options = options || {}; LDAPResult.call(this, options)
assert.object(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;

View File

@ -1,228 +1,221 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter
var util = require('util'); var util = require('util')
var assert = require('assert-plus'); var assert = require('assert-plus')
var asn1 = require('asn1'); var asn1 = require('asn1')
var VError = require('verror').VError; // var VError = require('verror').VError
var logger = require('../logger') var logger = require('../logger')
var AbandonRequest = require('./abandon_request'); var AbandonRequest = require('./abandon_request')
var AddRequest = require('./add_request'); var AddRequest = require('./add_request')
var AddResponse = require('./add_response'); var AddResponse = require('./add_response')
var BindRequest = require('./bind_request'); var BindRequest = require('./bind_request')
var BindResponse = require('./bind_response'); var BindResponse = require('./bind_response')
var CompareRequest = require('./compare_request'); var CompareRequest = require('./compare_request')
var CompareResponse = require('./compare_response'); var CompareResponse = require('./compare_response')
var DeleteRequest = require('./del_request'); var DeleteRequest = require('./del_request')
var DeleteResponse = require('./del_response'); var DeleteResponse = require('./del_response')
var ExtendedRequest = require('./ext_request'); var ExtendedRequest = require('./ext_request')
var ExtendedResponse = require('./ext_response'); var ExtendedResponse = require('./ext_response')
var ModifyRequest = require('./modify_request'); var ModifyRequest = require('./modify_request')
var ModifyResponse = require('./modify_response'); var ModifyResponse = require('./modify_response')
var ModifyDNRequest = require('./moddn_request'); var ModifyDNRequest = require('./moddn_request')
var ModifyDNResponse = require('./moddn_response'); var ModifyDNResponse = require('./moddn_response')
var SearchRequest = require('./search_request'); var SearchRequest = require('./search_request')
var SearchEntry = require('./search_entry'); var SearchEntry = require('./search_entry')
var SearchReference = require('./search_reference'); var SearchReference = require('./search_reference')
var SearchResponse = require('./search_response'); var SearchResponse = require('./search_response')
var UnbindRequest = require('./unbind_request'); var UnbindRequest = require('./unbind_request')
var UnbindResponse = require('./unbind_response'); // var UnbindResponse = require('./unbind_response')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var Message = require('./message'); // 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; /// --- API
var BerReader = asn1.BerReader;
function Parser (options = {}) {
assert.object(options)
///--- API EventEmitter.call(this)
function Parser(options = {}) { this.buffer = null
assert.object(options); this.log = options.log || logger
EventEmitter.call(this);
this.buffer = null;
this.log = options.log || logger;
} }
util.inherits(Parser, EventEmitter); util.inherits(Parser, EventEmitter)
Parser.prototype.write = function (data) { Parser.prototype.write = function (data) {
if (!data || !Buffer.isBuffer(data)) if (!data || !Buffer.isBuffer(data)) { throw new TypeError('data (buffer) required') }
throw new TypeError('data (buffer) required');
var nextMessage = null; var nextMessage = null
var self = this; var self = this
function end() { function end () {
if (nextMessage) if (nextMessage) { return self.write(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 { try {
foundSeq = ber.readSequence(); foundSeq = ber.readSequence()
} catch (e) { } catch (e) {
this.emit('error', e); this.emit('error', e)
} }
if (!foundSeq || ber.remain < ber.length) { if (!foundSeq || ber.remain < ber.length) {
// ENOTENOUGH // ENOTENOUGH
return false; return false
} else if (ber.remain > ber.length) { } else if (ber.remain > ber.length) {
// ETOOMUCH // ETOOMUCH
// This is sort of ugly, but allows us to make miminal copies // This is sort of ugly, but allows us to make miminal copies
nextMessage = self.buffer.slice(ber.offset + ber.length); nextMessage = self.buffer.slice(ber.offset + ber.length)
ber._size = ber.offset + ber.length; ber._size = ber.offset + ber.length
assert.equal(ber.remain, ber.length); assert.equal(ber.remain, ber.length)
} }
// If we're here, ber holds the message, and nextMessage is temporarily // If we're here, ber holds the message, and nextMessage is temporarily
// pointing at the next sequence of data (if it exists) // pointing at the next sequence of data (if it exists)
self.buffer = null; self.buffer = null
var message; var message
try { try {
// Bail here if peer isn't speaking protocol at all // Bail here if peer isn't speaking protocol at all
message = this.getMessage(ber); message = this.getMessage(ber)
if (!message) { if (!message) {
return end(); return end()
} }
message.parse(ber); message.parse(ber)
} catch (e) { } catch (e) {
this.emit('error', e, message); this.emit('error', e, message)
return false; return false
} }
this.emit('message', message); this.emit('message', message)
return end(); return end()
}; }
Parser.prototype.getMessage = function (ber) { Parser.prototype.getMessage = function (ber) {
assert.ok(ber); assert.ok(ber)
var self = this; var self = this
var messageID = ber.readInt(); var messageID = ber.readInt()
var type = ber.readSequence(); var type = ber.readSequence()
var Message; var Message
switch (type) { switch (type) {
case Protocol.LDAP_REQ_ABANDON:
Message = AbandonRequest
break
case Protocol.LDAP_REQ_ABANDON: case Protocol.LDAP_REQ_ADD:
Message = AbandonRequest; Message = AddRequest
break; break
case Protocol.LDAP_REQ_ADD: case Protocol.LDAP_REP_ADD:
Message = AddRequest; Message = AddResponse
break; break
case Protocol.LDAP_REP_ADD: case Protocol.LDAP_REQ_BIND:
Message = AddResponse; Message = BindRequest
break; break
case Protocol.LDAP_REQ_BIND: case Protocol.LDAP_REP_BIND:
Message = BindRequest; Message = BindResponse
break; break
case Protocol.LDAP_REP_BIND: case Protocol.LDAP_REQ_COMPARE:
Message = BindResponse; Message = CompareRequest
break; break
case Protocol.LDAP_REQ_COMPARE: case Protocol.LDAP_REP_COMPARE:
Message = CompareRequest; Message = CompareResponse
break; break
case Protocol.LDAP_REP_COMPARE: case Protocol.LDAP_REQ_DELETE:
Message = CompareResponse; Message = DeleteRequest
break; break
case Protocol.LDAP_REQ_DELETE: case Protocol.LDAP_REP_DELETE:
Message = DeleteRequest; Message = DeleteResponse
break; break
case Protocol.LDAP_REP_DELETE: case Protocol.LDAP_REQ_EXTENSION:
Message = DeleteResponse; Message = ExtendedRequest
break; break
case Protocol.LDAP_REQ_EXTENSION: case Protocol.LDAP_REP_EXTENSION:
Message = ExtendedRequest; Message = ExtendedResponse
break; break
case Protocol.LDAP_REP_EXTENSION: case Protocol.LDAP_REQ_MODIFY:
Message = ExtendedResponse; Message = ModifyRequest
break; break
case Protocol.LDAP_REQ_MODIFY: case Protocol.LDAP_REP_MODIFY:
Message = ModifyRequest; Message = ModifyResponse
break; break
case Protocol.LDAP_REP_MODIFY: case Protocol.LDAP_REQ_MODRDN:
Message = ModifyResponse; Message = ModifyDNRequest
break; break
case Protocol.LDAP_REQ_MODRDN: case Protocol.LDAP_REP_MODRDN:
Message = ModifyDNRequest; Message = ModifyDNResponse
break; break
case Protocol.LDAP_REP_MODRDN: case Protocol.LDAP_REQ_SEARCH:
Message = ModifyDNResponse; Message = SearchRequest
break; break
case Protocol.LDAP_REQ_SEARCH: case Protocol.LDAP_REP_SEARCH_ENTRY:
Message = SearchRequest; Message = SearchEntry
break; break
case Protocol.LDAP_REP_SEARCH_ENTRY: case Protocol.LDAP_REP_SEARCH_REF:
Message = SearchEntry; Message = SearchReference
break; break
case Protocol.LDAP_REP_SEARCH_REF: case Protocol.LDAP_REP_SEARCH:
Message = SearchReference; Message = SearchResponse
break; break
case Protocol.LDAP_REP_SEARCH: case Protocol.LDAP_REQ_UNBIND:
Message = SearchResponse; Message = UnbindRequest
break; break
case Protocol.LDAP_REQ_UNBIND: default:
Message = UnbindRequest; this.emit('error',
break; new Error('Op 0x' + (type ? type.toString(16) : '??') +
default:
this.emit('error',
new Error('Op 0x' + (type ? type.toString(16) : '??') +
' not supported'), ' not supported'),
new LDAPResult({ new LDAPResult({
messageID: messageID, messageID: messageID,
protocolOp: type || Protocol.LDAP_REP_EXTENSION protocolOp: type || Protocol.LDAP_REP_EXTENSION
})); }))
return false; return false
} }
return new Message({ return new Message({
messageID: messageID, messageID: messageID,
log: self.log log: self.log
}); })
}; }
/// --- Exports
///--- Exports module.exports = Parser
module.exports = Parser;

View File

@ -1,65 +1,61 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var asn1 = require('asn1'); // var asn1 = require('asn1')
var dtrace = require('../dtrace'); var dtrace = require('../dtrace')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- Globals
///--- Globals // var Ber = asn1.Ber
// var BerWriter = asn1.BerWriter
var Ber = asn1.Ber; /// --- API
var BerWriter = asn1.BerWriter;
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) { this.status = options.status || 0 // LDAP SUCCESS
options = options || {}; this.matchedDN = options.matchedDN || ''
assert.object(options); this.errorMessage = options.errorMessage || ''
assert.optionalNumber(options.status); this.referrals = options.referrals || []
assert.optionalString(options.matchedDN);
assert.optionalString(options.errorMessage);
assert.optionalArrayOfString(options.referrals);
LDAPMessage.call(this, options); this.connection = options.connection || null
this.status = options.status || 0; // LDAP SUCCESS
this.matchedDN = options.matchedDN || '';
this.errorMessage = options.errorMessage || '';
this.referrals = options.referrals || [];
this.connection = options.connection || null;
} }
util.inherits(LDAPResult, LDAPMessage); util.inherits(LDAPResult, LDAPMessage)
Object.defineProperties(LDAPResult.prototype, { Object.defineProperties(LDAPResult.prototype, {
type: { type: {
get: function getType() { return 'LDAPResult'; }, get: function getType () { return 'LDAPResult' },
configurable: false configurable: false
} }
}); })
LDAPResult.prototype.end = function (status) { LDAPResult.prototype.end = function (status) {
assert.ok(this.connection); assert.ok(this.connection)
if (typeof (status) === 'number') if (typeof (status) === 'number') { this.status = status }
this.status = status;
var ber = this.toBer(); var ber = this.toBer()
if (this.log.debug()) if (this.log.debug()) { this.log.debug('%s: sending: %j', this.connection.ldap.id, this.json) }
this.log.debug('%s: sending: %j', this.connection.ldap.id, this.json);
try { try {
var self = this; var self = this
this.connection.write(ber); this.connection.write(ber)
if (self._dtraceOp && self._dtraceId) { if (self._dtraceOp && self._dtraceId) {
dtrace.fire('server-' + self._dtraceOp + '-done', function () { dtrace.fire('server-' + self._dtraceOp + '-done', function () {
var c = self.connection || {ldap: {}}; var c = self.connection || { ldap: {} }
return [ return [
self._dtraceId || 0, self._dtraceId || 0,
(c.remoteAddress || ''), (c.remoteAddress || ''),
@ -67,63 +63,59 @@ LDAPResult.prototype.end = function (status) {
(self.requestDN ? self.requestDN.toString() : ''), (self.requestDN ? self.requestDN.toString() : ''),
status || self.status, status || self.status,
self.errorMessage self.errorMessage
]; ]
}); })
} }
} catch (e) { } catch (e) {
this.log.warn(e, '%s failure to write message %j', 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) { LDAPResult.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.status = ber.readEnumeration(); this.status = ber.readEnumeration()
this.matchedDN = ber.readString(); this.matchedDN = ber.readString()
this.errorMessage = ber.readString(); this.errorMessage = ber.readString()
var t = ber.peek(); var t = ber.peek()
if (t === Protocol.LDAP_REP_REFERRAL) { if (t === Protocol.LDAP_REP_REFERRAL) {
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) while (ber.offset < end) { this.referrals.push(ber.readString()) }
this.referrals.push(ber.readString());
} }
return true; return true
}; }
LDAPResult.prototype._toBer = function (ber) { LDAPResult.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeEnumeration(this.status); ber.writeEnumeration(this.status)
ber.writeString(this.matchedDN || ''); ber.writeString(this.matchedDN || '')
ber.writeString(this.errorMessage || ''); ber.writeString(this.errorMessage || '')
if (this.referrals.length) { if (this.referrals.length) {
ber.startSequence(Protocol.LDAP_REP_REFERRAL); ber.startSequence(Protocol.LDAP_REP_REFERRAL)
ber.writeStringArray(this.referrals); ber.writeStringArray(this.referrals)
ber.endSequence(); ber.endSequence()
} }
return ber; return ber
}; }
LDAPResult.prototype._json = function (j) { LDAPResult.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.status = this.status; j.status = this.status
j.matchedDN = this.matchedDN; j.matchedDN = this.matchedDN
j.errorMessage = this.errorMessage; j.errorMessage = this.errorMessage
j.referrals = this.referrals; j.referrals = this.referrals
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = LDAPResult
module.exports = LDAPResult;

View File

@ -1,196 +1,187 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var asn1 = require('asn1'); // var asn1 = require('asn1')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Attribute = require('../attribute'); var Attribute = require('../attribute')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
var lassert = require('../assert'); 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) { this.objectName = options.objectName || null
options = options || {}; this.setAttributes(options.attributes || [])
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 || []);
} }
util.inherits(SearchEntry, LDAPMessage); util.inherits(SearchEntry, LDAPMessage)
Object.defineProperties(SearchEntry.prototype, { Object.defineProperties(SearchEntry.prototype, {
type: { type: {
get: function getType() { return 'SearchEntry'; }, get: function getType () { return 'SearchEntry' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.objectName; }, get: function getDN () { return this.objectName },
configurable: false configurable: false
}, },
object: { object: {
get: function getObject() { get: function getObject () {
var obj = { var obj = {
dn: this.dn.toString(), dn: this.dn.toString(),
controls: [] controls: []
}; }
this.attributes.forEach(function (a) { this.attributes.forEach(function (a) {
if (a.vals && a.vals.length) { if (a.vals && a.vals.length) {
if (a.vals.length > 1) { if (a.vals.length > 1) {
obj[a.type] = a.vals.slice(); obj[a.type] = a.vals.slice()
} else { } else {
obj[a.type] = a.vals[0]; obj[a.type] = a.vals[0]
} }
} else { } else {
obj[a.type] = []; obj[a.type] = []
} }
}); })
this.controls.forEach(function (element, index, array) { this.controls.forEach(function (element, index, array) {
obj.controls.push(element.json); obj.controls.push(element.json)
}); })
return obj; return obj
}, },
configurable: false configurable: false
}, },
raw: { raw: {
get: function getRaw() { get: function getRaw () {
var obj = { var obj = {
dn: this.dn.toString(), dn: this.dn.toString(),
controls: [] controls: []
}; }
this.attributes.forEach(function (a) { this.attributes.forEach(function (a) {
if (a.buffers && a.buffers.length) { if (a.buffers && a.buffers.length) {
if (a.buffers.length > 1) { if (a.buffers.length > 1) {
obj[a.type] = a.buffers.slice(); obj[a.type] = a.buffers.slice()
} else { } else {
obj[a.type] = a.buffers[0]; obj[a.type] = a.buffers[0]
} }
} else { } else {
obj[a.type] = []; obj[a.type] = []
} }
}); })
this.controls.forEach(function (element, index, array) { this.controls.forEach(function (element, index, array) {
obj.controls.push(element.json); obj.controls.push(element.json)
}); })
return obj; return obj
}, },
configurable: false configurable: false
} }
}); })
SearchEntry.prototype.addAttribute = function (attr) { SearchEntry.prototype.addAttribute = function (attr) {
if (!attr || typeof (attr) !== 'object') if (!attr || typeof (attr) !== 'object') { throw new TypeError('attr (attribute) required') }
throw new TypeError('attr (attribute) required');
this.attributes.push(attr); this.attributes.push(attr)
}; }
SearchEntry.prototype.toObject = function () { SearchEntry.prototype.toObject = function () {
return this.object; return this.object
}; }
SearchEntry.prototype.fromObject = function (obj) { SearchEntry.prototype.fromObject = function (obj) {
if (typeof (obj) !== 'object') if (typeof (obj) !== 'object') { throw new TypeError('object required') }
throw new TypeError('object required');
var self = this; var self = this
if (obj.controls) if (obj.controls) { this.controls = obj.controls }
this.controls = obj.controls;
if (obj.attributes) if (obj.attributes) { obj = obj.attributes }
obj = obj.attributes; this.attributes = []
this.attributes = [];
Object.keys(obj).forEach(function (k) { 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) { SearchEntry.prototype.setAttributes = function (obj) {
if (typeof (obj) !== 'object') if (typeof (obj) !== 'object') { throw new TypeError('object required') }
throw new TypeError('object required');
if (Array.isArray(obj)) { if (Array.isArray(obj)) {
obj.forEach(function (a) { obj.forEach(function (a) {
if (!Attribute.isAttribute(a)) if (!Attribute.isAttribute(a)) { throw new TypeError('entry must be an Array of Attributes') }
throw new TypeError('entry must be an Array of Attributes'); })
}); this.attributes = obj
this.attributes = obj;
} else { } else {
var self = this; var self = this
self.attributes = []; self.attributes = []
Object.keys(obj).forEach(function (k) { Object.keys(obj).forEach(function (k) {
var attr = new Attribute({type: k}); var attr = new Attribute({ type: k })
if (Array.isArray(obj[k])) { if (Array.isArray(obj[k])) {
obj[k].forEach(function (v) { obj[k].forEach(function (v) {
attr.addValue(v.toString()); attr.addValue(v.toString())
}); })
} else { } else {
attr.addValue(obj[k].toString()); attr.addValue(obj[k].toString())
} }
self.attributes.push(attr); self.attributes.push(attr)
}); })
} }
}; }
SearchEntry.prototype._json = function (j) { SearchEntry.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.objectName = this.objectName.toString(); j.objectName = this.objectName.toString()
j.attributes = []; j.attributes = []
this.attributes.forEach(function (a) { 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) { SearchEntry.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.objectName = ber.readString(); this.objectName = ber.readString()
assert.ok(ber.readSequence()); assert.ok(ber.readSequence())
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) { while (ber.offset < end) {
var a = new Attribute(); var a = new Attribute()
a.parse(ber); a.parse(ber)
this.attributes.push(a); this.attributes.push(a)
} }
return true; return true
}; }
SearchEntry.prototype._toBer = function (ber) { SearchEntry.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.objectName.toString()); ber.writeString(this.objectName.toString())
ber.startSequence(); ber.startSequence()
this.attributes.forEach(function (a) { this.attributes.forEach(function (a) {
// This may or may not be an attribute // This may or may not be an attribute
ber = Attribute.toBer(a, ber); ber = Attribute.toBer(a, ber)
}); })
ber.endSequence(); ber.endSequence()
return ber; return ber
}; }
/// --- Exports
///--- Exports module.exports = SearchEntry
module.exports = SearchEntry;

View File

@ -1,105 +1,101 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var asn1 = require('asn1'); // var asn1 = require('asn1')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
var dn = require('../dn'); var dn = require('../dn')
var url = require('../url'); var url = require('../url')
/// --- Globals
///--- Globals // var BerWriter = asn1.BerWriter
var parseURL = url.parse
var BerWriter = asn1.BerWriter; /// --- API
var parseURL = url.parse;
function SearchReference (options) {
options = options || {}
assert.object(options)
///--- API options.protocolOp = Protocol.LDAP_REP_SEARCH_REF
LDAPMessage.call(this, options)
function SearchReference(options) { this.uris = options.uris || []
options = options || {};
assert.object(options);
options.protocolOp = Protocol.LDAP_REP_SEARCH_REF;
LDAPMessage.call(this, options);
this.uris = options.uris || [];
} }
util.inherits(SearchReference, LDAPMessage); util.inherits(SearchReference, LDAPMessage)
Object.defineProperties(SearchReference.prototype, { Object.defineProperties(SearchReference.prototype, {
type: { type: {
get: function getType() { return 'SearchReference'; }, get: function getType () { return 'SearchReference' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return new dn.DN(''); }, get: function getDN () { return new dn.DN('') },
configurable: false configurable: false
}, },
object: { object: {
get: function getObject() { get: function getObject () {
return { return {
dn: this.dn.toString(), dn: this.dn.toString(),
uris: this.uris.slice() uris: this.uris.slice()
}; }
}, },
configurable: false configurable: false
}, },
urls: { urls: {
get: function getUrls() { return this.uris; }, get: function getUrls () { return this.uris },
set: function setUrls(val) { set: function setUrls (val) {
assert.ok(val); assert.ok(val)
assert.ok(Array.isArray(val)); assert.ok(Array.isArray(val))
this.uris = val.slice(); this.uris = val.slice()
}, },
configurable: false configurable: false
} }
}); })
SearchReference.prototype.toObject = function () { SearchReference.prototype.toObject = function () {
return this.object; return this.object
}; }
SearchReference.prototype.fromObject = function (obj) { SearchReference.prototype.fromObject = function (obj) {
if (typeof (obj) !== 'object') if (typeof (obj) !== 'object') { throw new TypeError('object required') }
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) { SearchReference.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.uris = this.uris.slice(); j.uris = this.uris.slice()
return j; return j
}; }
SearchReference.prototype._parse = function (ber, length) { SearchReference.prototype._parse = function (ber, length) {
assert.ok(ber); assert.ok(ber)
while (ber.offset < length) { while (ber.offset < length) {
var _url = ber.readString(); var _url = ber.readString()
parseURL(_url); parseURL(_url)
this.uris.push(_url); this.uris.push(_url)
} }
return true; return true
}; }
SearchReference.prototype._toBer = function (ber) { SearchReference.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
this.uris.forEach(function (u) { 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;

View File

@ -1,150 +1,146 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var asn1 = require('asn1'); var asn1 = require('asn1')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var LDAPResult = require('./result'); // var LDAPResult = require('./result')
var dn = require('../dn'); var dn = require('../dn')
var filters = require('../filters'); var filters = require('../filters')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- Globals
///--- Globals var Ber = asn1.Ber
var Ber = asn1.Ber; /// --- API
function SearchRequest (options) {
options = options || {}
assert.object(options)
///--- API options.protocolOp = Protocol.LDAP_REQ_SEARCH
LDAPMessage.call(this, options)
function SearchRequest(options) {
options = options || {};
assert.object(options);
options.protocolOp = Protocol.LDAP_REQ_SEARCH;
LDAPMessage.call(this, options);
if (options.baseObject !== undefined) { if (options.baseObject !== undefined) {
this.baseObject = options.baseObject; this.baseObject = options.baseObject
} else { } else {
this.baseObject = dn.parse(''); this.baseObject = dn.parse('')
} }
this.scope = options.scope || 'base'; this.scope = options.scope || 'base'
this.derefAliases = options.derefAliases || Protocol.NEVER_DEREF_ALIASES; this.derefAliases = options.derefAliases || Protocol.NEVER_DEREF_ALIASES
this.sizeLimit = options.sizeLimit || 0; this.sizeLimit = options.sizeLimit || 0
this.timeLimit = options.timeLimit || 0; this.timeLimit = options.timeLimit || 0
this.typesOnly = options.typesOnly || false; this.typesOnly = options.typesOnly || false
this.filter = options.filter || null; this.filter = options.filter || null
this.attributes = options.attributes ? options.attributes.slice(0) : []; this.attributes = options.attributes ? options.attributes.slice(0) : []
} }
util.inherits(SearchRequest, LDAPMessage); util.inherits(SearchRequest, LDAPMessage)
Object.defineProperties(SearchRequest.prototype, { Object.defineProperties(SearchRequest.prototype, {
type: { type: {
get: function getType() { return 'SearchRequest'; }, get: function getType () { return 'SearchRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { return this.baseObject; }, get: function getDN () { return this.baseObject },
configurable: false configurable: false
}, },
scope: { scope: {
get: function getScope() { get: function getScope () {
switch (this._scope) { switch (this._scope) {
case Protocol.SCOPE_BASE_OBJECT: return 'base'; case Protocol.SCOPE_BASE_OBJECT: return 'base'
case Protocol.SCOPE_ONE_LEVEL: return 'one'; case Protocol.SCOPE_ONE_LEVEL: return 'one'
case Protocol.SCOPE_SUBTREE: return 'sub'; case Protocol.SCOPE_SUBTREE: return 'sub'
default: default:
throw new Error(this._scope + ' is an invalid search scope'); throw new Error(this._scope + ' is an invalid search scope')
} }
}, },
set: function setScope(val) { set: function setScope (val) {
if (typeof (val) === 'string') { if (typeof (val) === 'string') {
switch (val) { switch (val) {
case 'base': case 'base':
this._scope = Protocol.SCOPE_BASE_OBJECT; this._scope = Protocol.SCOPE_BASE_OBJECT
break; break
case 'one': case 'one':
this._scope = Protocol.SCOPE_ONE_LEVEL; this._scope = Protocol.SCOPE_ONE_LEVEL
break; break
case 'sub': case 'sub':
this._scope = Protocol.SCOPE_SUBTREE; this._scope = Protocol.SCOPE_SUBTREE
break; break
default: default:
throw new Error(val + ' is an invalid search scope'); throw new Error(val + ' is an invalid search scope')
} }
} else { } else {
this._scope = val; this._scope = val
} }
}, },
configurable: false configurable: false
} }
}); })
SearchRequest.prototype._parse = function (ber) { SearchRequest.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
this.baseObject = ber.readString(); this.baseObject = ber.readString()
this.scope = ber.readEnumeration(); this.scope = ber.readEnumeration()
this.derefAliases = ber.readEnumeration(); this.derefAliases = ber.readEnumeration()
this.sizeLimit = ber.readInt(); this.sizeLimit = ber.readInt()
this.timeLimit = ber.readInt(); this.timeLimit = ber.readInt()
this.typesOnly = ber.readBoolean(); this.typesOnly = ber.readBoolean()
this.filter = filters.parse(ber); this.filter = filters.parse(ber)
// look for attributes // look for attributes
if (ber.peek() === 0x30) { if (ber.peek() === 0x30) {
ber.readSequence(); ber.readSequence()
var end = ber.offset + ber.length; var end = ber.offset + ber.length
while (ber.offset < end) while (ber.offset < end) { this.attributes.push(ber.readString().toLowerCase()) }
this.attributes.push(ber.readString().toLowerCase());
} }
return true; return true
}; }
SearchRequest.prototype._toBer = function (ber) { SearchRequest.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
ber.writeString(this.baseObject.toString()); ber.writeString(this.baseObject.toString())
ber.writeEnumeration(this._scope); ber.writeEnumeration(this._scope)
ber.writeEnumeration(this.derefAliases); ber.writeEnumeration(this.derefAliases)
ber.writeInt(this.sizeLimit); ber.writeInt(this.sizeLimit)
ber.writeInt(this.timeLimit); ber.writeInt(this.timeLimit)
ber.writeBoolean(this.typesOnly); ber.writeBoolean(this.typesOnly)
var f = this.filter || new filters.PresenceFilter({attribute: 'objectclass'}); var f = this.filter || new filters.PresenceFilter({ attribute: 'objectclass' })
ber = f.toBer(ber); ber = f.toBer(ber)
ber.startSequence(Ber.Sequence | Ber.Constructor); ber.startSequence(Ber.Sequence | Ber.Constructor)
if (this.attributes && this.attributes.length) { if (this.attributes && this.attributes.length) {
this.attributes.forEach(function (a) { this.attributes.forEach(function (a) {
ber.writeString(a); ber.writeString(a)
}); })
} }
ber.endSequence(); ber.endSequence()
return ber; return ber
}; }
SearchRequest.prototype._json = function (j) { SearchRequest.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
j.baseObject = this.baseObject; j.baseObject = this.baseObject
j.scope = this.scope; j.scope = this.scope
j.derefAliases = this.derefAliases; j.derefAliases = this.derefAliases
j.sizeLimit = this.sizeLimit; j.sizeLimit = this.sizeLimit
j.timeLimit = this.timeLimit; j.timeLimit = this.timeLimit
j.typesOnly = this.typesOnly; j.typesOnly = this.typesOnly
j.filter = this.filter.toString(); j.filter = this.filter.toString()
j.attributes = this.attributes; j.attributes = this.attributes
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = SearchRequest
module.exports = SearchRequest;

View File

@ -1,32 +1,31 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPResult = require('./result'); var LDAPResult = require('./result')
var SearchEntry = require('./search_entry'); var SearchEntry = require('./search_entry')
var SearchReference = require('./search_reference'); var SearchReference = require('./search_reference')
var dtrace = require('../dtrace'); var dtrace = require('../dtrace')
var parseDN = require('../dn').parse; var parseDN = require('../dn').parse
var parseURL = require('../url').parse; var parseURL = require('../url').parse
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- API
///--- API function SearchResponse (options) {
options = options || {}
assert.object(options)
function SearchResponse(options) { options.protocolOp = Protocol.LDAP_REP_SEARCH
options = options || {}; LDAPResult.call(this, options)
assert.object(options);
options.protocolOp = Protocol.LDAP_REP_SEARCH; this.attributes = options.attributes ? options.attributes.slice() : []
LDAPResult.call(this, options); 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. * Allows you to send a SearchEntry back to the client.
@ -36,61 +35,54 @@ util.inherits(SearchResponse, LDAPResult);
* Defaults to 'false'. * Defaults to 'false'.
*/ */
SearchResponse.prototype.send = function (entry, nofiltering) { SearchResponse.prototype.send = function (entry, nofiltering) {
if (!entry || typeof (entry) !== 'object') if (!entry || typeof (entry) !== 'object') { throw new TypeError('entry (SearchEntry) required') }
throw new TypeError('entry (SearchEntry) required'); if (nofiltering === undefined) { nofiltering = false }
if (nofiltering === undefined) if (typeof (nofiltering) !== 'boolean') { throw new TypeError('noFiltering must be a boolean') }
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 instanceof SearchEntry || entry instanceof SearchReference) {
if (!entry.messageID) if (!entry.messageID) { entry.messageID = this.messageID }
entry.messageID = this.messageID; if (entry.messageID !== this.messageID) { throw new Error('SearchEntry messageID mismatch') }
if (entry.messageID !== this.messageID)
throw new Error('SearchEntry messageID mismatch');
} else { } else {
if (!entry.attributes) if (!entry.attributes) { throw new Error('entry.attributes required') }
throw new Error('entry.attributes required');
var savedAttrs = {}; var savedAttrs = {}
var all = (self.attributes.indexOf('*') !== -1); var all = (self.attributes.indexOf('*') !== -1)
Object.keys(entry.attributes).forEach(function (a) { Object.keys(entry.attributes).forEach(function (a) {
var _a = a.toLowerCase(); var _a = a.toLowerCase()
if (!nofiltering && _a.length && _a[0] === '_') { if (!nofiltering && _a.length && _a[0] === '_') {
savedAttrs[a] = entry.attributes[a]; savedAttrs[a] = entry.attributes[a]
delete entry.attributes[a]; delete entry.attributes[a]
} else if (!nofiltering && self.notAttributes.indexOf(_a) !== -1) { } else if (!nofiltering && self.notAttributes.indexOf(_a) !== -1) {
savedAttrs[a] = entry.attributes[a]; savedAttrs[a] = entry.attributes[a]
delete entry.attributes[a]; delete entry.attributes[a]
} else if (all) { } 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({ entry = new SearchEntry({
objectName: typeof (save.dn) === 'string' ? parseDN(save.dn) : save.dn, objectName: typeof (save.dn) === 'string' ? parseDN(save.dn) : save.dn,
messageID: self.messageID, messageID: self.messageID,
log: self.log log: self.log
}); })
entry.fromObject(save); entry.fromObject(save)
} }
try { try {
if (this.log.debug()) if (this.log.debug) { this.log.debug('%s: sending: %j', this.connection.ldap.id, entry.json) }
this.log.debug('%s: sending: %j', this.connection.ldap.id, entry.json);
this.connection.write(entry.toBer()); this.connection.write(entry.toBer())
this.sentEntries++; this.sentEntries++
if (self._dtraceOp && self._dtraceId) { if (self._dtraceOp && self._dtraceId) {
dtrace.fire('server-search-entry', function () { dtrace.fire('server-search-entry', function () {
var c = self.connection || {ldap: {}}; var c = self.connection || { ldap: {} }
return [ return [
self._dtraceId || 0, self._dtraceId || 0,
(c.remoteAddress || ''), (c.remoteAddress || ''),
@ -98,54 +90,49 @@ SearchResponse.prototype.send = function (entry, nofiltering) {
(self.requestDN ? self.requestDN.toString() : ''), (self.requestDN ? self.requestDN.toString() : ''),
entry.objectName.toString(), entry.objectName.toString(),
entry.attributes.length entry.attributes.length
]; ]
}); })
} }
// Restore attributes // Restore attributes
Object.keys(savedAttrs || {}).forEach(function (k) { Object.keys(savedAttrs || {}).forEach(function (k) {
save.attributes[k] = savedAttrs[k]; save.attributes[k] = savedAttrs[k]
}); })
} catch (e) { } catch (e) {
this.log.warn(e, '%s failure to write message %j', 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) { SearchResponse.prototype.createSearchEntry = function (object) {
assert.object(object); assert.object(object)
var entry = new SearchEntry({ var entry = new SearchEntry({
messageID: this.messageID, messageID: this.messageID,
log: this.log, log: this.log,
objectName: object.objectName || object.dn objectName: object.objectName || object.dn
}); })
entry.fromObject((object.attributes || object)); entry.fromObject((object.attributes || object))
return entry; return entry
}; }
SearchResponse.prototype.createSearchReference = function (uris) { SearchResponse.prototype.createSearchReference = function (uris) {
if (!uris) if (!uris) { throw new TypeError('uris ([string]) required') }
throw new TypeError('uris ([string]) required');
if (!Array.isArray(uris)) if (!Array.isArray(uris)) { uris = [uris] }
uris = [uris];
for (var i = 0; i < uris.length; i++) { for (var i = 0; i < uris.length; i++) {
if (typeof (uris[i]) == 'string') if (typeof (uris[i]) === 'string') { uris[i] = parseURL(uris[i]) }
uris[i] = parseURL(uris[i]);
} }
var self = this; var self = this
return new SearchReference({ return new SearchReference({
messageID: self.messageID, messageID: self.messageID,
log: self.log, log: self.log,
uris: uris uris: uris
}); })
}; }
/// --- Exports
///--- Exports module.exports = SearchResponse
module.exports = SearchResponse;

View File

@ -1,65 +1,62 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var LDAPMessage = require('./message'); var LDAPMessage = require('./message')
var dn = require('../dn'); var dn = require('../dn')
var Protocol = require('../protocol'); var Protocol = require('../protocol')
/// --- Globals
///--- Globals var DN = dn.DN
var RDN = dn.RDN
var DN = dn.DN; /// --- API
var RDN = dn.RDN;
function UnbindRequest (options) {
options = options || {}
assert.object(options)
///--- API options.protocolOp = Protocol.LDAP_REQ_UNBIND
LDAPMessage.call(this, options)
function UnbindRequest(options) {
options = options || {};
assert.object(options);
options.protocolOp = Protocol.LDAP_REQ_UNBIND;
LDAPMessage.call(this, options);
} }
util.inherits(UnbindRequest, LDAPMessage); util.inherits(UnbindRequest, LDAPMessage)
Object.defineProperties(UnbindRequest.prototype, { Object.defineProperties(UnbindRequest.prototype, {
type: { type: {
get: function getType() { return 'UnbindRequest'; }, get: function getType () { return 'UnbindRequest' },
configurable: false configurable: false
}, },
_dn: { _dn: {
get: function getDN() { get: function getDN () {
if (this.connection) { if (this.connection) {
return this.connection.ldap.bindDN; return this.connection.ldap.bindDN
} else { } else {
return new DN([new RDN({cn: 'anonymous'})]); return new DN([new RDN({ cn: 'anonymous' })])
} }
}, },
configurable: false configurable: false
} }
}); })
UnbindRequest.prototype._parse = function (ber) { UnbindRequest.prototype._parse = function (ber) {
assert.ok(ber); assert.ok(ber)
return true; return true
}; }
UnbindRequest.prototype._toBer = function (ber) { UnbindRequest.prototype._toBer = function (ber) {
assert.ok(ber); assert.ok(ber)
return ber; return ber
}; }
UnbindRequest.prototype._json = function (j) { UnbindRequest.prototype._json = function (j) {
assert.ok(j); assert.ok(j)
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = UnbindRequest
module.exports = UnbindRequest;

View File

@ -1,33 +1,32 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
var assert = require('assert-plus'); var assert = require('assert-plus')
var util = require('util'); var util = require('util')
var dtrace = require('../dtrace'); var dtrace = require('../dtrace')
var LDAPMessage = require('./result'); var LDAPMessage = require('./result')
var Protocol = require('../protocol'); // var Protocol = require('../protocol')
/// --- API
///--- API
// Ok, so there's really no such thing as an unbind 'response', but to make // 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 // the framework not suck, I just made this up, and have it stubbed so it's
// not such a one-off. // not such a one-off.
function UnbindResponse(options) { function UnbindResponse (options) {
options = options || {}; options = options || {}
assert.object(options); assert.object(options)
options.protocolOp = 0; options.protocolOp = 0
LDAPMessage.call(this, options); LDAPMessage.call(this, options)
} }
util.inherits(UnbindResponse, LDAPMessage); util.inherits(UnbindResponse, LDAPMessage)
Object.defineProperties(UnbindResponse.prototype, { Object.defineProperties(UnbindResponse.prototype, {
type: { type: {
get: function getType() { return 'UnbindResponse'; }, get: function getType () { return 'UnbindResponse' },
configurable: false configurable: false
} }
}); })
/** /**
* Special override that just ends the connection, if present. * Special override that just ends the connection, if present.
@ -35,16 +34,16 @@ Object.defineProperties(UnbindResponse.prototype, {
* @param {Number} status completely ignored. * @param {Number} status completely ignored.
*/ */
UnbindResponse.prototype.end = function (status) { 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) { if (self._dtraceOp && self._dtraceId) {
dtrace.fire('server-' + self._dtraceOp + '-done', function () { dtrace.fire('server-' + self._dtraceOp + '-done', function () {
var c = self.connection || {ldap: {}}; var c = self.connection || { ldap: {} }
return [ return [
self._dtraceId || 0, self._dtraceId || 0,
(c.remoteAddress || ''), (c.remoteAddress || ''),
@ -52,16 +51,15 @@ UnbindResponse.prototype.end = function (status) {
(self.requestDN ? self.requestDN.toString() : ''), (self.requestDN ? self.requestDN.toString() : ''),
0, 0,
'' ''
]; ]
}); })
} }
}; }
UnbindResponse.prototype._json = function (j) { UnbindResponse.prototype._json = function (j) {
return j; return j
}; }
/// --- Exports
///--- Exports module.exports = UnbindResponse
module.exports = UnbindResponse;

View File

@ -1,123 +1,109 @@
///--- Globals /// --- Globals
var parseDN = require('./dn').parse; // var parseDN = require('./dn').parse
var EntryChangeNotificationControl = var EntryChangeNotificationControl =
require('./controls').EntryChangeNotificationControl; require('./controls').EntryChangeNotificationControl
///--- API /// --- API
// Cache used to store connected persistent search clients // Cache used to store connected persistent search clients
function PersistentSearch() { function PersistentSearch () {
this.clientList = []; this.clientList = []
} }
PersistentSearch.prototype.addClient = function (req, res, callback) { PersistentSearch.prototype.addClient = function (req, res, callback) {
if (typeof (req) !== 'object') if (typeof (req) !== 'object') { throw new TypeError('req must be an object') }
throw new TypeError('req must be an object'); if (typeof (res) !== 'object') { throw new TypeError('res must be an object') }
if (typeof (res) !== 'object') if (callback && typeof (callback) !== 'function') { throw new TypeError('callback must be a function') }
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 = {}; var client = {}
client.req = req; client.req = req
client.res = res; 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', log.debug('%s total number of clients %s',
req.logId, this.clientList.length); req.logId, this.clientList.length)
if (callback) if (callback) { callback(client) }
callback(client); }
};
PersistentSearch.prototype.removeClient = function (req, res, callback) { PersistentSearch.prototype.removeClient = function (req, res, callback) {
if (typeof (req) !== 'object') if (typeof (req) !== 'object') { throw new TypeError('req must be an object') }
throw new TypeError('req must be an object'); if (typeof (res) !== 'object') { throw new TypeError('res must be an object') }
if (typeof (res) !== 'object') if (callback && typeof (callback) !== 'function') { throw new TypeError('callback must be a function') }
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
log.debug('%s removing client', req.logId); log.debug('%s removing client', req.logId)
var client = {}; var client = {}
client.req = req; client.req = req
client.res = res; client.res = res
// remove the client if it exists // remove the client if it exists
this.clientList.forEach(function (element, index, array) { this.clientList.forEach(function (element, index, array) {
if (element.req === client.req) { if (element.req === client.req) {
log.debug('%s removing client from list', req.logId); log.debug('%s removing client from list', req.logId)
array.splice(index, 1); array.splice(index, 1)
} }
}); })
log.debug('%s number of persistent search clients %s', log.debug('%s number of persistent search clients %s',
req.logId, this.clientList.length); req.logId, this.clientList.length)
if (callback) if (callback) { callback(client) }
callback(client); }
};
function getOperationType (requestType) {
function getOperationType(requestType) {
switch (requestType) { switch (requestType) {
case 'AddRequest': case 'AddRequest':
case 'add': case 'add':
return 1; return 1
case 'DeleteRequest': case 'DeleteRequest':
case 'delete': case 'delete':
return 2; return 2
case 'ModifyRequest': case 'ModifyRequest':
case 'modify': case 'modify':
return 4; return 4
case 'ModifyDNRequest': case 'ModifyDNRequest':
case 'modrdn': case 'modrdn':
return 8; return 8
default: default:
throw new TypeError('requestType %s, is an invalid request type', 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 we want to return a ECNC
if (req.persistentSearch.value.returnECs) { if (req.persistentSearch.value.returnECs) {
var attrs = obj.attributes; var attrs = obj.attributes
var value = {}; var value = {}
value.changeType = getOperationType(attrs.changetype); value.changeType = getOperationType(attrs.changetype)
// if it's a modDN request, fill in the previous DN // if it's a modDN request, fill in the previous DN
if (value.changeType === 8 && attrs.previousDN) { if (value.changeType === 8 && attrs.previousDN) {
value.previousDN = attrs.previousDN; value.previousDN = attrs.previousDN
} }
value.changeNumber = attrs.changenumber; value.changeNumber = attrs.changenumber
return new EntryChangeNotificationControl({ value: value }); return new EntryChangeNotificationControl({ value: value })
} else { } else {
return false; return false
} }
} }
function checkChangeType (req, requestType) {
function checkChangeType(req, requestType) {
return (req.persistentSearch.value.changeTypes & return (req.persistentSearch.value.changeTypes &
getOperationType(requestType)); getOperationType(requestType))
} }
/// --- Exports
///--- Exports
module.exports = { module.exports = {
PersistentSearchCache: PersistentSearch, PersistentSearchCache: PersistentSearch,
checkChangeType: checkChangeType, checkChangeType: checkChangeType,
getEntryChangeNotificationControl: getEntryChangeNotificationControl getEntryChangeNotificationControl: getEntryChangeNotificationControl
}; }

View File

@ -1,6 +1,5 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // Copyright 2011 Mark Cavage, Inc. All rights reserved.
module.exports = { module.exports = {
// Misc // Misc
@ -51,4 +50,4 @@ module.exports = {
LDAP_REP_MODRDN: 0x6d, LDAP_REP_MODRDN: 0x6d,
LDAP_REP_COMPARE: 0x6f, LDAP_REP_COMPARE: 0x6f,
LDAP_REP_EXTENSION: 0x78 LDAP_REP_EXTENSION: 0x78
}; }

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +1,66 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. 'use strict'
var querystring = require('querystring');
var url = require('url');
var util = require('util');
var dn = require('./dn');
var filter = require('./filters/index');
const querystring = require('querystring')
const url = require('url')
const dn = require('./dn')
const filter = require('./filters/')
module.exports = { module.exports = {
parse: function (urlStr, parseDN) { parse: function (urlStr, parseDN) {
var u = url.parse(urlStr); const parsedURL = new url.URL(urlStr)
if (!u.protocol || !(u.protocol === 'ldap:' || u.protocol === 'ldaps:')) if (!parsedURL.protocol || !(parsedURL.protocol === 'ldap:' || parsedURL.protocol === 'ldaps:')) { throw new TypeError(urlStr + ' is an invalid LDAP url (protocol)') }
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.secure = (u.protocol === 'ldaps:')
u.hostname = 'localhost';
if (!u.hostname) { u.hostname = 'localhost' }
if (!u.port) { if (!u.port) {
u.port = (u.secure ? 636 : 389); u.port = (u.secure ? 636 : 389)
} else { } else {
u.port = parseInt(u.port, 10); u.port = parseInt(u.port, 10)
} }
if (u.pathname) { if (u.pathname) {
u.pathname = querystring.unescape(u.pathname.substr(1)); u.pathname = querystring.unescape(u.pathname.substr(1))
u.DN = parseDN ? dn.parse(u.pathname) : u.pathname; u.DN = parseDN ? dn.parse(u.pathname) : u.pathname
} }
if (u.search) { if (u.search) {
u.attributes = []; u.attributes = []
var tmp = u.search.substr(1).split('?'); var tmp = u.search.substr(1).split('?')
if (tmp && tmp.length) { if (tmp && tmp.length) {
if (tmp[0]) { if (tmp[0]) {
tmp[0].split(',').forEach(function (a) { 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]) {
if (tmp[1] !== 'base' && tmp[1] !== 'one' && tmp[1] !== 'sub') if (tmp[1] !== 'base' && tmp[1] !== 'one' && tmp[1] !== 'sub') { throw new TypeError(urlStr + ' is an invalid LDAP url (scope)') }
throw new TypeError(urlStr + ' is an invalid LDAP url (scope)'); u.scope = tmp[1]
u.scope = tmp[1];
} }
if (tmp[2]) { if (tmp[2]) {
u.filter = querystring.unescape(tmp[2]); u.filter = querystring.unescape(tmp[2])
} }
if (tmp[3]) { if (tmp[3]) {
u.extensions = querystring.unescape(tmp[3]); u.extensions = querystring.unescape(tmp[3])
} }
if (!u.scope) if (!u.scope) { u.scope = 'base' }
u.scope = 'base'; if (!u.filter) { u.filter = filter.parseString('(objectclass=*)') } else { u.filter = filter.parseString(u.filter) }
if (!u.filter)
u.filter = filter.parseString('(objectclass=*)');
else
u.filter = filter.parseString(u.filter);
} }
return u; return u
} }
}; }

View File

@ -40,6 +40,9 @@
"verror": "^1.8.1" "verror": "^1.8.1"
}, },
"devDependencies": { "devDependencies": {
"husky": "^3.0.4",
"snazzy": "^8.0.0",
"standard": "^14.0.2",
"tap": "^14.6.1", "tap": "^14.6.1",
"uuid": "^3.3.3" "uuid": "^3.3.3"
}, },
@ -47,6 +50,13 @@
"test": "tap --no-cov 'test/**/*.test.js'", "test": "tap --no-cov 'test/**/*.test.js'",
"test:cov": "tap 'test/**/*.test.js'", "test:cov": "tap 'test/**/*.test.js'",
"test:cov:html": "tap --coverage-report=html '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"
}
} }
} }

View File

@ -1,163 +1,163 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { Attribute } = require('../lib'); const { Attribute } = require('../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new Attribute()); t.ok(new Attribute())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const attr = new Attribute({ let attr = new Attribute({
type: 'cn', type: 'cn',
vals: ['foo', 'bar'] vals: ['foo', 'bar']
}); })
t.ok(attr); t.ok(attr)
attr.addValue('baz'); attr.addValue('baz')
t.equal(attr.type, 'cn'); t.equal(attr.type, 'cn')
t.equal(attr.vals.length, 3); t.equal(attr.vals.length, 3)
t.equal(attr.vals[0], 'foo'); t.equal(attr.vals[0], 'foo')
t.equal(attr.vals[1], 'bar'); t.equal(attr.vals[1], 'bar')
t.equal(attr.vals[2], 'baz'); t.equal(attr.vals[2], 'baz')
t.throws(function () { t.throws(function () {
attr = new Attribute('not an object'); attr = new Attribute('not an object')
}); })
t.throws(function () { t.throws(function () {
const typeThatIsNotAString = 1; const typeThatIsNotAString = 1
attr = new Attribute({ attr = new Attribute({
type: typeThatIsNotAString type: typeThatIsNotAString
}); })
}); })
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const attr = new Attribute({ const attr = new Attribute({
type: 'cn', type: 'cn',
vals: ['foo', 'bar'] vals: ['foo', 'bar']
}); })
t.ok(attr); t.ok(attr)
const ber = new BerWriter(); const ber = new BerWriter()
attr.toBer(ber); attr.toBer(ber)
const reader = new BerReader(ber.buffer); const reader = new BerReader(ber.buffer)
t.ok(reader.readSequence()); t.ok(reader.readSequence())
t.equal(reader.readString(), 'cn'); t.equal(reader.readString(), 'cn')
t.equal(reader.readSequence(), 0x31); // lber set t.equal(reader.readSequence(), 0x31) // lber set
t.equal(reader.readString(), 'foo'); t.equal(reader.readString(), 'foo')
t.equal(reader.readString(), 'bar'); t.equal(reader.readString(), 'bar')
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.startSequence(); ber.startSequence()
ber.writeString('cn'); ber.writeString('cn')
ber.startSequence(0x31); ber.startSequence(0x31)
ber.writeStringArray(['foo', 'bar']); ber.writeStringArray(['foo', 'bar'])
ber.endSequence(); ber.endSequence()
ber.endSequence(); ber.endSequence()
const attr = new Attribute(); const attr = new Attribute()
t.ok(attr); t.ok(attr)
t.ok(attr.parse(new BerReader(ber.buffer))); t.ok(attr.parse(new BerReader(ber.buffer)))
t.equal(attr.type, 'cn'); t.equal(attr.type, 'cn')
t.equal(attr.vals.length, 2); t.equal(attr.vals.length, 2)
t.equal(attr.vals[0], 'foo'); t.equal(attr.vals[0], 'foo')
t.equal(attr.vals[1], 'bar'); t.equal(attr.vals[1], 'bar')
t.end(); t.end()
}); })
test('parse - without 0x31', function (t) { test('parse - without 0x31', function (t) {
const ber = new BerWriter; const ber = new BerWriter()
ber.startSequence(); ber.startSequence()
ber.writeString('sn'); ber.writeString('sn')
ber.endSequence(); ber.endSequence()
const attr = new Attribute; const attr = new Attribute()
t.ok(attr); t.ok(attr)
t.ok(attr.parse(new BerReader(ber.buffer))); t.ok(attr.parse(new BerReader(ber.buffer)))
t.equal(attr.type, 'sn'); t.equal(attr.type, 'sn')
t.equal(attr.vals.length, 0); t.equal(attr.vals.length, 0)
t.end(); t.end()
}); })
test('toString', function (t) { test('toString', function (t) {
const attr = new Attribute({ const attr = new Attribute({
type: 'foobar', type: 'foobar',
vals: ['asdf'] vals: ['asdf']
}); })
const expected = attr.toString(); const expected = attr.toString()
const actual = JSON.stringify(attr.json); const actual = JSON.stringify(attr.json)
t.equal(actual, expected); t.equal(actual, expected)
t.end(); t.end()
}); })
test('isAttribute', function (t) { test('isAttribute', function (t) {
const isA = Attribute.isAttribute; const isA = Attribute.isAttribute
t.notOk(isA(null)); t.notOk(isA(null))
t.notOk(isA('asdf')); t.notOk(isA('asdf'))
t.ok(isA(new Attribute({ t.ok(isA(new Attribute({
type: 'foobar', type: 'foobar',
vals: ['asdf'] vals: ['asdf']
}))); })))
t.ok(isA({ t.ok(isA({
type: 'foo', type: 'foo',
vals: ['item', Buffer.alloc(5)], vals: ['item', Buffer.alloc(5)],
toBer: function () { /* placeholder */ } toBer: function () { /* placeholder */ }
})); }))
// bad type in vals // bad type in vals
t.notOk(isA({ t.notOk(isA({
type: 'foo', type: 'foo',
vals: ['item', null], vals: ['item', null],
toBer: function () { /* placeholder */ } toBer: function () { /* placeholder */ }
})); }))
t.end(); t.end()
}); })
test('compare', function (t) { test('compare', function (t) {
const comp = Attribute.compare; const comp = Attribute.compare
const a = new Attribute({ const a = new Attribute({
type: 'foo', type: 'foo',
vals: ['bar'] vals: ['bar']
}); })
const b = new Attribute({ const b = new Attribute({
type: 'foo', type: 'foo',
vals: ['bar'] vals: ['bar']
}); })
const notAnAttribute = 'this is not an attribute'; const notAnAttribute = 'this is not an attribute'
t.throws(function () { t.throws(function () {
comp(a, notAnAttribute); comp(a, notAnAttribute)
}); })
t.throws(function () { t.throws(function () {
comp(notAnAttribute, b); comp(notAnAttribute, b)
}); })
t.equal(comp(a, b), 0); t.equal(comp(a, b), 0)
// Different types // Different types
a.type = 'boo'; a.type = 'boo'
t.equal(comp(a, b), -1); t.equal(comp(a, b), -1)
t.equal(comp(b, a), 1); t.equal(comp(b, a), 1)
a.type = 'foo'; a.type = 'foo'
// Different value counts // Different value counts
a.vals = ['bar', 'baz']; a.vals = ['bar', 'baz']
t.equal(comp(a, b), 1); t.equal(comp(a, b), 1)
t.equal(comp(b, a), -1); t.equal(comp(b, a), -1)
// Different value contents (same count) // Different value contents (same count)
a.vals = ['baz']; a.vals = ['baz']
t.equal(comp(a, b), 1); t.equal(comp(a, b), 1)
t.equal(comp(b, a), -1); t.equal(comp(b, a), -1)
t.end(); t.end()
}); })

View File

@ -1,13 +1,13 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { Attribute, Change } = require('../lib'); const { Attribute, Change } = require('../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new Change()); t.ok(new Change())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const change = new Change({ const change = new Change({
@ -16,33 +16,33 @@ test('new with args', function (t) {
type: 'cn', type: 'cn',
vals: ['foo', 'bar'] vals: ['foo', 'bar']
}) })
}); })
t.ok(change); t.ok(change)
t.equal(change.operation, 'add'); t.equal(change.operation, 'add')
t.equal(change.modification.type, 'cn'); t.equal(change.modification.type, 'cn')
t.equal(change.modification.vals.length, 2); t.equal(change.modification.vals.length, 2)
t.equal(change.modification.vals[0], 'foo'); t.equal(change.modification.vals[0], 'foo')
t.equal(change.modification.vals[1], 'bar'); t.equal(change.modification.vals[1], 'bar')
t.end(); t.end()
}); })
test('validate fields', function (t) { test('validate fields', function (t) {
const c = new Change(); const c = new Change()
t.ok(c); t.ok(c)
t.throws(function () { t.throws(function () {
c.operation = 'bogus'; c.operation = 'bogus'
}); })
t.throws(function () { t.throws(function () {
c.modification = {too: 'many', fields: 'here'}; c.modification = { too: 'many', fields: 'here' }
}); })
c.modification = { c.modification = {
foo: ['bar', 'baz'] foo: ['bar', 'baz']
}; }
t.ok(c.modification); t.ok(c.modification)
t.end(); t.end()
}); })
test('GH-31 (multiple attributes per Change)', function (t) { test('GH-31 (multiple attributes per Change)', function (t) {
t.throws(function () { t.throws(function () {
@ -52,11 +52,11 @@ test('GH-31 (multiple attributes per Change)', function (t) {
cn: 'foo', cn: 'foo',
sn: 'bar' sn: 'bar'
} }
}); })
t.notOk(c); t.notOk(c)
}); })
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const change = new Change({ const change = new Change({
@ -65,168 +65,167 @@ test('toBer', function (t) {
type: 'cn', type: 'cn',
vals: ['foo', 'bar'] vals: ['foo', 'bar']
}) })
}); })
t.ok(change); t.ok(change)
const ber = new BerWriter(); const ber = new BerWriter()
change.toBer(ber); change.toBer(ber)
const reader = new BerReader(ber.buffer); const reader = new BerReader(ber.buffer)
t.ok(reader.readSequence()); t.ok(reader.readSequence())
t.equal(reader.readEnumeration(), 0x00); t.equal(reader.readEnumeration(), 0x00)
t.ok(reader.readSequence()); t.ok(reader.readSequence())
t.equal(reader.readString(), 'cn'); t.equal(reader.readString(), 'cn')
t.equal(reader.readSequence(), 0x31); // lber set t.equal(reader.readSequence(), 0x31) // lber set
t.equal(reader.readString(), 'foo'); t.equal(reader.readString(), 'foo')
t.equal(reader.readString(), 'bar'); t.equal(reader.readString(), 'bar')
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.startSequence(); ber.startSequence()
ber.writeEnumeration(0x00); ber.writeEnumeration(0x00)
ber.startSequence(); ber.startSequence()
ber.writeString('cn'); ber.writeString('cn')
ber.startSequence(0x31); ber.startSequence(0x31)
ber.writeStringArray(['foo', 'bar']); ber.writeStringArray(['foo', 'bar'])
ber.endSequence(); ber.endSequence()
ber.endSequence(); ber.endSequence()
ber.endSequence(); ber.endSequence()
const change = new Change(); const change = new Change()
t.ok(change); t.ok(change)
t.ok(change.parse(new BerReader(ber.buffer))); t.ok(change.parse(new BerReader(ber.buffer)))
t.equal(change.operation, 'add'); t.equal(change.operation, 'add')
t.equal(change.modification.type, 'cn'); t.equal(change.modification.type, 'cn')
t.equal(change.modification.vals.length, 2); t.equal(change.modification.vals.length, 2)
t.equal(change.modification.vals[0], 'foo'); t.equal(change.modification.vals[0], 'foo')
t.equal(change.modification.vals[1], 'bar'); t.equal(change.modification.vals[1], 'bar')
t.end(); t.end()
}); })
test('apply - replace', function (t) { test('apply - replace', function (t) {
let res; let res
const single = new Change({ const single = new Change({
operation: 'replace', operation: 'replace',
modification: { modification: {
type: 'cn', type: 'cn',
vals: ['new'] vals: ['new']
} }
}); })
const twin = new Change({ const twin = new Change({
operation: 'replace', operation: 'replace',
modification: { modification: {
type: 'cn', type: 'cn',
vals: ['new', 'two'] vals: ['new', 'two']
} }
}); })
const empty = new Change({ const empty = new Change({
operation: 'replace', operation: 'replace',
modification: { modification: {
type: 'cn', type: 'cn',
vals: [] vals: []
} }
}); })
// plain // plain
res = Change.apply(single, { cn: ['old'] }); res = Change.apply(single, { cn: ['old'] })
t.deepEqual(res.cn, ['new']); t.deepEqual(res.cn, ['new'])
// multiple // multiple
res = Change.apply(single, { cn: ['old', 'also'] }); res = Change.apply(single, { cn: ['old', 'also'] })
t.deepEqual(res.cn, ['new']); t.deepEqual(res.cn, ['new'])
// empty // empty
res = Change.apply(empty, { cn: ['existing'] }); res = Change.apply(empty, { cn: ['existing'] })
t.equal(res.cn, undefined); t.equal(res.cn, undefined)
t.ok(Object.keys(res).indexOf('cn') === -1); t.ok(Object.keys(res).indexOf('cn') === -1)
//absent // absent
res = Change.apply(single, { dn: ['otherjunk'] }); res = Change.apply(single, { dn: ['otherjunk'] })
t.deepEqual(res.cn, ['new']); t.deepEqual(res.cn, ['new'])
// scalar formatting "success" // scalar formatting "success"
res = Change.apply(single, { cn: 'old' }, true); res = Change.apply(single, { cn: 'old' }, true)
t.equal(res.cn, 'new'); t.equal(res.cn, 'new')
// scalar formatting "failure" // scalar formatting "failure"
res = Change.apply(twin, { cn: 'old' }, true); res = Change.apply(twin, { cn: 'old' }, true)
t.deepEqual(res.cn, ['new', 'two']); t.deepEqual(res.cn, ['new', 'two'])
t.end(); t.end()
}); })
test('apply - add', function (t) { test('apply - add', function (t) {
let res; let res
const single = new Change({ const single = new Change({
operation: 'add', operation: 'add',
modification: { modification: {
type: 'cn', type: 'cn',
vals: ['new'] vals: ['new']
} }
}); })
// plain // plain
res = Change.apply(single, { cn: ['old'] }); res = Change.apply(single, { cn: ['old'] })
t.deepEqual(res.cn, ['old', 'new']); t.deepEqual(res.cn, ['old', 'new'])
// multiple // multiple
res = Change.apply(single, { cn: ['old', 'also'] }); res = Change.apply(single, { cn: ['old', 'also'] })
t.deepEqual(res.cn, ['old', 'also', 'new']); t.deepEqual(res.cn, ['old', 'also', 'new'])
//absent // absent
res = Change.apply(single, { dn: ['otherjunk'] }); res = Change.apply(single, { dn: ['otherjunk'] })
t.deepEqual(res.cn, ['new']); t.deepEqual(res.cn, ['new'])
// scalar formatting "success" // scalar formatting "success"
res = Change.apply(single, { }, true); res = Change.apply(single, { }, true)
t.equal(res.cn, 'new'); t.equal(res.cn, 'new')
// scalar formatting "failure" // scalar formatting "failure"
res = Change.apply(single, { cn: 'old' }, true); res = Change.apply(single, { cn: 'old' }, true)
t.deepEqual(res.cn, ['old', 'new']); t.deepEqual(res.cn, ['old', 'new'])
// duplicate add // duplicate add
res = Change.apply(single, { cn: 'new' }); res = Change.apply(single, { cn: 'new' })
t.deepEqual(res.cn, ['new']); t.deepEqual(res.cn, ['new'])
t.end(); t.end()
}); })
test('apply - delete', function (t) { test('apply - delete', function (t) {
let res; let res
const single = new Change({ const single = new Change({
operation: 'delete', operation: 'delete',
modification: { modification: {
type: 'cn', type: 'cn',
vals: ['old'] vals: ['old']
} }
}); })
// plain // plain
res = Change.apply(single, { cn: ['old', 'new'] }); res = Change.apply(single, { cn: ['old', 'new'] })
t.deepEqual(res.cn, ['new']); t.deepEqual(res.cn, ['new'])
// empty // empty
res = Change.apply(single, { cn: ['old'] }); res = Change.apply(single, { cn: ['old'] })
t.equal(res.cn, undefined); t.equal(res.cn, undefined)
t.ok(Object.keys(res).indexOf('cn') === -1); t.ok(Object.keys(res).indexOf('cn') === -1)
// scalar formatting "success" // scalar formatting "success"
res = Change.apply(single, { cn: ['old', 'one'] }, true); res = Change.apply(single, { cn: ['old', 'one'] }, true)
t.equal(res.cn, 'one'); t.equal(res.cn, 'one')
// scalar formatting "failure" // scalar formatting "failure"
res = Change.apply(single, { cn: ['old', 'several', 'items'] }, true); res = Change.apply(single, { cn: ['old', 'several', 'items'] }, true)
t.deepEqual(res.cn, ['several', 'items']); t.deepEqual(res.cn, ['several', 'items'])
// absent
res = Change.apply(single, { dn: ['otherjunk'] })
t.ok(res)
t.equal(res.cn, undefined)
//absent t.end()
res = Change.apply(single, { dn: ['otherjunk'] }); })
t.ok(res);
t.equal(res.cn, undefined);
t.end();
});

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +1,53 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { Control, getControl } = require('../../lib'); const { Control, getControl } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new Control()); t.ok(new Control())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const c = new Control({ const c = new Control({
type: '2.16.840.1.113730.3.4.2', type: '2.16.840.1.113730.3.4.2',
criticality: true criticality: true
}); })
t.ok(c); t.ok(c)
t.equal(c.type, '2.16.840.1.113730.3.4.2'); t.equal(c.type, '2.16.840.1.113730.3.4.2')
t.ok(c.criticality); t.ok(c.criticality)
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.startSequence(); ber.startSequence()
ber.writeString('2.16.840.1.113730.3.4.2'); ber.writeString('2.16.840.1.113730.3.4.2')
ber.writeBoolean(true); ber.writeBoolean(true)
ber.writeString('foo'); ber.writeString('foo')
ber.endSequence(); ber.endSequence()
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '2.16.840.1.113730.3.4.2'); t.equal(c.type, '2.16.840.1.113730.3.4.2')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.toString('utf8'), 'foo'); t.equal(c.value.toString('utf8'), 'foo')
t.end(); t.end()
}); })
test('parse no value', function (t) { test('parse no value', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.startSequence(); ber.startSequence()
ber.writeString('2.16.840.1.113730.3.4.2'); ber.writeString('2.16.840.1.113730.3.4.2')
ber.endSequence(); ber.endSequence()
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '2.16.840.1.113730.3.4.2'); t.equal(c.type, '2.16.840.1.113730.3.4.2')
t.equal(c.criticality, false); t.equal(c.criticality, false)
t.notOk(c.value, null); t.notOk(c.value, null)
t.end(); t.end()
}); })

View File

@ -1,13 +1,13 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { getControl, EntryChangeNotificationControl } = require('../../lib'); const { getControl, EntryChangeNotificationControl } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new EntryChangeNotificationControl()); t.ok(new EntryChangeNotificationControl())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const c = new EntryChangeNotificationControl({ const c = new EntryChangeNotificationControl({
@ -18,27 +18,27 @@ test('new with args', function (t) {
previousDN: 'cn=foobarbazcar', previousDN: 'cn=foobarbazcar',
changeNumber: 123456789 changeNumber: 123456789
} }
}); })
t.ok(c); t.ok(c)
t.equal(c.type, '2.16.840.1.113730.3.4.7'); t.equal(c.type, '2.16.840.1.113730.3.4.7')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.changeType, 8); t.equal(c.value.changeType, 8)
t.equal(c.value.previousDN, 'cn=foobarbazcar'); t.equal(c.value.previousDN, 'cn=foobarbazcar')
t.equal(c.value.changeNumber, 123456789); t.equal(c.value.changeNumber, 123456789)
const writer = new BerWriter(); const writer = new BerWriter()
c.toBer(writer); c.toBer(writer)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
const psc = getControl(reader); const psc = getControl(reader)
t.ok(psc); t.ok(psc)
t.equal(psc.type, '2.16.840.1.113730.3.4.7'); t.equal(psc.type, '2.16.840.1.113730.3.4.7')
t.ok(psc.criticality); t.ok(psc.criticality)
t.equal(psc.value.changeType, 8); t.equal(psc.value.changeType, 8)
t.equal(psc.value.previousDN, 'cn=foobarbazcar'); t.equal(psc.value.previousDN, 'cn=foobarbazcar')
t.equal(psc.value.changeNumber, 123456789); t.equal(psc.value.changeNumber, 123456789)
t.end(); t.end()
}); })
test('tober', function (t) { test('tober', function (t) {
const psc = new EntryChangeNotificationControl({ const psc = new EntryChangeNotificationControl({
@ -49,18 +49,18 @@ test('tober', function (t) {
previousDN: 'cn=foobarbazcar', previousDN: 'cn=foobarbazcar',
changeNumber: 123456789 changeNumber: 123456789
} }
}); })
const ber = new BerWriter(); const ber = new BerWriter()
psc.toBer(ber); psc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '2.16.840.1.113730.3.4.7'); t.equal(c.type, '2.16.840.1.113730.3.4.7')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.changeType, 8); t.equal(c.value.changeType, 8)
t.equal(c.value.previousDN, 'cn=foobarbazcar'); t.equal(c.value.previousDN, 'cn=foobarbazcar')
t.equal(c.value.changeNumber, 123456789); t.equal(c.value.changeNumber, 123456789)
t.end(); t.end()
}); })

View File

@ -1,13 +1,13 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { getControl, PagedResultsControl } = require('../../lib'); const { getControl, PagedResultsControl } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new PagedResultsControl()); t.ok(new PagedResultsControl())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const c = new PagedResultsControl({ const c = new PagedResultsControl({
@ -17,25 +17,25 @@ test('new with args', function (t) {
size: 1000, size: 1000,
cookie: Buffer.from([1, 2, 3]) cookie: Buffer.from([1, 2, 3])
} }
}); })
t.ok(c); t.ok(c)
t.equal(c.type, '1.2.840.113556.1.4.319'); t.equal(c.type, '1.2.840.113556.1.4.319')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.size, 1000); t.equal(c.value.size, 1000)
t.is(Buffer.compare(c.value.cookie, Buffer.from([1, 2, 3])), 0) t.is(Buffer.compare(c.value.cookie, Buffer.from([1, 2, 3])), 0)
const writer = new BerWriter(); const writer = new BerWriter()
c.toBer(writer); c.toBer(writer)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
const psc = getControl(reader); const psc = getControl(reader)
t.ok(psc); t.ok(psc)
t.equal(psc.type, '1.2.840.113556.1.4.319'); t.equal(psc.type, '1.2.840.113556.1.4.319')
t.ok(psc.criticality); t.ok(psc.criticality)
t.equal(psc.value.size, 1000); t.equal(psc.value.size, 1000)
t.is(Buffer.compare(psc.value.cookie, Buffer.from([1, 2, 3])), 0) t.is(Buffer.compare(psc.value.cookie, Buffer.from([1, 2, 3])), 0)
t.end(); t.end()
}); })
test('tober', function (t) { test('tober', function (t) {
const psc = new PagedResultsControl({ const psc = new PagedResultsControl({
@ -45,17 +45,17 @@ test('tober', function (t) {
size: 20, size: 20,
cookie: Buffer.alloc(0) cookie: Buffer.alloc(0)
} }
}); })
const ber = new BerWriter(); const ber = new BerWriter()
psc.toBer(ber); psc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '1.2.840.113556.1.4.319'); t.equal(c.type, '1.2.840.113556.1.4.319')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.size, 20); t.equal(c.value.size, 20)
t.is(Buffer.compare(c.value.cookie, Buffer.alloc(0)), 0) t.is(Buffer.compare(c.value.cookie, Buffer.alloc(0)), 0)
t.end(); t.end()
}); })

View File

@ -1,32 +1,28 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved. // 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 BerReader = asn1.BerReader
var BerWriter = asn1.BerWriter; var BerWriter = asn1.BerWriter
var getControl; var getControl
var PersistentSearchControl; var PersistentSearchControl
/// --- Tests
///--- Tests
test('load library', function (t) { test('load library', function (t) {
PersistentSearchControl = require('../../lib').PersistentSearchControl; PersistentSearchControl = require('../../lib').PersistentSearchControl
t.ok(PersistentSearchControl); t.ok(PersistentSearchControl)
getControl = require('../../lib').getControl; getControl = require('../../lib').getControl
t.ok(getControl); t.ok(getControl)
t.end(); t.end()
}); })
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new PersistentSearchControl()); t.ok(new PersistentSearchControl())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
var c = new PersistentSearchControl({ var c = new PersistentSearchControl({
@ -37,47 +33,46 @@ test('new with args', function (t) {
changesOnly: false, changesOnly: false,
returnECs: false returnECs: false
} }
}); })
t.ok(c); t.ok(c)
t.equal(c.type, '2.16.840.1.113730.3.4.3'); t.equal(c.type, '2.16.840.1.113730.3.4.3')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.changeTypes, 15); t.equal(c.value.changeTypes, 15)
t.equal(c.value.changesOnly, false); t.equal(c.value.changesOnly, false)
t.equal(c.value.returnECs, 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(); t.end()
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();
});
test('getControl with args', function (t) { test('getControl with args', function (t) {
var buf = Buffer.from([ var buf = Buffer.from([
0x30, 0x26, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x30, 0x26, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30,
0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e,
0x34, 0x2e, 0x33, 0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01, 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 ber = new BerReader(buf)
var psc = getControl(ber); var psc = getControl(ber)
t.ok(psc); t.ok(psc)
t.equal(psc.type, '2.16.840.1.113730.3.4.3'); t.equal(psc.type, '2.16.840.1.113730.3.4.3')
t.equal(psc.criticality, false); t.equal(psc.criticality, false)
t.equal(psc.value.changeTypes, 15); t.equal(psc.value.changeTypes, 15)
t.equal(psc.value.changesOnly, true); t.equal(psc.value.changesOnly, true)
t.equal(psc.value.returnECs, true); t.equal(psc.value.returnECs, true)
t.end(); t.end()
}); })
test('tober', function (t) { test('tober', function (t) {
var psc = new PersistentSearchControl({ var psc = new PersistentSearchControl({
@ -88,17 +83,17 @@ test('tober', function (t) {
changesOnly: false, changesOnly: false,
returnECs: false returnECs: false
} }
}); })
var ber = new BerWriter(); var ber = new BerWriter()
psc.toBer(ber); psc.toBer(ber)
var c = getControl(new BerReader(ber.buffer)); var c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '2.16.840.1.113730.3.4.3'); t.equal(c.type, '2.16.840.1.113730.3.4.3')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.changeTypes, 15); t.equal(c.value.changeTypes, 15)
t.equal(c.value.changesOnly, false); t.equal(c.value.changesOnly, false)
t.equal(c.value.returnECs, false); t.equal(c.value.returnECs, false)
t.end(); t.end()
}); })

View File

@ -1,13 +1,13 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { getControl, ServerSideSortingRequestControl: SSSRControl } = require('../../lib'); const { getControl, ServerSideSortingRequestControl: SSSRControl } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new SSSRControl()); t.ok(new SSSRControl())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const c = new SSSRControl({ const c = new SSSRControl({
@ -15,15 +15,15 @@ test('new with args', function (t) {
value: { value: {
attributeType: 'sn' attributeType: 'sn'
} }
}); })
t.ok(c); t.ok(c)
t.equal(c.type, '1.2.840.113556.1.4.473'); t.equal(c.type, '1.2.840.113556.1.4.473')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.length, 1); t.equal(c.value.length, 1)
t.equal(c.value[0].attributeType, 'sn'); t.equal(c.value[0].attributeType, 'sn')
t.end(); t.end()
}); })
test('toBer - object', function (t) { test('toBer - object', function (t) {
const sssc = new SSSRControl({ const sssc = new SSSRControl({
@ -32,21 +32,22 @@ test('toBer - object', function (t) {
attributeType: 'sn', attributeType: 'sn',
orderingRule: 'caseIgnoreOrderingMatch', orderingRule: 'caseIgnoreOrderingMatch',
reverseOrder: true reverseOrder: true
}}); }
})
const ber = new BerWriter(); const ber = new BerWriter()
sssc.toBer(ber); sssc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '1.2.840.113556.1.4.473'); t.equal(c.type, '1.2.840.113556.1.4.473')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value[0].attributeType, 'sn'); t.equal(c.value[0].attributeType, 'sn')
t.equal(c.value[0].orderingRule, 'caseIgnoreOrderingMatch'); t.equal(c.value[0].orderingRule, 'caseIgnoreOrderingMatch')
t.equal(c.value[0].reverseOrder, true); t.equal(c.value[0].reverseOrder, true)
t.end(); t.end()
}); })
test('toBer - array', function (t) { test('toBer - array', function (t) {
const sssc = new SSSRControl({ const sssc = new SSSRControl({
@ -62,33 +63,33 @@ test('toBer - array', function (t) {
orderingRule: 'caseIgnoreOrderingMatch' orderingRule: 'caseIgnoreOrderingMatch'
} }
] ]
}); })
const ber = new BerWriter(); const ber = new BerWriter()
sssc.toBer(ber); sssc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '1.2.840.113556.1.4.473'); t.equal(c.type, '1.2.840.113556.1.4.473')
t.ok(c.criticality); t.ok(c.criticality)
t.equal(c.value.length, 2); t.equal(c.value.length, 2)
t.equal(c.value[0].attributeType, 'sn'); t.equal(c.value[0].attributeType, 'sn')
t.equal(c.value[0].orderingRule, 'caseIgnoreOrderingMatch'); t.equal(c.value[0].orderingRule, 'caseIgnoreOrderingMatch')
t.equal(c.value[0].reverseOrder, true); t.equal(c.value[0].reverseOrder, true)
t.equal(c.value[1].attributeType, 'givenName'); t.equal(c.value[1].attributeType, 'givenName')
t.equal(c.value[1].orderingRule, 'caseIgnoreOrderingMatch'); t.equal(c.value[1].orderingRule, 'caseIgnoreOrderingMatch')
t.end(); t.end()
}); })
test('toBer - empty', function (t) { test('toBer - empty', function (t) {
const sssc = new SSSRControl(); const sssc = new SSSRControl()
const ber = new BerWriter(); const ber = new BerWriter()
sssc.toBer(ber); sssc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '1.2.840.113556.1.4.473'); t.equal(c.type, '1.2.840.113556.1.4.473')
t.equal(c.value.length, 0); t.equal(c.value.length, 0)
t.end(); t.end()
}); })

View File

@ -1,18 +1,18 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const ldap = require('../../lib'); const ldap = require('../../lib')
const { getControl, ServerSideSortingResponseControl: SSSResponseControl } = ldap 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) { test('new no args', function (t) {
const c = new SSSResponseControl(); const c = new SSSResponseControl()
t.ok(c); t.ok(c)
t.equal(c.type, OID); t.equal(c.type, OID)
t.equal(c.criticality, false); t.equal(c.criticality, false)
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const c = new SSSResponseControl({ const c = new SSSResponseControl({
@ -21,82 +21,85 @@ test('new with args', function (t) {
result: ldap.LDAP_SUCCESS, result: ldap.LDAP_SUCCESS,
failedAttribute: 'cn' failedAttribute: 'cn'
} }
}); })
t.ok(c); t.ok(c)
t.equal(c.type, OID); t.equal(c.type, OID)
t.equal(c.criticality, false); t.equal(c.criticality, false)
t.equal(c.value.result, ldap.LDAP_SUCCESS); t.equal(c.value.result, ldap.LDAP_SUCCESS)
t.equal(c.value.failedAttribute, 'cn'); t.equal(c.value.failedAttribute, 'cn')
t.end(); t.end()
}); })
test('toBer - success', function (t) { test('toBer - success', function (t) {
const sssc = new SSSResponseControl({ const sssc = new SSSResponseControl({
value: { value: {
result: ldap.LDAP_SUCCESS, result: ldap.LDAP_SUCCESS,
failedAttribute: 'foobar' failedAttribute: 'foobar'
}}); }
})
const ber = new BerWriter(); const ber = new BerWriter()
sssc.toBer(ber); sssc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, '1.2.840.113556.1.4.474'); t.equal(c.type, '1.2.840.113556.1.4.474')
t.equal(c.criticality, false); t.equal(c.criticality, false)
t.equal(c.value.result, ldap.LDAP_SUCCESS); t.equal(c.value.result, ldap.LDAP_SUCCESS)
t.notOk(c.value.failedAttribute); t.notOk(c.value.failedAttribute)
t.end(); t.end()
}); })
test('toBer - simple failure', function (t) { test('toBer - simple failure', function (t) {
const sssc = new SSSResponseControl({ const sssc = new SSSResponseControl({
value: { value: {
result: ldap.LDAP_NO_SUCH_ATTRIBUTE result: ldap.LDAP_NO_SUCH_ATTRIBUTE
}}); }
})
const ber = new BerWriter(); const ber = new BerWriter()
sssc.toBer(ber); sssc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, OID); t.equal(c.type, OID)
t.equal(c.criticality, false); t.equal(c.criticality, false)
t.equal(c.value.result, ldap.LDAP_NO_SUCH_ATTRIBUTE); t.equal(c.value.result, ldap.LDAP_NO_SUCH_ATTRIBUTE)
t.notOk(c.value.failedAttribute); t.notOk(c.value.failedAttribute)
t.end(); t.end()
}); })
test('toBer - detailed failure', function (t) { test('toBer - detailed failure', function (t) {
const sssc = new SSSResponseControl({ const sssc = new SSSResponseControl({
value: { value: {
result: ldap.LDAP_NO_SUCH_ATTRIBUTE, result: ldap.LDAP_NO_SUCH_ATTRIBUTE,
failedAttribute: 'foobar' failedAttribute: 'foobar'
}}); }
})
const ber = new BerWriter(); const ber = new BerWriter()
sssc.toBer(ber); sssc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, OID); t.equal(c.type, OID)
t.equal(c.criticality, false); t.equal(c.criticality, false)
t.equal(c.value.result, ldap.LDAP_NO_SUCH_ATTRIBUTE); t.equal(c.value.result, ldap.LDAP_NO_SUCH_ATTRIBUTE)
t.equal(c.value.failedAttribute, 'foobar'); t.equal(c.value.failedAttribute, 'foobar')
t.end(); t.end()
}); })
test('toBer - empty', function (t) { test('toBer - empty', function (t) {
const sssc = new SSSResponseControl(); const sssc = new SSSResponseControl()
const ber = new BerWriter(); const ber = new BerWriter()
sssc.toBer(ber); sssc.toBer(ber)
const c = getControl(new BerReader(ber.buffer)); const c = getControl(new BerReader(ber.buffer))
t.ok(c); t.ok(c)
t.equal(c.type, OID); t.equal(c.type, OID)
t.equal(c.criticality, false); t.equal(c.criticality, false)
t.notOk(c.value.result); t.notOk(c.value.result)
t.notOk(c.value.failedAttribute); t.notOk(c.value.failedAttribute)
t.end(); t.end()
}); })

View File

@ -1,234 +1,234 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { dn } = require('../lib'); const { dn } = require('../lib')
test('parse basic', function (t) { test('parse basic', function (t) {
const DN_STR = 'cn=mark, ou=people, o=joyent'; const DN_STR = 'cn=mark, ou=people, o=joyent'
const name = dn.parse(DN_STR); const name = dn.parse(DN_STR)
t.ok(name); t.ok(name)
t.ok(name.rdns); t.ok(name.rdns)
t.ok(Array.isArray(name.rdns)); t.ok(Array.isArray(name.rdns))
t.equal(3, name.rdns.length); t.equal(3, name.rdns.length)
name.rdns.forEach(function (rdn) { name.rdns.forEach(function (rdn) {
t.equal('object', typeof (rdn)); t.equal('object', typeof (rdn))
}); })
t.equal(name.toString(), DN_STR); t.equal(name.toString(), DN_STR)
t.end(); t.end()
}); })
test('parse escaped', function (t) { test('parse escaped', function (t) {
const DN_STR = 'cn=m\\,ark, ou=people, o=joyent'; const DN_STR = 'cn=m\\,ark, ou=people, o=joyent'
const name = dn.parse(DN_STR); const name = dn.parse(DN_STR)
t.ok(name); t.ok(name)
t.ok(name.rdns); t.ok(name.rdns)
t.ok(Array.isArray(name.rdns)); t.ok(Array.isArray(name.rdns))
t.equal(3, name.rdns.length); t.equal(3, name.rdns.length)
name.rdns.forEach(function (rdn) { name.rdns.forEach(function (rdn) {
t.equal('object', typeof (rdn)); t.equal('object', typeof (rdn))
}); })
t.equal(name.toString(), DN_STR); t.equal(name.toString(), DN_STR)
t.end(); t.end()
}); })
test('parse compound', function (t) { test('parse compound', function (t) {
const DN_STR = 'cn=mark+sn=cavage, ou=people, o=joyent'; const DN_STR = 'cn=mark+sn=cavage, ou=people, o=joyent'
const name = dn.parse(DN_STR); const name = dn.parse(DN_STR)
t.ok(name); t.ok(name)
t.ok(name.rdns); t.ok(name.rdns)
t.ok(Array.isArray(name.rdns)); t.ok(Array.isArray(name.rdns))
t.equal(3, name.rdns.length); t.equal(3, name.rdns.length)
name.rdns.forEach(function (rdn) { name.rdns.forEach(function (rdn) {
t.equal('object', typeof (rdn)); t.equal('object', typeof (rdn))
}); })
t.equal(name.toString(), DN_STR); t.equal(name.toString(), DN_STR)
t.end(); t.end()
}); })
test('parse quoted', function (t) { test('parse quoted', function (t) {
const DN_STR = 'cn="mark+sn=cavage", ou=people, o=joyent'; const DN_STR = 'cn="mark+sn=cavage", ou=people, o=joyent'
const ESCAPE_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); const name = dn.parse(DN_STR)
t.ok(name); t.ok(name)
t.ok(name.rdns); t.ok(name.rdns)
t.ok(Array.isArray(name.rdns)); t.ok(Array.isArray(name.rdns))
t.equal(3, name.rdns.length); t.equal(3, name.rdns.length)
name.rdns.forEach(function (rdn) { name.rdns.forEach(function (rdn) {
t.equal('object', typeof (rdn)); t.equal('object', typeof (rdn))
}); })
t.equal(name.toString(), ESCAPE_STR); t.equal(name.toString(), ESCAPE_STR)
t.end(); t.end()
}); })
test('equals', function (t) { test('equals', function (t) {
const dn1 = dn.parse('cn=foo,dc=bar'); const dn1 = dn.parse('cn=foo,dc=bar')
t.ok(dn1.equals('cn=foo,dc=bar')); t.ok(dn1.equals('cn=foo,dc=bar'))
t.ok(!dn1.equals('cn=foo1,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=foo,dc=bar')))
t.ok(!dn1.equals(dn.parse('cn=foo2,dc=bar'))); t.ok(!dn1.equals(dn.parse('cn=foo2,dc=bar')))
t.end(); t.end()
}); })
test('child of', function (t) { test('child of', function (t) {
const dn1 = dn.parse('cn=foo,dc=bar'); const dn1 = dn.parse('cn=foo,dc=bar')
t.ok(dn1.childOf('dc=bar')); t.ok(dn1.childOf('dc=bar'))
t.ok(!dn1.childOf('dc=moo')); t.ok(!dn1.childOf('dc=moo'))
t.ok(!dn1.childOf('dc=foo')); t.ok(!dn1.childOf('dc=foo'))
t.ok(!dn1.childOf('cn=foo,dc=bar')); t.ok(!dn1.childOf('cn=foo,dc=bar'))
t.ok(dn1.childOf(dn.parse('dc=bar'))); t.ok(dn1.childOf(dn.parse('dc=bar')))
t.end(); t.end()
}); })
test('parent of', function (t) { test('parent of', function (t) {
const dn1 = dn.parse('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=foo,dc=bar'))
t.ok(!dn1.parentOf('cn=moo,cn=bar,dc=foo')); t.ok(!dn1.parentOf('cn=moo,cn=bar,dc=foo'))
t.ok(!dn1.parentOf('cn=foo,dc=bar')); t.ok(!dn1.parentOf('cn=foo,dc=bar'))
t.ok(dn1.parentOf(dn.parse('cn=moo,cn=foo,dc=bar'))); t.ok(dn1.parentOf(dn.parse('cn=moo,cn=foo,dc=bar')))
t.end(); t.end()
}); })
test('DN parent', function (t) { test('DN parent', function (t) {
const _dn = dn.parse('cn=foo,ou=bar'); const _dn = dn.parse('cn=foo,ou=bar')
const parent1 = _dn.parent(); const parent1 = _dn.parent()
const parent2 = parent1.parent(); const parent2 = parent1.parent()
t.ok(parent1.equals('ou=bar')); t.ok(parent1.equals('ou=bar'))
t.ok(parent2.equals('')); t.ok(parent2.equals(''))
t.equal(parent2.parent(), null); t.equal(parent2.parent(), null)
t.end(); t.end()
}); })
test('empty DNs', function (t) { test('empty DNs', function (t) {
const _dn = dn.parse(''); const _dn = dn.parse('')
const _dn2 = dn.parse('cn=foo'); const _dn2 = dn.parse('cn=foo')
t.ok(_dn.isEmpty()); t.ok(_dn.isEmpty())
t.notOk(_dn2.isEmpty()); t.notOk(_dn2.isEmpty())
t.notOk(_dn.equals('cn=foo')); t.notOk(_dn.equals('cn=foo'))
t.notOk(_dn2.equals('')); t.notOk(_dn2.equals(''))
t.ok(_dn.parentOf('cn=foo')); t.ok(_dn.parentOf('cn=foo'))
t.notOk(_dn.childOf('cn=foo')); t.notOk(_dn.childOf('cn=foo'))
t.notOk(_dn2.parentOf('')); t.notOk(_dn2.parentOf(''))
t.ok(_dn2.childOf('')); t.ok(_dn2.childOf(''))
t.end(); t.end()
}); })
test('case insensitive attribute names', function (t) { test('case insensitive attribute names', function (t) {
const dn1 = dn.parse('CN=foo,dc=bar'); const dn1 = dn.parse('CN=foo,dc=bar')
t.ok(dn1.equals('cn=foo,dc=bar')); t.ok(dn1.equals('cn=foo,dc=bar'))
t.ok(dn1.equals(dn.parse('cn=foo,DC=bar'))); t.ok(dn1.equals(dn.parse('cn=foo,DC=bar')))
t.end(); t.end()
}); })
test('format', function (t) { test('format', function (t) {
const DN_ORDER = dn.parse('sn=bar+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_QUOTE = dn.parse('cn="foo",ou=test')
const DN_QUOTE2 = 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_SPACE = dn.parse('cn=foo,ou=test')
const DN_SPACE2 = 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_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: 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: true }), 'sn=bar+cn=foo, ou=test')
t.equal(DN_QUOTE.format({keepQuote: false}), '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_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: false }), 'cn=" foo", ou=test')
t.equal(DN_QUOTE2.format({keepQuote: true}), '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: false }), 'cn=foo, ou=test')
t.equal(DN_SPACE.format({keepSpace: true}), '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_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: false }), 'cn=foo, ou=test')
t.equal(DN_SPACE2.format({keepSpace: true}), '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_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: false }), 'cn=foo, ou=test')
t.equal(DN_CASE.format({keepCase: true}), '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.equal(DN_CASE.format({ upperName: true }), 'CN=foo, OU=test')
t.end(); t.end()
}); })
test('set format', function (t) { test('set format', function (t) {
const _dn = dn.parse('uid="user", sn=bar+cn=foo, dc=test , DC=com'); 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'); t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test, dc=com')
_dn.setFormat({keepOrder: true}); _dn.setFormat({ keepOrder: true })
t.equal(_dn.toString(), 'uid=user, sn=bar+cn=foo, dc=test, dc=com'); t.equal(_dn.toString(), 'uid=user, sn=bar+cn=foo, dc=test, dc=com')
_dn.setFormat({keepQuote: true}); _dn.setFormat({ keepQuote: true })
t.equal(_dn.toString(), 'uid="user", cn=foo+sn=bar, dc=test, dc=com'); t.equal(_dn.toString(), 'uid="user", cn=foo+sn=bar, dc=test, dc=com')
_dn.setFormat({keepSpace: true}); _dn.setFormat({ keepSpace: true })
t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test , dc=com'); t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test , dc=com')
_dn.setFormat({keepCase: true}); _dn.setFormat({ keepCase: true })
t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test, DC=com'); t.equal(_dn.toString(), 'uid=user, cn=foo+sn=bar, dc=test, DC=com')
_dn.setFormat({upperName: true}); _dn.setFormat({ upperName: true })
t.equal(_dn.toString(), 'UID=user, CN=foo+SN=bar, DC=test, DC=com'); t.equal(_dn.toString(), 'UID=user, CN=foo+SN=bar, DC=test, DC=com')
t.end(); t.end()
}); })
test('format persists across clone', function (t) { test('format persists across clone', function (t) {
const _dn = dn.parse('uid="user", sn=bar+cn=foo, dc=test , DC=com'); 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'; const OUT = 'UID="user", CN=foo+SN=bar, DC=test, DC=com'
_dn.setFormat({keepQuote: true, upperName: true}); _dn.setFormat({ keepQuote: true, upperName: true })
const clone = _dn.clone(); const clone = _dn.clone()
t.equals(_dn.toString(), OUT); t.equals(_dn.toString(), OUT)
t.equals(clone.toString(), OUT); t.equals(clone.toString(), OUT)
t.end(); t.end()
}); })
test('initialization', function (t) { test('initialization', function (t) {
const dn1 = new dn.DN(); const dn1 = new dn.DN()
t.ok(dn1); t.ok(dn1)
t.equals(dn1.toString(), ''); t.equals(dn1.toString(), '')
t.ok(dn1.isEmpty(), 'DN with no initializer defaults to null DN'); t.ok(dn1.isEmpty(), 'DN with no initializer defaults to null DN')
const data = [ const data = [
new dn.RDN({ foo: 'bar' }), new dn.RDN({ foo: 'bar' }),
new dn.RDN({ o: 'base' }) new dn.RDN({ o: 'base' })
]; ]
const dn2 = new dn.DN(data); const dn2 = new dn.DN(data)
t.ok(dn2); t.ok(dn2)
t.equals(dn2.toString(), 'foo=bar, o=base'); t.equals(dn2.toString(), 'foo=bar, o=base')
t.ok(!dn2.isEmpty()); t.ok(!dn2.isEmpty())
t.end(); t.end()
}); })
test('array functions', function (t) { test('array functions', function (t) {
const dn1 = dn.parse('a=foo, b=bar, c=baz'); const dn1 = dn.parse('a=foo, b=bar, c=baz')
t.ok(dn1); t.ok(dn1)
t.equal(dn1.toString(), 'a=foo, b=bar, c=baz'); t.equal(dn1.toString(), 'a=foo, b=bar, c=baz')
t.ok(dn1.reverse()); t.ok(dn1.reverse())
t.equal(dn1.toString(), 'c=baz, b=bar, a=foo'); t.equal(dn1.toString(), 'c=baz, b=bar, a=foo')
let rdn = dn1.pop(); let rdn = dn1.pop()
t.ok(rdn); t.ok(rdn)
t.equal(dn1.toString(), 'c=baz, b=bar'); t.equal(dn1.toString(), 'c=baz, b=bar')
t.ok(dn1.push(rdn)); t.ok(dn1.push(rdn))
t.equal(dn1.toString(), 'c=baz, b=bar, a=foo'); t.equal(dn1.toString(), 'c=baz, b=bar, a=foo')
rdn = dn1.shift(); rdn = dn1.shift()
t.ok(rdn); t.ok(rdn)
t.equal(dn1.toString(), 'b=bar, a=foo'); t.equal(dn1.toString(), 'b=bar, a=foo')
t.ok(dn1.unshift(rdn)); t.ok(dn1.unshift(rdn))
t.equal(dn1.toString(), 'c=baz, b=bar, a=foo'); t.equal(dn1.toString(), 'c=baz, b=bar, a=foo')
t.end(); t.end()
}); })
test('isDN duck-testing', function (t) { test('isDN duck-testing', function (t) {
const valid = dn.parse('cn=foo'); const valid = dn.parse('cn=foo')
const isDN = dn.DN.isDN; const isDN = dn.DN.isDN
t.notOk(isDN(null)); t.notOk(isDN(null))
t.notOk(isDN('cn=foo')); t.notOk(isDN('cn=foo'))
t.ok(isDN(valid)); t.ok(isDN(valid))
const duck = { const duck = {
rdns: [ {look: 'ma'}, {a: 'dn'} ], rdns: [{ look: 'ma' }, { a: 'dn' }],
toString: function () { return 'look=ma, a=dn'; } toString: function () { return 'look=ma, a=dn' }
}; }
t.ok(isDN(duck)); t.ok(isDN(duck))
t.end(); t.end()
}); })

View File

@ -1,35 +1,35 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { LDAPError, ConnectionError, AbandonedError, TimeoutError, LDAP_OTHER } = require('../lib'); const { LDAPError, ConnectionError, AbandonedError, TimeoutError, LDAP_OTHER } = require('../lib')
test('basic error', function (t) { test('basic error', function (t) {
const msg = 'mymsg'; const msg = 'mymsg'
const err = new LDAPError(msg, null, null); const err = new LDAPError(msg, null, null)
t.ok(err); t.ok(err)
t.equal(err.name, 'LDAPError'); t.equal(err.name, 'LDAPError')
t.equal(err.code, LDAP_OTHER); t.equal(err.code, LDAP_OTHER)
t.equal(err.dn, ''); t.equal(err.dn, '')
t.equal(err.message, msg); t.equal(err.message, msg)
t.end(); t.end()
}); })
test('"custom" errors', function (t) { test('"custom" errors', function (t) {
const errors = [ const errors = [
{ name: 'ConnectionError', func: ConnectionError }, { name: 'ConnectionError', Func: ConnectionError },
{ name: 'AbandonedError', func: AbandonedError }, { name: 'AbandonedError', Func: AbandonedError },
{ name: 'TimeoutError', func: TimeoutError } { name: 'TimeoutError', Func: TimeoutError }
]; ]
errors.forEach(function (entry) { errors.forEach(function (entry) {
const msg = entry.name + 'msg'; const msg = entry.name + 'msg'
const err = new entry.func(msg); const err = new entry.Func(msg)
t.ok(err); t.ok(err)
t.equal(err.name, entry.name); t.equal(err.name, entry.name)
t.equal(err.code, LDAP_OTHER); t.equal(err.code, LDAP_OTHER)
t.equal(err.dn, ''); t.equal(err.dn, '')
t.equal(err.message, msg); t.equal(err.message, msg)
}); })
t.end(); t.end()
}); })

View File

@ -1,55 +1,54 @@
'use strict'; 'use strict'
const { test } = require('tap');
const { filters: { EqualityFilter, AndFilter } } = require('../../lib');
const { test } = require('tap')
const { filters: { EqualityFilter, AndFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
t.ok(new AndFilter()); t.ok(new AndFilter())
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new AndFilter(); const f = new AndFilter()
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
})); }))
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'zig', attribute: 'zig',
value: 'zag' value: 'zag'
})); }))
t.ok(f); t.ok(f)
t.equal(f.toString(), '(&(foo=bar)(zig=zag))'); t.equal(f.toString(), '(&(foo=bar)(zig=zag))')
t.end(); t.end()
}); })
test('match true', function (t) { test('match true', function (t) {
const f = new AndFilter(); const f = new AndFilter()
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
})); }))
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'zig', attribute: 'zig',
value: 'zag' value: 'zag'
})); }))
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: 'bar', zig: 'zag' })); t.ok(f.matches({ foo: 'bar', zig: 'zag' }))
t.end(); t.end()
}); })
test('match false', function (t) { test('match false', function (t) {
const f = new AndFilter(); const f = new AndFilter()
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
})); }))
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'zig', attribute: 'zig',
value: 'zag' value: 'zag'
})); }))
t.ok(f); t.ok(f)
t.ok(!f.matches({ foo: 'bar', zig: 'zonk' })); t.ok(!f.matches({ foo: 'bar', zig: 'zonk' }))
t.end(); t.end()
}); })

View File

@ -1,85 +1,85 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { filters: { ApproximateFilter } } = require('../../lib'); const { filters: { ApproximateFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
const f = new ApproximateFilter(); const f = new ApproximateFilter()
t.ok(f); t.ok(f)
t.ok(!f.attribute); t.ok(!f.attribute)
t.ok(!f.value); t.ok(!f.value)
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new ApproximateFilter({ const f = new ApproximateFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar'); t.equal(f.value, 'bar')
t.equal(f.toString(), '(foo~=bar)'); t.equal(f.toString(), '(foo~=bar)')
t.end(); t.end()
}); })
test('GH-109 = escape value only in toString()', function (t) { test('GH-109 = escape value only in toString()', function (t) {
const f = new ApproximateFilter({ const f = new ApproximateFilter({
attribute: 'foo', attribute: 'foo',
value: 'ba(r)' value: 'ba(r)'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'ba(r)'); t.equal(f.value, 'ba(r)')
t.equal(f.toString(), '(foo~=ba\\28r\\29)'); t.equal(f.toString(), '(foo~=ba\\28r\\29)')
t.end(); t.end()
}); })
test('parse ok', function (t) { test('parse ok', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeString('bar'); writer.writeString('bar')
const f = new ApproximateFilter(); const f = new ApproximateFilter()
t.ok(f); t.ok(f)
t.ok(f.parse(new BerReader(writer.buffer))); t.ok(f.parse(new BerReader(writer.buffer)))
t.end(); t.end()
}); })
test('parse bad', function (t) { test('parse bad', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeInt(20); writer.writeInt(20)
const f = new ApproximateFilter(); const f = new ApproximateFilter()
t.ok(f); t.ok(f)
try { try {
f.parse(new BerReader(writer.buffer)); f.parse(new BerReader(writer.buffer))
t.fail('Should have thrown InvalidAsn1Error'); t.fail('Should have thrown InvalidAsn1Error')
} catch (e) { } 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) { test('GH-109 = to ber uses plain values', function (t) {
let f = new ApproximateFilter({ let f = new ApproximateFilter({
attribute: 'foo', attribute: 'foo',
value: 'ba(r)' value: 'ba(r)'
}); })
t.ok(f); t.ok(f)
const writer = new BerWriter(); const writer = new BerWriter()
f.toBer(writer); f.toBer(writer)
f = new ApproximateFilter(); f = new ApproximateFilter()
t.ok(f); t.ok(f)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
reader.readSequence(); reader.readSequence()
t.ok(f.parse(reader)); t.ok(f.parse(reader))
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'ba(r)'); t.equal(f.value, 'ba(r)')
t.end(); t.end()
}); })

View File

@ -1,167 +1,167 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { filters: { EqualityFilter } } = require('../../lib'); const { filters: { EqualityFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
const f = new EqualityFilter(); const f = new EqualityFilter()
t.ok(f); t.ok(f)
t.ok(!f.attribute); t.ok(!f.attribute)
t.ok(!f.value); t.ok(!f.value)
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new EqualityFilter({ const f = new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar'); t.equal(f.value, 'bar')
t.equal(f.toString(), '(foo=bar)'); t.equal(f.toString(), '(foo=bar)')
t.end(); t.end()
}); })
test('GH-109 = escape value only in toString()', function (t) { test('GH-109 = escape value only in toString()', function (t) {
const f = new EqualityFilter({ const f = new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'ba(r)' value: 'ba(r)'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'ba(r)'); t.equal(f.value, 'ba(r)')
t.equal(f.toString(), '(foo=ba\\28r\\29)'); t.equal(f.toString(), '(foo=ba\\28r\\29)')
t.end(); t.end()
}); })
test('match true', function (t) { test('match true', function (t) {
const f = new EqualityFilter({ const f = new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: 'bar' })); t.ok(f.matches({ foo: 'bar' }))
t.end(); t.end()
}); })
test('match multiple', function (t) { test('match multiple', function (t) {
const f = new EqualityFilter({ const f = new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: ['plop', 'bar'] })); t.ok(f.matches({ foo: ['plop', 'bar'] }))
t.end(); t.end()
}); })
test('match false', function (t) { test('match false', function (t) {
const f = new EqualityFilter({ const f = new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(!f.matches({ foo: 'baz' })); t.ok(!f.matches({ foo: 'baz' }))
t.end(); t.end()
}); })
test('parse ok', function (t) { test('parse ok', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeString('bar'); writer.writeString('bar')
const f = new EqualityFilter(); const f = new EqualityFilter()
t.ok(f); t.ok(f)
t.ok(f.parse(new BerReader(writer.buffer))); t.ok(f.parse(new BerReader(writer.buffer)))
t.ok(f.matches({ foo: 'bar' })); t.ok(f.matches({ foo: 'bar' }))
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar'); t.equal(f.value, 'bar')
t.end(); t.end()
}); })
test('escape EqualityFilter inputs', function (t) { test('escape EqualityFilter inputs', function (t) {
const f = new EqualityFilter({ const f = new EqualityFilter({
attribute: '(|(foo', attribute: '(|(foo',
value: 'bar))(' value: 'bar))('
}); })
t.equal(f.attribute, '(|(foo'); t.equal(f.attribute, '(|(foo')
t.equal(f.value, 'bar))('); t.equal(f.value, 'bar))(')
t.equal(f.toString(), '(\\28|\\28foo=bar\\29\\29\\28)'); t.equal(f.toString(), '(\\28|\\28foo=bar\\29\\29\\28)')
t.end(); t.end()
}); })
test('parse bad', function (t) { test('parse bad', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeInt(20); writer.writeInt(20)
const f = new EqualityFilter(); const f = new EqualityFilter()
t.ok(f); t.ok(f)
try { try {
f.parse(new BerReader(writer.buffer)); f.parse(new BerReader(writer.buffer))
t.fail('Should have thrown InvalidAsn1Error'); t.fail('Should have thrown InvalidAsn1Error')
} catch (e) { } 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) { test('GH-109 = to ber uses plain values', function (t) {
let f = new EqualityFilter({ let f = new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'ba(r)' value: 'ba(r)'
}); })
t.ok(f); t.ok(f)
const writer = new BerWriter(); const writer = new BerWriter()
f.toBer(writer); f.toBer(writer)
f = new EqualityFilter(); f = new EqualityFilter()
t.ok(f); t.ok(f)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
reader.readSequence(); reader.readSequence()
t.ok(f.parse(reader)); t.ok(f.parse(reader))
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'ba(r)'); t.equal(f.value, 'ba(r)')
t.end(); t.end()
}); })
test('handle values passed via buffer', function (t) { 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({ const f = new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: b value: b
}); })
t.ok(f); t.ok(f)
const writer = new BerWriter(); const writer = new BerWriter()
f.toBer(writer); f.toBer(writer)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
reader.readSequence(); reader.readSequence()
const f2 = new EqualityFilter(); const f2 = new EqualityFilter()
t.ok(f2.parse(reader)); t.ok(f2.parse(reader))
t.equal(f2.value, b.toString()); t.equal(f2.value, b.toString())
t.equal(f2.raw.length, b.length); t.equal(f2.raw.length, b.length)
for (let i = 0; i < b.length; i++) { 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) { test('GH-277 objectClass should be case-insensitive', function (t) {
const f = new EqualityFilter({ const f = new EqualityFilter({
attribute: 'objectClass', attribute: 'objectClass',
value: 'CaseInsensitiveObj' value: 'CaseInsensitiveObj'
}); })
t.ok(f); 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: 'CASEINSENSITIVEOBJ' }))
t.ok(f.matches({ objectclass: 'caseinsensitiveobj' })); t.ok(f.matches({ objectclass: 'caseinsensitiveobj' }))
t.ok(!f.matches({ objectclass: 'matchless' })); t.ok(!f.matches({ objectclass: 'matchless' }))
t.end(); t.end()
}); })

View File

@ -1,82 +1,82 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { filters: { parseString, ExtensibleFilter } } = require('../../lib'); const { filters: { parseString, ExtensibleFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
const f = new ExtensibleFilter(); const f = new ExtensibleFilter()
t.ok(f); t.ok(f)
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new ExtensibleFilter({ const f = new ExtensibleFilter({
matchType: 'foo', matchType: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.equal(f.matchType, 'foo'); t.equal(f.matchType, 'foo')
t.equal(f.value, 'bar'); t.equal(f.value, 'bar')
t.equal(f.toString(), '(foo:=bar)'); t.equal(f.toString(), '(foo:=bar)')
t.end(); t.end()
}); })
test('parse RFC example 1', function (t) { test('parse RFC example 1', function (t) {
const f = parseString('(cn:caseExactMatch:=Fred Flintstone)'); const f = parseString('(cn:caseExactMatch:=Fred Flintstone)')
t.ok(f); t.ok(f)
t.equal(f.matchType, 'cn'); t.equal(f.matchType, 'cn')
t.equal(f.matchingRule, 'caseExactMatch'); t.equal(f.matchingRule, 'caseExactMatch')
t.equal(f.matchValue, 'Fred Flintstone'); t.equal(f.matchValue, 'Fred Flintstone')
t.notOk(f.dnAttributes); t.notOk(f.dnAttributes)
t.end(); t.end()
}); })
test('parse RFC example 2', function (t) { test('parse RFC example 2', function (t) {
const f = parseString('(cn:=Betty Rubble)'); const f = parseString('(cn:=Betty Rubble)')
t.ok(f); t.ok(f)
t.equal(f.matchType, 'cn'); t.equal(f.matchType, 'cn')
t.equal(f.matchValue, 'Betty Rubble'); t.equal(f.matchValue, 'Betty Rubble')
t.notOk(f.dnAttributes); t.notOk(f.dnAttributes)
t.notOk(f.matchingRule); t.notOk(f.matchingRule)
t.end(); t.end()
}); })
test('parse RFC example 3', function (t) { test('parse RFC example 3', function (t) {
const f = parseString('(sn:dn:2.4.6.8.10:=Barney Rubble)'); const f = parseString('(sn:dn:2.4.6.8.10:=Barney Rubble)')
t.ok(f); t.ok(f)
t.equal(f.matchType, 'sn'); t.equal(f.matchType, 'sn')
t.equal(f.matchingRule, '2.4.6.8.10'); t.equal(f.matchingRule, '2.4.6.8.10')
t.equal(f.matchValue, 'Barney Rubble'); t.equal(f.matchValue, 'Barney Rubble')
t.ok(f.dnAttributes); t.ok(f.dnAttributes)
t.end(); t.end()
}); })
test('parse RFC example 3', function (t) { test('parse RFC example 3', function (t) {
const f = parseString('(o:dn:=Ace Industry)'); const f = parseString('(o:dn:=Ace Industry)')
t.ok(f); t.ok(f)
t.equal(f.matchType, 'o'); t.equal(f.matchType, 'o')
t.notOk(f.matchingRule); t.notOk(f.matchingRule)
t.equal(f.matchValue, 'Ace Industry'); t.equal(f.matchValue, 'Ace Industry')
t.ok(f.dnAttributes); t.ok(f.dnAttributes)
t.end(); t.end()
}); })
test('parse RFC example 4', function (t) { test('parse RFC example 4', function (t) {
const f = parseString('(:1.2.3:=Wilma Flintstone)'); const f = parseString('(:1.2.3:=Wilma Flintstone)')
t.ok(f); t.ok(f)
t.notOk(f.matchType); t.notOk(f.matchType)
t.equal(f.matchingRule, '1.2.3'); t.equal(f.matchingRule, '1.2.3')
t.equal(f.matchValue, 'Wilma Flintstone'); t.equal(f.matchValue, 'Wilma Flintstone')
t.notOk(f.dnAttributes); t.notOk(f.dnAttributes)
t.end(); t.end()
}); })
test('parse RFC example 5', function (t) { test('parse RFC example 5', function (t) {
const f = parseString('(:DN:2.4.6.8.10:=Dino)'); const f = parseString('(:DN:2.4.6.8.10:=Dino)')
t.ok(f); t.ok(f)
t.notOk(f.matchType); t.notOk(f.matchType)
t.equal(f.matchingRule, '2.4.6.8.10'); t.equal(f.matchingRule, '2.4.6.8.10')
t.equal(f.matchValue, 'Dino'); t.equal(f.matchValue, 'Dino')
t.ok(f.dnAttributes); t.ok(f.dnAttributes)
t.end(); t.end()
}); })

View File

@ -1,116 +1,116 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { filters: { GreaterThanEqualsFilter } } = require('../../lib'); const { filters: { GreaterThanEqualsFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
const f = new GreaterThanEqualsFilter(); const f = new GreaterThanEqualsFilter()
t.ok(f); t.ok(f)
t.ok(!f.attribute); t.ok(!f.attribute)
t.ok(!f.value); t.ok(!f.value)
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new GreaterThanEqualsFilter({ const f = new GreaterThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar'); t.equal(f.value, 'bar')
t.equal(f.toString(), '(foo>=bar)'); t.equal(f.toString(), '(foo>=bar)')
t.end(); t.end()
}); })
test('GH-109 = escape value only in toString()', function (t) { test('GH-109 = escape value only in toString()', function (t) {
const f = new GreaterThanEqualsFilter({ const f = new GreaterThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'ba(r)' value: 'ba(r)'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'ba(r)'); t.equal(f.value, 'ba(r)')
t.equal(f.toString(), '(foo>=ba\\28r\\29)'); t.equal(f.toString(), '(foo>=ba\\28r\\29)')
t.end(); t.end()
}); })
test('match true', function (t) { test('match true', function (t) {
const f = new GreaterThanEqualsFilter({ const f = new GreaterThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: 'baz' })); t.ok(f.matches({ foo: 'baz' }))
t.end(); t.end()
}); })
test('match multiple', function (t) { test('match multiple', function (t) {
const f = new GreaterThanEqualsFilter({ const f = new GreaterThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: ['beuha', 'baz'] })); t.ok(f.matches({ foo: ['beuha', 'baz'] }))
t.end(); t.end()
}); })
test('match false', function (t) { test('match false', function (t) {
const f = new GreaterThanEqualsFilter({ const f = new GreaterThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(!f.matches({ foo: 'abc' })); t.ok(!f.matches({ foo: 'abc' }))
t.end(); t.end()
}); })
test('parse ok', function (t) { test('parse ok', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeString('bar'); writer.writeString('bar')
const f = new GreaterThanEqualsFilter(); const f = new GreaterThanEqualsFilter()
t.ok(f); t.ok(f)
t.ok(f.parse(new BerReader(writer.buffer))); t.ok(f.parse(new BerReader(writer.buffer)))
t.ok(f.matches({ foo: 'bar' })); t.ok(f.matches({ foo: 'bar' }))
t.end(); t.end()
}); })
test('parse bad', function (t) { test('parse bad', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeInt(20); writer.writeInt(20)
const f = new GreaterThanEqualsFilter(); const f = new GreaterThanEqualsFilter()
t.ok(f); t.ok(f)
try { try {
f.parse(new BerReader(writer.buffer)); f.parse(new BerReader(writer.buffer))
t.fail('Should have thrown InvalidAsn1Error'); t.fail('Should have thrown InvalidAsn1Error')
} catch (e) { } 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) { test('GH-109 = to ber uses plain values', function (t) {
let f = new GreaterThanEqualsFilter({ let f = new GreaterThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'ba(r)' value: 'ba(r)'
}); })
t.ok(f); t.ok(f)
const writer = new BerWriter(); const writer = new BerWriter()
f.toBer(writer); f.toBer(writer)
f = new GreaterThanEqualsFilter(); f = new GreaterThanEqualsFilter()
t.ok(f); t.ok(f)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
reader.readSequence(); reader.readSequence()
t.ok(f.parse(reader)); t.ok(f.parse(reader))
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'ba(r)'); t.equal(f.value, 'ba(r)')
t.end(); t.end()
}); })

View File

@ -1,116 +1,116 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { filters: { LessThanEqualsFilter } } = require('../../lib'); const { filters: { LessThanEqualsFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
const f = new LessThanEqualsFilter(); const f = new LessThanEqualsFilter()
t.ok(f); t.ok(f)
t.ok(!f.attribute); t.ok(!f.attribute)
t.ok(!f.value); t.ok(!f.value)
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new LessThanEqualsFilter({ const f = new LessThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar'); t.equal(f.value, 'bar')
t.equal(f.toString(), '(foo<=bar)'); t.equal(f.toString(), '(foo<=bar)')
t.end(); t.end()
}); })
test('GH-109 = escape value only in toString()', function (t) { test('GH-109 = escape value only in toString()', function (t) {
const f = new LessThanEqualsFilter({ const f = new LessThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'ba(r)' value: 'ba(r)'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'ba(r)'); t.equal(f.value, 'ba(r)')
t.equal(f.toString(), '(foo<=ba\\28r\\29)'); t.equal(f.toString(), '(foo<=ba\\28r\\29)')
t.end(); t.end()
}); })
test('match true', function (t) { test('match true', function (t) {
const f = new LessThanEqualsFilter({ const f = new LessThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: 'abc' })); t.ok(f.matches({ foo: 'abc' }))
t.end(); t.end()
}); })
test('match multiple', function (t) { test('match multiple', function (t) {
const f = new LessThanEqualsFilter({ const f = new LessThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: ['abc', 'beuha'] })); t.ok(f.matches({ foo: ['abc', 'beuha'] }))
t.end(); t.end()
}); })
test('match false', function (t) { test('match false', function (t) {
const f = new LessThanEqualsFilter({ const f = new LessThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(!f.matches({ foo: 'baz' })); t.ok(!f.matches({ foo: 'baz' }))
t.end(); t.end()
}); })
test('parse ok', function (t) { test('parse ok', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeString('bar'); writer.writeString('bar')
const f = new LessThanEqualsFilter(); const f = new LessThanEqualsFilter()
t.ok(f); t.ok(f)
t.ok(f.parse(new BerReader(writer.buffer))); t.ok(f.parse(new BerReader(writer.buffer)))
t.ok(f.matches({ foo: 'bar' })); t.ok(f.matches({ foo: 'bar' }))
t.end(); t.end()
}); })
test('parse bad', function (t) { test('parse bad', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeInt(20); writer.writeInt(20)
const f = new LessThanEqualsFilter(); const f = new LessThanEqualsFilter()
t.ok(f); t.ok(f)
try { try {
f.parse(new BerReader(writer.buffer)); f.parse(new BerReader(writer.buffer))
t.fail('Should have thrown InvalidAsn1Error'); t.fail('Should have thrown InvalidAsn1Error')
} catch (e) { } 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) { test('GH-109 = to ber uses plain values', function (t) {
let f = new LessThanEqualsFilter({ let f = new LessThanEqualsFilter({
attribute: 'foo', attribute: 'foo',
value: 'ba(r)' value: 'ba(r)'
}); })
t.ok(f); t.ok(f)
const writer = new BerWriter(); const writer = new BerWriter()
f.toBer(writer); f.toBer(writer)
f = new LessThanEqualsFilter(); f = new LessThanEqualsFilter()
t.ok(f); t.ok(f)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
reader.readSequence(); reader.readSequence()
t.ok(f.parse(reader)); t.ok(f.parse(reader))
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'ba(r)'); t.equal(f.value, 'ba(r)')
t.end(); t.end()
}); })

View File

@ -1,12 +1,12 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { filters: { EqualityFilter, NotFilter } } = require('../../lib'); const { filters: { EqualityFilter, NotFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
t.ok(new NotFilter()); t.ok(new NotFilter())
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new NotFilter({ const f = new NotFilter({
@ -14,11 +14,11 @@ test('Construct args', function (t) {
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}) })
}); })
t.ok(f); t.ok(f)
t.equal(f.toString(), '(!(foo=bar))'); t.equal(f.toString(), '(!(foo=bar))')
t.end(); t.end()
}); })
test('match true', function (t) { test('match true', function (t) {
const f = new NotFilter({ const f = new NotFilter({
@ -26,11 +26,11 @@ test('match true', function (t) {
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}) })
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: 'baz' })); t.ok(f.matches({ foo: 'baz' }))
t.end(); t.end()
}); })
test('match false', function (t) { test('match false', function (t) {
const f = new NotFilter({ const f = new NotFilter({
@ -38,8 +38,8 @@ test('match false', function (t) {
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
}) })
}); })
t.ok(f); t.ok(f)
t.ok(!f.matches({ foo: 'bar' })); t.ok(!f.matches({ foo: 'bar' }))
t.end(); t.end()
}); })

View File

@ -1,54 +1,54 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { filters: { EqualityFilter, OrFilter } } = require('../../lib'); const { filters: { EqualityFilter, OrFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
t.ok(new OrFilter()); t.ok(new OrFilter())
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new OrFilter(); const f = new OrFilter()
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
})); }))
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'zig', attribute: 'zig',
value: 'zag' value: 'zag'
})); }))
t.ok(f); t.ok(f)
t.equal(f.toString(), '(|(foo=bar)(zig=zag))'); t.equal(f.toString(), '(|(foo=bar)(zig=zag))')
t.end(); t.end()
}); })
test('match true', function (t) { test('match true', function (t) {
const f = new OrFilter(); const f = new OrFilter()
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
})); }))
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'zig', attribute: 'zig',
value: 'zag' value: 'zag'
})); }))
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: 'bar', zig: 'zonk' })); t.ok(f.matches({ foo: 'bar', zig: 'zonk' }))
t.end(); t.end()
}); })
test('match false', function (t) { test('match false', function (t) {
const f = new OrFilter(); const f = new OrFilter()
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'foo', attribute: 'foo',
value: 'bar' value: 'bar'
})); }))
f.addFilter(new EqualityFilter({ f.addFilter(new EqualityFilter({
attribute: 'zig', attribute: 'zig',
value: 'zag' value: 'zag'
})); }))
t.ok(f); t.ok(f)
t.ok(!f.matches({ foo: 'baz', zig: 'zonk' })); t.ok(!f.matches({ foo: 'baz', zig: 'zonk' }))
t.end(); t.end()
}); })

View File

@ -1,121 +1,121 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { parseFilter: parse } = require('../../lib'); const { parseFilter: parse } = require('../../lib')
test('GH-48 XML Strings in filter', function (t) { test('GH-48 XML Strings in filter', function (t) {
const str = '(&(CentralUIEnrollments=\\<mydoc\\>*)(objectClass=User))'; const str = '(&(CentralUIEnrollments=\\<mydoc\\>*)(objectClass=User))'
const f = parse(str); const f = parse(str)
t.ok(f); t.ok(f)
t.ok(f.filters); t.ok(f.filters)
t.equal(f.filters.length, 2); t.equal(f.filters.length, 2)
f.filters.forEach(function (filter) { f.filters.forEach(function (filter) {
t.ok(filter.attribute); t.ok(filter.attribute)
}); })
t.end(); t.end()
}); })
test('GH-50 = in filter', function (t) { test('GH-50 = in filter', function (t) {
const str = '(uniquemember=uuid=930896af-bf8c-48d4-885c-6573a94b1853, ' + const str = '(uniquemember=uuid=930896af-bf8c-48d4-885c-6573a94b1853, ' +
'ou=users, o=smartdc)'; 'ou=users, o=smartdc)'
const f = parse(str); const f = parse(str)
t.ok(f); t.ok(f)
t.equal(f.attribute, 'uniquemember'); t.equal(f.attribute, 'uniquemember')
t.equal(f.value, t.equal(f.value,
'uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc'); 'uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc')
t.end(); t.end()
}); })
test('( in filter', function (t) { test('( in filter', function (t) {
const str = '(foo=bar\\()'; const str = '(foo=bar\\()'
const f = parse(str); const f = parse(str)
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar('); t.equal(f.value, 'bar(')
t.equal(f.toString(), '(foo=bar\\28)'); t.equal(f.toString(), '(foo=bar\\28)')
t.end(); t.end()
}); })
test(') in filter', function (t) { test(') in filter', function (t) {
const str = '(foo=bar\\))'; const str = '(foo=bar\\))'
const f = parse(str); const f = parse(str)
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar)'); t.equal(f.value, 'bar)')
t.equal(f.toString(), '(foo=bar\\29)'); t.equal(f.toString(), '(foo=bar\\29)')
t.end(); t.end()
}); })
test('\\ in filter', function (t) { test('\\ in filter', function (t) {
const str = '(foo=bar\\\\)'; const str = '(foo=bar\\\\)'
const f = parse(str); const f = parse(str)
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar\\'); t.equal(f.value, 'bar\\')
t.equal(f.toString(), '(foo=bar\\5c)'); t.equal(f.toString(), '(foo=bar\\5c)')
t.end(); t.end()
}); })
test('* in equality filter', function (t) { test('* in equality filter', function (t) {
const str = '(foo=bar\\*)'; const str = '(foo=bar\\*)'
const f = parse(str); const f = parse(str)
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.value, 'bar*'); t.equal(f.value, 'bar*')
t.equal(f.toString(), '(foo=bar\\2a)'); t.equal(f.toString(), '(foo=bar\\2a)')
t.end(); t.end()
}); })
test('* substr filter (prefix)', function (t) { test('* substr filter (prefix)', function (t) {
const str = '(foo=bar*)'; const str = '(foo=bar*)'
const f = parse(str); const f = parse(str)
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.initial, 'bar'); t.equal(f.initial, 'bar')
t.equal(f.toString(), '(foo=bar*)'); t.equal(f.toString(), '(foo=bar*)')
t.end(); t.end()
}); })
test('GH-53 NotFilter', function (t) { test('GH-53 NotFilter', function (t) {
const str = '(&(objectClass=person)(!(objectClass=shadowAccount)))'; const str = '(&(objectClass=person)(!(objectClass=shadowAccount)))'
const f = parse(str); const f = parse(str)
t.ok(f); t.ok(f)
t.equal(f.type, 'and'); t.equal(f.type, 'and')
t.equal(f.filters.length, 2); t.equal(f.filters.length, 2)
t.equal(f.filters[0].type, 'equal'); t.equal(f.filters[0].type, 'equal')
t.equal(f.filters[1].type, 'not'); t.equal(f.filters[1].type, 'not')
t.equal(f.filters[1].filter.type, 'equal'); t.equal(f.filters[1].filter.type, 'equal')
t.equal(f.filters[1].filter.attribute, 'objectClass'); t.equal(f.filters[1].filter.attribute, 'objectClass')
t.equal(f.filters[1].filter.value, 'shadowAccount'); t.equal(f.filters[1].filter.value, 'shadowAccount')
t.end(); t.end()
}); })
test('presence filter', function (t) { test('presence filter', function (t) {
const f = parse('(foo=*)'); const f = parse('(foo=*)')
t.ok(f); t.ok(f)
t.equal(f.type, 'present'); t.equal(f.type, 'present')
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.toString(), '(foo=*)'); t.equal(f.toString(), '(foo=*)')
t.end(); t.end()
}); })
test('bogus filter', function (t) { test('bogus filter', function (t) {
t.throws(function () { t.throws(function () {
parse('foo>1'); parse('foo>1')
}); })
t.end(); t.end()
}); })
test('bogus filter !=', function (t) { test('bogus filter !=', function (t) {
t.throws(function () { t.throws(function () {
parse('foo!=1'); parse('foo!=1')
}); })
t.end(); t.end()
}); })
test('mismatched parens', function (t) { test('mismatched parens', function (t) {
t.throws(function () { t.throws(function () {
parse('(&(foo=bar)(!(state=done))'); parse('(&(foo=bar)(!(state=done))')
}); })
t.end(); t.end()
}); })

View File

@ -1,83 +1,83 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { filters: { PresenceFilter } } = require('../../lib'); const { filters: { PresenceFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
const f = new PresenceFilter(); const f = new PresenceFilter()
t.ok(f); t.ok(f)
t.ok(!f.attribute); t.ok(!f.attribute)
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new PresenceFilter({ const f = new PresenceFilter({
attribute: 'foo' attribute: 'foo'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.toString(), '(foo=*)'); t.equal(f.toString(), '(foo=*)')
t.end(); t.end()
}); })
test('GH-109 = escape value only in toString()', function (t) { test('GH-109 = escape value only in toString()', function (t) {
const f = new PresenceFilter({ const f = new PresenceFilter({
attribute: 'fo)o' attribute: 'fo)o'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'fo)o'); t.equal(f.attribute, 'fo)o')
t.equal(f.toString(), '(fo\\29o=*)'); t.equal(f.toString(), '(fo\\29o=*)')
t.end(); t.end()
}); })
test('match true', function (t) { test('match true', function (t) {
const f = new PresenceFilter({ const f = new PresenceFilter({
attribute: 'foo' attribute: 'foo'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: 'bar' })); t.ok(f.matches({ foo: 'bar' }))
t.end(); t.end()
}); })
test('match false', function (t) { test('match false', function (t) {
const f = new PresenceFilter({ const f = new PresenceFilter({
attribute: 'foo' attribute: 'foo'
}); })
t.ok(f); t.ok(f)
t.ok(!f.matches({ bar: 'foo' })); t.ok(!f.matches({ bar: 'foo' }))
t.end(); t.end()
}); })
test('parse ok', function (t) { test('parse ok', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo', 0x87); writer.writeString('foo', 0x87)
const f = new PresenceFilter(); const f = new PresenceFilter()
t.ok(f); t.ok(f)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
reader.readSequence(); reader.readSequence()
t.ok(f.parse(reader)); t.ok(f.parse(reader))
t.ok(f.matches({ foo: 'bar' })); t.ok(f.matches({ foo: 'bar' }))
t.end(); t.end()
}); })
test('GH-109 = to ber uses plain values', function (t) { test('GH-109 = to ber uses plain values', function (t) {
let f = new PresenceFilter({ let f = new PresenceFilter({
attribute: 'f(o)o' attribute: 'f(o)o'
}); })
t.ok(f); t.ok(f)
const writer = new BerWriter(); const writer = new BerWriter()
f.toBer(writer); f.toBer(writer)
f = new PresenceFilter(); f = new PresenceFilter()
t.ok(f); t.ok(f)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
reader.readSequence(); reader.readSequence()
t.ok(f.parse(reader)); t.ok(f.parse(reader))
t.equal(f.attribute, 'f(o)o'); t.equal(f.attribute, 'f(o)o')
t.end(); t.end()
}); })

View File

@ -1,152 +1,152 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { filters: { SubstringFilter } } = require('../../lib'); const { filters: { SubstringFilter } } = require('../../lib')
test('Construct no args', function (t) { test('Construct no args', function (t) {
const f = new SubstringFilter(); const f = new SubstringFilter()
t.ok(f); t.ok(f)
t.ok(!f.attribute); t.ok(!f.attribute)
t.ok(!f.value); t.ok(!f.value)
t.end(); t.end()
}); })
test('Construct args', function (t) { test('Construct args', function (t) {
const f = new SubstringFilter({ const f = new SubstringFilter({
attribute: 'foo', attribute: 'foo',
initial: 'bar', initial: 'bar',
any: ['zig', 'zag'], any: ['zig', 'zag'],
'final': 'baz' final: 'baz'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'foo'); t.equal(f.attribute, 'foo')
t.equal(f.initial, 'bar'); t.equal(f.initial, 'bar')
t.equal(f.any.length, 2); t.equal(f.any.length, 2)
t.equal(f.any[0], 'zig'); t.equal(f.any[0], 'zig')
t.equal(f.any[1], 'zag'); t.equal(f.any[1], 'zag')
t.equal(f['final'], 'baz'); t.equal(f.final, 'baz')
t.equal(f.toString(), '(foo=bar*zig*zag*baz)'); t.equal(f.toString(), '(foo=bar*zig*zag*baz)')
t.end(); t.end()
}); })
test('GH-109 = escape value only in toString()', function (t) { test('GH-109 = escape value only in toString()', function (t) {
const f = new SubstringFilter({ const f = new SubstringFilter({
attribute: 'fo(o', attribute: 'fo(o',
initial: 'ba(r)', initial: 'ba(r)',
any: ['zi)g', 'z(ag'], any: ['zi)g', 'z(ag'],
'final': '(baz)' final: '(baz)'
}); })
t.ok(f); t.ok(f)
t.equal(f.attribute, 'fo(o'); t.equal(f.attribute, 'fo(o')
t.equal(f.initial, 'ba(r)'); t.equal(f.initial, 'ba(r)')
t.equal(f.any.length, 2); t.equal(f.any.length, 2)
t.equal(f.any[0], 'zi)g'); t.equal(f.any[0], 'zi)g')
t.equal(f.any[1], 'z(ag'); t.equal(f.any[1], 'z(ag')
t.equal(f['final'], '(baz)'); t.equal(f.final, '(baz)')
t.equal(f.toString(), '(fo\\28o=ba\\28r\\29*zi\\29g*z\\28ag*\\28baz\\29)'); t.equal(f.toString(), '(fo\\28o=ba\\28r\\29*zi\\29g*z\\28ag*\\28baz\\29)')
t.end(); t.end()
}); })
test('match true', function (t) { test('match true', function (t) {
const f = new SubstringFilter({ const f = new SubstringFilter({
attribute: 'foo', attribute: 'foo',
initial: 'bar', initial: 'bar',
any: ['zig', 'zag'], any: ['zig', 'zag'],
'final': 'baz' final: 'baz'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: 'barmoozigbarzagblahbaz' })); t.ok(f.matches({ foo: 'barmoozigbarzagblahbaz' }))
t.end(); t.end()
}); })
test('match false', function (t) { test('match false', function (t) {
const f = new SubstringFilter({ const f = new SubstringFilter({
attribute: 'foo', attribute: 'foo',
initial: 'bar', initial: 'bar',
foo: ['zig', 'zag'], foo: ['zig', 'zag'],
'final': 'baz' final: 'baz'
}); })
t.ok(f); t.ok(f)
t.ok(!f.matches({ foo: 'bafmoozigbarzagblahbaz' })); t.ok(!f.matches({ foo: 'bafmoozigbarzagblahbaz' }))
t.end(); t.end()
}); })
test('match any', function (t) { test('match any', function (t) {
const f = new SubstringFilter({ const f = new SubstringFilter({
attribute: 'foo', attribute: 'foo',
initial: 'bar' initial: 'bar'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ foo: ['beuha', 'barista']})); t.ok(f.matches({ foo: ['beuha', 'barista'] }))
t.end(); t.end()
}); })
test('GH-109 = escape for regex in matches', function (t) { test('GH-109 = escape for regex in matches', function (t) {
const f = new SubstringFilter({ const f = new SubstringFilter({
attribute: 'fo(o', attribute: 'fo(o',
initial: 'ba(r)', initial: 'ba(r)',
any: ['zi)g', 'z(ag'], any: ['zi)g', 'z(ag'],
'final': '(baz)' final: '(baz)'
}); })
t.ok(f); t.ok(f)
t.ok(f.matches({ 'fo(o': ['ba(r)_zi)g-z(ag~(baz)']})); t.ok(f.matches({ 'fo(o': ['ba(r)_zi)g-z(ag~(baz)'] }))
t.end(); t.end()
}); })
test('parse ok', function (t) { test('parse ok', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.startSequence(); writer.startSequence()
writer.writeString('bar', 0x80); writer.writeString('bar', 0x80)
writer.writeString('bad', 0x81); writer.writeString('bad', 0x81)
writer.writeString('baz', 0x82); writer.writeString('baz', 0x82)
writer.endSequence(); writer.endSequence()
const f = new SubstringFilter(); const f = new SubstringFilter()
t.ok(f); t.ok(f)
t.ok(f.parse(new BerReader(writer.buffer))); t.ok(f.parse(new BerReader(writer.buffer)))
t.ok(f.matches({ foo: 'bargoobadgoobaz' })); t.ok(f.matches({ foo: 'bargoobadgoobaz' }))
t.end(); t.end()
}); })
test('parse bad', function (t) { test('parse bad', function (t) {
const writer = new BerWriter(); const writer = new BerWriter()
writer.writeString('foo'); writer.writeString('foo')
writer.writeInt(20); writer.writeInt(20)
const f = new SubstringFilter(); const f = new SubstringFilter()
t.ok(f); t.ok(f)
try { try {
f.parse(new BerReader(writer.buffer)); f.parse(new BerReader(writer.buffer))
t.fail('Should have thrown InvalidAsn1Error'); t.fail('Should have thrown InvalidAsn1Error')
} catch (e) { } catch (e) {
} }
t.end(); t.end()
}); })
test('GH-109 = to ber uses plain values', function (t) { test('GH-109 = to ber uses plain values', function (t) {
let f = new SubstringFilter({ let f = new SubstringFilter({
attribute: 'fo(o', attribute: 'fo(o',
initial: 'ba(r)', initial: 'ba(r)',
any: ['zi)g', 'z(ag'], any: ['zi)g', 'z(ag'],
'final': '(baz)' final: '(baz)'
}); })
t.ok(f); t.ok(f)
const writer = new BerWriter(); const writer = new BerWriter()
f.toBer(writer); f.toBer(writer)
f = new SubstringFilter(); f = new SubstringFilter()
t.ok(f); t.ok(f)
const reader = new BerReader(writer.buffer); const reader = new BerReader(writer.buffer)
reader.readSequence(); reader.readSequence()
t.ok(f.parse(reader)); t.ok(f.parse(reader))
t.equal(f.attribute, 'fo(o'); t.equal(f.attribute, 'fo(o')
t.equal(f.initial, 'ba(r)'); t.equal(f.initial, 'ba(r)')
t.equal(f.any.length, 2); t.equal(f.any.length, 2)
t.equal(f.any[0], 'zi)g'); t.equal(f.any[0], 'zi)g')
t.equal(f.any[1], 'z(ag'); t.equal(f.any[1], 'z(ag')
t.equal(f['final'], '(baz)'); t.equal(f.final, '(baz)')
t.end(); t.end()
}); })

View File

@ -1,39 +1,39 @@
'use strict'; 'use strict'
const tap = require('tap'); const tap = require('tap')
const uuid = require('uuid') const uuid = require('uuid')
const { getSock } = require('./utils') 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.context.client.search(t.context.suffix, options, function (err, res) {
t.error(err); t.error(err)
t.ok(res); t.ok(res)
let found = false; let found = false
res.on('searchEntry', function (entry) { res.on('searchEntry', function (entry) {
t.ok(entry); t.ok(entry)
found = true; found = true
}); })
res.on('end', function () { res.on('end', function () {
t.true(found); t.true(found)
if (callback) return callback(); if (callback) return callback()
return t.end(); return t.end()
}); })
}); })
} }
tap.beforeEach((done, t) => { tap.beforeEach((done, t) => {
const suffix = `dc=${uuid()}`; const suffix = `dc=${uuid()}`
const server = ldap.createServer(); const server = ldap.createServer()
t.context.server = server; t.context.server = server
t.context.socketPath = getSock(); t.context.socketPath = getSock()
t.context.suffix = suffix; t.context.suffix = suffix
server.bind('cn=root', function (req, res, next) { server.bind('cn=root', function (req, res, next) {
res.end(); res.end()
return next(); return next()
}); })
server.search(suffix, function (req, res, next) { server.search(suffix, function (req, res, next) {
var entry = { var entry = {
@ -45,27 +45,26 @@ tap.beforeEach((done, t) => {
givenname: 'ogo', givenname: 'ogo',
mail: uuid() + '@pogostick.org' mail: uuid() + '@pogostick.org'
} }
}; }
if (req.filter.matches(entry.attributes)) if (req.filter.matches(entry.attributes)) { res.send(entry) }
res.send(entry);
res.end(); res.end()
}); })
server.listen(t.context.socketPath, function () { server.listen(t.context.socketPath, function () {
t.context.client = ldap.createClient({ t.context.client = ldap.createClient({
socketPath: t.context.socketPath socketPath: t.context.socketPath
}); })
t.context.client.on('connectError', (err) => { 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.client.on('connect', (socket) => {
t.context.socket = socket; t.context.socket = socket
done(); done()
}) })
}); })
}) })
tap.afterEach((done, t) => { tap.afterEach((done, t) => {
@ -93,35 +92,35 @@ tap.test('Evolution search filter (GH-3)', function (t) {
'(otherpostaladdress=ogo*)(jpegphoto=ogo*)(usercertificate=ogo*)' + '(otherpostaladdress=ogo*)(jpegphoto=ogo*)(usercertificate=ogo*)' +
'(labeleduri=ogo*)(displayname=ogo*)(spousename=ogo*)(note=ogo*)' + '(labeleduri=ogo*)(displayname=ogo*)(spousename=ogo*)(note=ogo*)' +
'(anniversary=ogo*)(birthdate=ogo*)(mailer=ogo*)(fileas=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) { tap.test('GH-49 Client errors on bad attributes', function (t) {
const searchOpts = { const searchOpts = {
filter: 'cn=*ogo*', filter: 'cn=*ogo*',
scope: 'one', scope: 'one',
attributes: 'dn' attributes: 'dn'
}; }
return search(t, searchOpts); return search(t, searchOpts)
}); })
tap.test('GH-55 Client emits connect multiple times', function (t) { tap.test('GH-55 Client emits connect multiple times', function (t) {
const c = ldap.createClient({ const c = ldap.createClient({
socketPath: t.context.socketPath socketPath: t.context.socketPath
}); })
let count = 0; let count = 0
c.on('connect', function (socket) { c.on('connect', function (socket) {
t.ok(socket); t.ok(socket)
count++; count++
c.bind('cn=root', 'secret', function (err) { c.bind('cn=root', 'secret', function (err) {
t.ifError(err); t.ifError(err)
c.unbind(function () { c.unbind(function () {
t.equal(count, 1); t.equal(count, 1)
t.end(); t.end()
}); })
}); })
}); })
}); })

View File

@ -1,118 +1,118 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { AddRequest, Attribute, dn } = require('../../lib'); const { AddRequest, Attribute, dn } = require('../../lib')
test('new no args', t => { test('new no args', t => {
t.ok(new AddRequest()); t.ok(new AddRequest())
t.end(); t.end()
}); })
test('new with args', t => { test('new with args', t => {
const req = new AddRequest({ const req = new AddRequest({
entry: dn.parse('cn=foo, o=test'), entry: dn.parse('cn=foo, o=test'),
attributes: [new Attribute({type: 'cn', vals: ['foo']}), attributes: [new Attribute({ type: 'cn', vals: ['foo'] }),
new Attribute({type: 'objectclass', vals: ['person']})] new Attribute({ type: 'objectclass', vals: ['person'] })]
}); })
t.ok(req); t.ok(req)
t.equal(req.dn.toString(), 'cn=foo, o=test'); t.equal(req.dn.toString(), 'cn=foo, o=test')
t.equal(req.attributes.length, 2); t.equal(req.attributes.length, 2)
t.equal(req.attributes[0].type, 'cn'); t.equal(req.attributes[0].type, 'cn')
t.equal(req.attributes[0].vals[0], 'foo'); t.equal(req.attributes[0].vals[0], 'foo')
t.equal(req.attributes[1].type, 'objectclass'); t.equal(req.attributes[1].type, 'objectclass')
t.equal(req.attributes[1].vals[0], 'person'); t.equal(req.attributes[1].vals[0], 'person')
t.end(); t.end()
}); })
test('parse', t => { test('parse', t => {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeString('cn=foo, o=test'); ber.writeString('cn=foo, o=test')
ber.startSequence(); ber.startSequence()
ber.startSequence(); ber.startSequence()
ber.writeString('cn'); ber.writeString('cn')
ber.startSequence(0x31); ber.startSequence(0x31)
ber.writeString('foo'); ber.writeString('foo')
ber.endSequence(); ber.endSequence()
ber.endSequence(); ber.endSequence()
ber.startSequence(); ber.startSequence()
ber.writeString('objectclass'); ber.writeString('objectclass')
ber.startSequence(0x31); ber.startSequence(0x31)
ber.writeString('person'); ber.writeString('person')
ber.endSequence(); ber.endSequence()
ber.endSequence(); ber.endSequence()
ber.endSequence(); ber.endSequence()
const req = new AddRequest(); const req = new AddRequest()
t.ok(req._parse(new BerReader(ber.buffer))); t.ok(req._parse(new BerReader(ber.buffer)))
t.equal(req.dn.toString(), 'cn=foo, o=test'); t.equal(req.dn.toString(), 'cn=foo, o=test')
t.equal(req.attributes.length, 2); t.equal(req.attributes.length, 2)
t.equal(req.attributes[0].type, 'cn'); t.equal(req.attributes[0].type, 'cn')
t.equal(req.attributes[0].vals[0], 'foo'); t.equal(req.attributes[0].vals[0], 'foo')
t.equal(req.attributes[1].type, 'objectclass'); t.equal(req.attributes[1].type, 'objectclass')
t.equal(req.attributes[1].vals[0], 'person'); t.equal(req.attributes[1].vals[0], 'person')
t.end(); t.end()
}); })
test('toBer', t => { test('toBer', t => {
const req = new AddRequest({ const req = new AddRequest({
messageID: 123, messageID: 123,
entry: dn.parse('cn=foo, o=test'), entry: dn.parse('cn=foo, o=test'),
attributes: [new Attribute({type: 'cn', vals: ['foo']}), attributes: [new Attribute({ type: 'cn', vals: ['foo'] }),
new Attribute({type: 'objectclass', vals: ['person']})] new Attribute({ type: 'objectclass', vals: ['person'] })]
}); })
t.ok(req); t.ok(req)
const ber = new BerReader(req.toBer()); const ber = new BerReader(req.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x68); t.equal(ber.readSequence(), 0x68)
t.equal(ber.readString(), 'cn=foo, o=test'); t.equal(ber.readString(), 'cn=foo, o=test')
t.ok(ber.readSequence()); t.ok(ber.readSequence())
t.ok(ber.readSequence()); t.ok(ber.readSequence())
t.equal(ber.readString(), 'cn'); t.equal(ber.readString(), 'cn')
t.equal(ber.readSequence(), 0x31); t.equal(ber.readSequence(), 0x31)
t.equal(ber.readString(), 'foo'); t.equal(ber.readString(), 'foo')
t.ok(ber.readSequence()); t.ok(ber.readSequence())
t.equal(ber.readString(), 'objectclass'); t.equal(ber.readString(), 'objectclass')
t.equal(ber.readSequence(), 0x31); t.equal(ber.readSequence(), 0x31)
t.equal(ber.readString(), 'person'); t.equal(ber.readString(), 'person')
t.end(); t.end()
}); })
test('toObject', t => { test('toObject', t => {
const req = new AddRequest({ const req = new AddRequest({
entry: dn.parse('cn=foo, o=test'), entry: dn.parse('cn=foo, o=test'),
attributes: [new Attribute({type: 'cn', vals: ['foo', 'bar']}), attributes: [new Attribute({ type: 'cn', vals: ['foo', 'bar'] }),
new Attribute({type: 'objectclass', vals: ['person']})] new Attribute({ type: 'objectclass', vals: ['person'] })]
}); })
t.ok(req); t.ok(req)
const obj = req.toObject(); const obj = req.toObject()
t.ok(obj); t.ok(obj)
t.ok(obj.dn); t.ok(obj.dn)
t.equal(obj.dn, 'cn=foo, o=test'); t.equal(obj.dn, 'cn=foo, o=test')
t.ok(obj.attributes); t.ok(obj.attributes)
t.ok(obj.attributes.cn); t.ok(obj.attributes.cn)
t.ok(Array.isArray(obj.attributes.cn)); t.ok(Array.isArray(obj.attributes.cn))
t.equal(obj.attributes.cn.length, 2); t.equal(obj.attributes.cn.length, 2)
t.equal(obj.attributes.cn[0], 'foo'); t.equal(obj.attributes.cn[0], 'foo')
t.equal(obj.attributes.cn[1], 'bar'); t.equal(obj.attributes.cn[1], 'bar')
t.ok(obj.attributes.objectclass); t.ok(obj.attributes.objectclass)
t.ok(Array.isArray(obj.attributes.objectclass)); t.ok(Array.isArray(obj.attributes.objectclass))
t.equal(obj.attributes.objectclass.length, 1); t.equal(obj.attributes.objectclass.length, 1)
t.equal(obj.attributes.objectclass[0], 'person'); t.equal(obj.attributes.objectclass[0], 'person')
t.end(); t.end()
}); })

View File

@ -1,38 +1,38 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { AddResponse } = require('../../lib'); const { AddResponse } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new AddResponse()); t.ok(new AddResponse())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const res = new AddResponse({ const res = new AddResponse({
messageID: 123, messageID: 123,
status: 0 status: 0
}); })
t.ok(res); t.ok(res)
t.equal(res.messageID, 123); t.equal(res.messageID, 123)
t.equal(res.status, 0); t.equal(res.status, 0)
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeEnumeration(0); ber.writeEnumeration(0)
ber.writeString('cn=root'); ber.writeString('cn=root')
ber.writeString('foo'); ber.writeString('foo')
const res = new AddResponse(); const res = new AddResponse()
t.ok(res._parse(new BerReader(ber.buffer))); t.ok(res._parse(new BerReader(ber.buffer)))
t.equal(res.status, 0); t.equal(res.status, 0)
t.equal(res.matchedDN, 'cn=root'); t.equal(res.matchedDN, 'cn=root')
t.equal(res.errorMessage, 'foo'); t.equal(res.errorMessage, 'foo')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const res = new AddResponse({ const res = new AddResponse({
@ -40,17 +40,17 @@ test('toBer', function (t) {
status: 3, status: 3,
matchedDN: 'cn=root', matchedDN: 'cn=root',
errorMessage: 'foo' errorMessage: 'foo'
}); })
t.ok(res); t.ok(res)
const ber = new BerReader(res.toBer()); const ber = new BerReader(res.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x69); t.equal(ber.readSequence(), 0x69)
t.equal(ber.readEnumeration(), 3); t.equal(ber.readEnumeration(), 3)
t.equal(ber.readString(), 'cn=root'); t.equal(ber.readString(), 'cn=root')
t.equal(ber.readString(), 'foo'); t.equal(ber.readString(), 'foo')
t.end(); t.end()
}); })

View File

@ -1,40 +1,40 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { BindRequest, dn } = require('../../lib'); const { BindRequest, dn } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new BindRequest()); t.ok(new BindRequest())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const req = new BindRequest({ const req = new BindRequest({
version: 3, version: 3,
name: dn.parse('cn=root'), name: dn.parse('cn=root'),
credentials: 'secret' credentials: 'secret'
}); })
t.ok(req); t.ok(req)
t.equal(req.version, 3); t.equal(req.version, 3)
t.equal(req.name.toString(), 'cn=root'); t.equal(req.name.toString(), 'cn=root')
t.equal(req.credentials, 'secret'); t.equal(req.credentials, 'secret')
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeInt(3); ber.writeInt(3)
ber.writeString('cn=root'); ber.writeString('cn=root')
ber.writeString('secret', 0x80); ber.writeString('secret', 0x80)
const req = new BindRequest(); const req = new BindRequest()
t.ok(req._parse(new BerReader(ber.buffer))); t.ok(req._parse(new BerReader(ber.buffer)))
t.equal(req.version, 3); t.equal(req.version, 3)
t.equal(req.dn.toString(), 'cn=root'); t.equal(req.dn.toString(), 'cn=root')
t.equal(req.credentials, 'secret'); t.equal(req.credentials, 'secret')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const req = new BindRequest({ const req = new BindRequest({
@ -42,17 +42,17 @@ test('toBer', function (t) {
version: 3, version: 3,
name: dn.parse('cn=root'), name: dn.parse('cn=root'),
credentials: 'secret' credentials: 'secret'
}); })
t.ok(req); t.ok(req)
const ber = new BerReader(req.toBer()); const ber = new BerReader(req.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x60); t.equal(ber.readSequence(), 0x60)
t.equal(ber.readInt(), 0x03); t.equal(ber.readInt(), 0x03)
t.equal(ber.readString(), 'cn=root'); t.equal(ber.readString(), 'cn=root')
t.equal(ber.readString(0x80), 'secret'); t.equal(ber.readString(0x80), 'secret')
t.end(); t.end()
}); })

View File

@ -1,38 +1,38 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { BindResponse } = require('../../lib'); const { BindResponse } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new BindResponse()); t.ok(new BindResponse())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const res = new BindResponse({ const res = new BindResponse({
messageID: 123, messageID: 123,
status: 0 status: 0
}); })
t.ok(res); t.ok(res)
t.equal(res.messageID, 123); t.equal(res.messageID, 123)
t.equal(res.status, 0); t.equal(res.status, 0)
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeEnumeration(0); ber.writeEnumeration(0)
ber.writeString('cn=root'); ber.writeString('cn=root')
ber.writeString('foo'); ber.writeString('foo')
const res = new BindResponse(); const res = new BindResponse()
t.ok(res._parse(new BerReader(ber.buffer))); t.ok(res._parse(new BerReader(ber.buffer)))
t.equal(res.status, 0); t.equal(res.status, 0)
t.equal(res.matchedDN, 'cn=root'); t.equal(res.matchedDN, 'cn=root')
t.equal(res.errorMessage, 'foo'); t.equal(res.errorMessage, 'foo')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const res = new BindResponse({ const res = new BindResponse({
@ -40,17 +40,17 @@ test('toBer', function (t) {
status: 3, status: 3,
matchedDN: 'cn=root', matchedDN: 'cn=root',
errorMessage: 'foo' errorMessage: 'foo'
}); })
t.ok(res); t.ok(res)
const ber = new BerReader(res.toBer()); const ber = new BerReader(res.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x61); t.equal(ber.readSequence(), 0x61)
t.equal(ber.readEnumeration(), 3); t.equal(ber.readEnumeration(), 3)
t.equal(ber.readString(), 'cn=root'); t.equal(ber.readString(), 'cn=root')
t.equal(ber.readString(), 'foo'); t.equal(ber.readString(), 'foo')
t.end(); t.end()
}); })

View File

@ -1,43 +1,43 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { CompareRequest, dn } = require('../../lib'); const { CompareRequest, dn } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new CompareRequest()); t.ok(new CompareRequest())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const req = new CompareRequest({ const req = new CompareRequest({
entry: dn.parse('cn=foo, o=test'), entry: dn.parse('cn=foo, o=test'),
attribute: 'sn', attribute: 'sn',
value: 'testy' value: 'testy'
}); })
t.ok(req); t.ok(req)
t.equal(req.dn.toString(), 'cn=foo, o=test'); t.equal(req.dn.toString(), 'cn=foo, o=test')
t.equal(req.attribute, 'sn'); t.equal(req.attribute, 'sn')
t.equal(req.value, 'testy'); t.equal(req.value, 'testy')
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeString('cn=foo, o=test'); ber.writeString('cn=foo, o=test')
ber.startSequence(); ber.startSequence()
ber.writeString('sn'); ber.writeString('sn')
ber.writeString('testy'); ber.writeString('testy')
ber.endSequence(); ber.endSequence()
const req = new CompareRequest(); const req = new CompareRequest()
t.ok(req._parse(new BerReader(ber.buffer))); t.ok(req._parse(new BerReader(ber.buffer)))
t.equal(req.dn, 'cn=foo, o=test'); t.equal(req.dn, 'cn=foo, o=test')
t.equal(req.attribute, 'sn'); t.equal(req.attribute, 'sn')
t.equal(req.value, 'testy'); t.equal(req.value, 'testy')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const req = new CompareRequest({ const req = new CompareRequest({
@ -45,20 +45,20 @@ test('toBer', function (t) {
entry: dn.parse('cn=foo, o=test'), entry: dn.parse('cn=foo, o=test'),
attribute: 'sn', attribute: 'sn',
value: 'testy' value: 'testy'
}); })
t.ok(req); t.ok(req)
const ber = new BerReader(req.toBer()); const ber = new BerReader(req.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x6e); t.equal(ber.readSequence(), 0x6e)
t.equal(ber.readString(), 'cn=foo, o=test'); t.equal(ber.readString(), 'cn=foo, o=test')
t.ok(ber.readSequence()); t.ok(ber.readSequence())
t.equal(ber.readString(), 'sn'); t.equal(ber.readString(), 'sn')
t.equal(ber.readString(), 'testy'); t.equal(ber.readString(), 'testy')
t.end(); t.end()
}); })

View File

@ -1,38 +1,38 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { CompareResponse } = require('../../lib'); const { CompareResponse } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new CompareResponse()); t.ok(new CompareResponse())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const res = new CompareResponse({ const res = new CompareResponse({
messageID: 123, messageID: 123,
status: 0 status: 0
}); })
t.ok(res); t.ok(res)
t.equal(res.messageID, 123); t.equal(res.messageID, 123)
t.equal(res.status, 0); t.equal(res.status, 0)
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeEnumeration(0); ber.writeEnumeration(0)
ber.writeString('cn=root'); ber.writeString('cn=root')
ber.writeString('foo'); ber.writeString('foo')
const res = new CompareResponse(); const res = new CompareResponse()
t.ok(res._parse(new BerReader(ber.buffer))); t.ok(res._parse(new BerReader(ber.buffer)))
t.equal(res.status, 0); t.equal(res.status, 0)
t.equal(res.matchedDN, 'cn=root'); t.equal(res.matchedDN, 'cn=root')
t.equal(res.errorMessage, 'foo'); t.equal(res.errorMessage, 'foo')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const res = new CompareResponse({ const res = new CompareResponse({
@ -40,17 +40,17 @@ test('toBer', function (t) {
status: 3, status: 3,
matchedDN: 'cn=root', matchedDN: 'cn=root',
errorMessage: 'foo' errorMessage: 'foo'
}); })
t.ok(res); t.ok(res)
const ber = new BerReader(res.toBer()); const ber = new BerReader(res.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x6f); t.equal(ber.readSequence(), 0x6f)
t.equal(ber.readEnumeration(), 3); t.equal(ber.readEnumeration(), 3)
t.equal(ber.readString(), 'cn=root'); t.equal(ber.readString(), 'cn=root')
t.equal(ber.readString(), 'foo'); t.equal(ber.readString(), 'foo')
t.end(); t.end()
}); })

View File

@ -1,47 +1,47 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { DeleteRequest, dn } = require('../../lib'); const { DeleteRequest, dn } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new DeleteRequest()); t.ok(new DeleteRequest())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const req = new DeleteRequest({ const req = new DeleteRequest({
entry: dn.parse('cn=test') entry: dn.parse('cn=test')
}); })
t.ok(req); t.ok(req)
t.equal(req.dn.toString(), 'cn=test'); t.equal(req.dn.toString(), 'cn=test')
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeString('cn=test', 0x4a); ber.writeString('cn=test', 0x4a)
const req = new DeleteRequest(); const req = new DeleteRequest()
const reader = new BerReader(ber.buffer); const reader = new BerReader(ber.buffer)
reader.readSequence(0x4a); reader.readSequence(0x4a)
t.ok(req.parse(reader, reader.length)); t.ok(req.parse(reader, reader.length))
t.equal(req.dn.toString(), 'cn=test'); t.equal(req.dn.toString(), 'cn=test')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const req = new DeleteRequest({ const req = new DeleteRequest({
messageID: 123, messageID: 123,
entry: dn.parse('cn=test') entry: dn.parse('cn=test')
}); })
t.ok(req); t.ok(req)
const ber = new BerReader(req.toBer()); const ber = new BerReader(req.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readString(0x4a), 'cn=test'); t.equal(ber.readString(0x4a), 'cn=test')
t.end(); t.end()
}); })

View File

@ -1,38 +1,38 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { DeleteResponse } = require('../../lib'); const { DeleteResponse } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new DeleteResponse()); t.ok(new DeleteResponse())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const res = new DeleteResponse({ const res = new DeleteResponse({
messageID: 123, messageID: 123,
status: 0 status: 0
}); })
t.ok(res); t.ok(res)
t.equal(res.messageID, 123); t.equal(res.messageID, 123)
t.equal(res.status, 0); t.equal(res.status, 0)
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeEnumeration(0); ber.writeEnumeration(0)
ber.writeString('cn=root'); ber.writeString('cn=root')
ber.writeString('foo'); ber.writeString('foo')
const res = new DeleteResponse(); const res = new DeleteResponse()
t.ok(res._parse(new BerReader(ber.buffer))); t.ok(res._parse(new BerReader(ber.buffer)))
t.equal(res.status, 0); t.equal(res.status, 0)
t.equal(res.matchedDN, 'cn=root'); t.equal(res.matchedDN, 'cn=root')
t.equal(res.errorMessage, 'foo'); t.equal(res.errorMessage, 'foo')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const res = new DeleteResponse({ const res = new DeleteResponse({
@ -40,17 +40,17 @@ test('toBer', function (t) {
status: 3, status: 3,
matchedDN: 'cn=root', matchedDN: 'cn=root',
errorMessage: 'foo' errorMessage: 'foo'
}); })
t.ok(res); t.ok(res)
const ber = new BerReader(res.toBer()); const ber = new BerReader(res.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x6b); t.equal(ber.readSequence(), 0x6b)
t.equal(ber.readEnumeration(), 3); t.equal(ber.readEnumeration(), 3)
t.equal(ber.readString(), 'cn=root'); t.equal(ber.readString(), 'cn=root')
t.equal(ber.readString(), 'foo'); t.equal(ber.readString(), 'foo')
t.end(); t.end()
}); })

View File

@ -1,133 +1,125 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { ExtendedRequest } = require('../../lib'); const { ExtendedRequest } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new ExtendedRequest()); t.ok(new ExtendedRequest())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const req = new ExtendedRequest({ const req = new ExtendedRequest({
requestName: '1.2.3.4', requestName: '1.2.3.4',
requestValue: 'test' requestValue: 'test'
}); })
t.ok(req); t.ok(req)
t.equal(req.requestName, '1.2.3.4'); t.equal(req.requestName, '1.2.3.4')
t.equal(req.requestValue, 'test'); t.equal(req.requestValue, 'test')
t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0)
t.equal(req.value, 'test'); t.equal(req.value, 'test')
t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0)
t.end(); t.end()
}); })
test('new with buffer args', function (t) { test('new with buffer args', function (t) {
const req = new ExtendedRequest({ const req = new ExtendedRequest({
requestName: '1.2.3.4', requestName: '1.2.3.4',
requestValue: Buffer.from('test', 'utf8') requestValue: Buffer.from('test', 'utf8')
}); })
t.ok(req); t.ok(req)
t.equal(req.requestName, '1.2.3.4'); t.equal(req.requestName, '1.2.3.4')
t.equal(req.requestValue, req.requestValueBuffer); t.equal(req.requestValue, req.requestValueBuffer)
t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0)
t.equal(req.value, req.valueBuffer); t.equal(req.value, req.valueBuffer)
t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0)
t.end(); t.end()
}); })
test('new no args set args', function (t) { test('new no args set args', function (t) {
const req = new ExtendedRequest(); const req = new ExtendedRequest()
t.ok(req); t.ok(req)
req.name = '1.2.3.4'; req.name = '1.2.3.4'
t.equal(req.requestName, '1.2.3.4'); t.equal(req.requestName, '1.2.3.4')
req.value = 'test'; req.value = 'test'
t.equal(req.requestValue, 'test'); t.equal(req.requestValue, 'test')
t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0)
t.equal(req.value, 'test'); t.equal(req.value, 'test')
t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0)
t.end();
});
t.end()
})
test('new no args set args buffer', function (t) { test('new no args set args buffer', function (t) {
const req = new ExtendedRequest(); const req = new ExtendedRequest()
t.ok(req); t.ok(req)
req.name = '1.2.3.4'; req.name = '1.2.3.4'
t.equal(req.requestName, '1.2.3.4'); t.equal(req.requestName, '1.2.3.4')
req.value = Buffer.from('test', 'utf8'); req.value = Buffer.from('test', 'utf8')
t.equal(req.requestValue, req.requestValueBuffer); t.equal(req.requestValue, req.requestValueBuffer)
t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0); t.is(Buffer.compare(req.requestValueBuffer, Buffer.from('test', 'utf8')), 0)
t.equal(req.value, req.valueBuffer); t.equal(req.value, req.valueBuffer)
t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0); t.is(Buffer.compare(req.valueBuffer, Buffer.from('test', 'utf8')), 0)
t.end();
});
t.end()
})
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeString('1.2.3.4', 0x80); ber.writeString('1.2.3.4', 0x80)
ber.writeString('test', 0x81); 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 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) { test('toBer', function (t) {
const req = new ExtendedRequest({ const req = new ExtendedRequest({
messageID: 123, messageID: 123,
requestName: '1.2.3.4', requestName: '1.2.3.4',
requestValue: 'test' requestValue: 'test'
}); })
t.ok(req); t.ok(req)
const ber = new BerReader(req.toBer()); const ber = new BerReader(req.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x77); t.equal(ber.readSequence(), 0x77)
t.equal(ber.readString(0x80), '1.2.3.4'); t.equal(ber.readString(0x80), '1.2.3.4')
t.equal(ber.readString(0x81), 'test'); t.equal(ber.readString(0x81), 'test')
t.end();
});
t.end()
})
test('toBer from buffer', function (t) { test('toBer from buffer', function (t) {
const req = new ExtendedRequest({ const req = new ExtendedRequest({
messageID: 123, messageID: 123,
requestName: '1.2.3.4', requestName: '1.2.3.4',
requestValue: Buffer.from('test', 'utf8') requestValue: Buffer.from('test', 'utf8')
}); })
t.ok(req); t.ok(req)
const ber = new BerReader(req.toBer()); const ber = new BerReader(req.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x77); t.equal(ber.readSequence(), 0x77)
t.equal(ber.readString(0x80), '1.2.3.4'); t.equal(ber.readString(0x80), '1.2.3.4')
t.equal(ber.readString(0x81), 'test'); t.equal(ber.readString(0x81), 'test')
t.end(); t.end()
}); })

View File

@ -1,13 +1,13 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { ExtendedResponse } = require('../../lib'); const { ExtendedResponse } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new ExtendedResponse()); t.ok(new ExtendedResponse())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const res = new ExtendedResponse({ const res = new ExtendedResponse({
@ -15,32 +15,32 @@ test('new with args', function (t) {
status: 0, status: 0,
responseName: '1.2.3.4', responseName: '1.2.3.4',
responseValue: 'test' responseValue: 'test'
}); })
t.ok(res); t.ok(res)
t.equal(res.messageID, 123); t.equal(res.messageID, 123)
t.equal(res.status, 0); t.equal(res.status, 0)
t.equal(res.responseName, '1.2.3.4'); t.equal(res.responseName, '1.2.3.4')
t.equal(res.responseValue, 'test'); t.equal(res.responseValue, 'test')
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeEnumeration(0); ber.writeEnumeration(0)
ber.writeString('cn=root'); ber.writeString('cn=root')
ber.writeString('foo'); ber.writeString('foo')
ber.writeString('1.2.3.4', 0x8a); ber.writeString('1.2.3.4', 0x8a)
ber.writeString('test', 0x8b); ber.writeString('test', 0x8b)
const res = new ExtendedResponse(); const res = new ExtendedResponse()
t.ok(res._parse(new BerReader(ber.buffer))); t.ok(res._parse(new BerReader(ber.buffer)))
t.equal(res.status, 0); t.equal(res.status, 0)
t.equal(res.matchedDN, 'cn=root'); t.equal(res.matchedDN, 'cn=root')
t.equal(res.errorMessage, 'foo'); t.equal(res.errorMessage, 'foo')
t.equal(res.responseName, '1.2.3.4'); t.equal(res.responseName, '1.2.3.4')
t.equal(res.responseValue, 'test'); t.equal(res.responseValue, 'test')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const res = new ExtendedResponse({ const res = new ExtendedResponse({
@ -50,19 +50,19 @@ test('toBer', function (t) {
errorMessage: 'foo', errorMessage: 'foo',
responseName: '1.2.3.4', responseName: '1.2.3.4',
responseValue: 'test' responseValue: 'test'
}); })
t.ok(res); t.ok(res)
const ber = new BerReader(res.toBer()); const ber = new BerReader(res.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x78); t.equal(ber.readSequence(), 0x78)
t.equal(ber.readEnumeration(), 3); t.equal(ber.readEnumeration(), 3)
t.equal(ber.readString(), 'cn=root'); t.equal(ber.readString(), 'cn=root')
t.equal(ber.readString(), 'foo'); t.equal(ber.readString(), 'foo')
t.equal(ber.readString(0x8a), '1.2.3.4'); t.equal(ber.readString(0x8a), '1.2.3.4')
t.equal(ber.readString(0x8b), 'test'); t.equal(ber.readString(0x8b), 'test')
t.end(); t.end()
}); })

View File

@ -1,41 +1,41 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { ModifyDNRequest, dn } = require('../../lib'); const { ModifyDNRequest, dn } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new ModifyDNRequest()); t.ok(new ModifyDNRequest())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const req = new ModifyDNRequest({ const req = new ModifyDNRequest({
entry: dn.parse('cn=foo, o=test'), entry: dn.parse('cn=foo, o=test'),
newRdn: dn.parse('cn=foo2'), newRdn: dn.parse('cn=foo2'),
deleteOldRdn: true deleteOldRdn: true
}); })
t.ok(req); t.ok(req)
t.equal(req.dn.toString(), 'cn=foo, o=test'); t.equal(req.dn.toString(), 'cn=foo, o=test')
t.equal(req.newRdn.toString(), 'cn=foo2'); t.equal(req.newRdn.toString(), 'cn=foo2')
t.equal(req.deleteOldRdn, true); t.equal(req.deleteOldRdn, true)
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeString('cn=foo, o=test'); ber.writeString('cn=foo, o=test')
ber.writeString('cn=foo2'); ber.writeString('cn=foo2')
ber.writeBoolean(true); ber.writeBoolean(true)
const req = new ModifyDNRequest(); const req = new ModifyDNRequest()
t.ok(req._parse(new BerReader(ber.buffer))); t.ok(req._parse(new BerReader(ber.buffer)))
t.equal(req.dn.toString(), 'cn=foo, o=test'); t.equal(req.dn.toString(), 'cn=foo, o=test')
t.equal(req.newRdn.toString(), 'cn=foo2'); t.equal(req.newRdn.toString(), 'cn=foo2')
t.equal(req.deleteOldRdn, true); t.equal(req.deleteOldRdn, true)
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const req = new ModifyDNRequest({ const req = new ModifyDNRequest({
@ -43,18 +43,18 @@ test('toBer', function (t) {
entry: dn.parse('cn=foo, o=test'), entry: dn.parse('cn=foo, o=test'),
newRdn: dn.parse('cn=foo2'), newRdn: dn.parse('cn=foo2'),
deleteOldRdn: true deleteOldRdn: true
}); })
t.ok(req); t.ok(req)
const ber = new BerReader(req.toBer()); const ber = new BerReader(req.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x6c); t.equal(ber.readSequence(), 0x6c)
t.equal(ber.readString(), 'cn=foo, o=test'); t.equal(ber.readString(), 'cn=foo, o=test')
t.equal(ber.readString(), 'cn=foo2'); t.equal(ber.readString(), 'cn=foo2')
t.equal(ber.readBoolean(), true); t.equal(ber.readBoolean(), true)
t.end(); t.end()
}); })

View File

@ -1,38 +1,38 @@
'use strict'; 'use strict'
const { test } = require('tap'); const { test } = require('tap')
const { BerReader, BerWriter } = require('asn1'); const { BerReader, BerWriter } = require('asn1')
const { ModifyDNResponse } = require('../../lib'); const { ModifyDNResponse } = require('../../lib')
test('new no args', function (t) { test('new no args', function (t) {
t.ok(new ModifyDNResponse()); t.ok(new ModifyDNResponse())
t.end(); t.end()
}); })
test('new with args', function (t) { test('new with args', function (t) {
const res = new ModifyDNResponse({ const res = new ModifyDNResponse({
messageID: 123, messageID: 123,
status: 0 status: 0
}); })
t.ok(res); t.ok(res)
t.equal(res.messageID, 123); t.equal(res.messageID, 123)
t.equal(res.status, 0); t.equal(res.status, 0)
t.end(); t.end()
}); })
test('parse', function (t) { test('parse', function (t) {
const ber = new BerWriter(); const ber = new BerWriter()
ber.writeEnumeration(0); ber.writeEnumeration(0)
ber.writeString('cn=root'); ber.writeString('cn=root')
ber.writeString('foo'); ber.writeString('foo')
const res = new ModifyDNResponse(); const res = new ModifyDNResponse()
t.ok(res._parse(new BerReader(ber.buffer))); t.ok(res._parse(new BerReader(ber.buffer)))
t.equal(res.status, 0); t.equal(res.status, 0)
t.equal(res.matchedDN, 'cn=root'); t.equal(res.matchedDN, 'cn=root')
t.equal(res.errorMessage, 'foo'); t.equal(res.errorMessage, 'foo')
t.end(); t.end()
}); })
test('toBer', function (t) { test('toBer', function (t) {
const res = new ModifyDNResponse({ const res = new ModifyDNResponse({
@ -40,17 +40,17 @@ test('toBer', function (t) {
status: 3, status: 3,
matchedDN: 'cn=root', matchedDN: 'cn=root',
errorMessage: 'foo' errorMessage: 'foo'
}); })
t.ok(res); t.ok(res)
const ber = new BerReader(res.toBer()); const ber = new BerReader(res.toBer())
t.ok(ber); t.ok(ber)
t.equal(ber.readSequence(), 0x30); t.equal(ber.readSequence(), 0x30)
t.equal(ber.readInt(), 123); t.equal(ber.readInt(), 123)
t.equal(ber.readSequence(), 0x6d); t.equal(ber.readSequence(), 0x6d)
t.equal(ber.readEnumeration(), 3); t.equal(ber.readEnumeration(), 3)
t.equal(ber.readString(), 'cn=root'); t.equal(ber.readString(), 'cn=root')
t.equal(ber.readString(), 'foo'); t.equal(ber.readString(), 'foo')
t.end(); t.end()
}); })

Some files were not shown because too many files have changed in this diff Show More