diff --git a/lib/controls/entry_change_notification_control.js b/lib/controls/entry_change_notification_control.js new file mode 100644 index 0000000..4893021 --- /dev/null +++ b/lib/controls/entry_change_notification_control.js @@ -0,0 +1,93 @@ +var assert = require('assert'); +var util = require('util'); + +var asn1 = require('asn1'); + +var Control = require('./control'); + + + +///--- Globals + +var BerReader = asn1.BerReader; +var BerWriter = asn1.BerWriter; + + + +///--- API + +function EntryChangeNotificationControl(options) { + if (!options) + options = {}; + + options.type = EntryChangeNotificationControl.OID; + if (options.value) { + if (Buffer.isBuffer(options.value)) { + this.parse(options.value); + } else if (typeof(options.value) === 'object') { + this._value = options.value; + } else { + throw new TypeError('options.value must be a Buffer or Object'); + } + options.value = null; + } + Control.call(this, options); + + var self = this; + this.__defineGetter__('value', function() { + return self._value || {}; + }); +} +util.inherits(EntryChangeNotificationControl, Control); +module.exports = EntryChangeNotificationControl; + + +EntryChangeNotificationControl.prototype.parse = function parse(buffer) { + assert.ok(buffer); + + var ber = new BerReader(buffer); + if (ber.readSequence()) { + this._value = { + changeType: ber.readInt() + }; + + // if the operation was moddn, then parse the optional previousDN attr + if (this._value.changeType === 8) + this._value.previousDN = ber.readString(); + + this._value.changeNumber = ber.readInt(); + + return true; + } + + return false; +}; + + +EntryChangeNotificationControl.prototype._toBer = function(ber) { + assert.ok(ber); + + if (!this._value) + return; + + var writer = new BerWriter(); + writer.startSequence(); + writer.writeInt(this.value.changeType); + if (this.value.previousDN) + writer.writeString(this.value.previousDN); + + writer.writeInt(parseInt(this.value.changeNumber, 10)); + writer.endSequence(); + + ber.writeBuffer(writer.buffer, 0x04); +}; + + +EntryChangeNotificationControl.prototype._json = function(obj) { + obj.controlValue = this.value; + return obj; +}; + + + +EntryChangeNotificationControl.OID = '2.16.840.1.113730.3.4.7'; diff --git a/lib/controls/index.js b/lib/controls/index.js index 41d0507..d1fe472 100644 --- a/lib/controls/index.js +++ b/lib/controls/index.js @@ -3,6 +3,8 @@ var assert = require('assert'); var Control = require('./control'); +var EntryChangeNotificationControl = + require('./entry_change_notification_control'); var PersistentSearchControl = require('./persistent_search_control'); @@ -42,6 +44,12 @@ module.exports = { value: value }); break; + case EntryChangeNotificationControl.OID: + control = new EntryChangeNotificationControl({ + critical: critical, + value: value + }); + break; default: control = new Control({ type: type, @@ -54,5 +62,6 @@ module.exports = { }, Control: Control, + EntryChangeNotificationControl: EntryChangeNotificationControl, PersistentSearchControl: PersistentSearchControl }; diff --git a/lib/messages/result.js b/lib/messages/result.js index 36b9632..55624ec 100644 --- a/lib/messages/result.js +++ b/lib/messages/result.js @@ -60,7 +60,6 @@ module.exports = LDAPResult; LDAPResult.prototype.end = function(status) { assert.ok(this.connection); - if (typeof(status) === 'number') this.status = status; diff --git a/lib/messages/search_entry.js b/lib/messages/search_entry.js index d1364ad..c9b8e57 100644 --- a/lib/messages/search_entry.js +++ b/lib/messages/search_entry.js @@ -81,6 +81,8 @@ SearchEntry.prototype.fromObject = function(obj) { throw new TypeError('object required'); var self = this; + if (obj.controls) + this.controls = obj.controls; if (obj.attributes) obj = obj.attributes; diff --git a/lib/messages/search_request.js b/lib/messages/search_request.js index bc720c0..6b03857 100644 --- a/lib/messages/search_request.js +++ b/lib/messages/search_request.js @@ -30,6 +30,7 @@ function SearchRequest(options) { options = {}; } + options.protocolOp = Protocol.LDAP_REQ_SEARCH; LDAPMessage.call(this, options); diff --git a/lib/messages/search_response.js b/lib/messages/search_response.js index 0fa4ce8..8660f4e 100644 --- a/lib/messages/search_response.js +++ b/lib/messages/search_response.js @@ -41,6 +41,8 @@ module.exports = SearchResponse; * Defaults to 'false'. */ SearchResponse.prototype.send = function(entry, nofiltering) { + this.log.info('entry', entry); + this.log.info('nofiltering', nofiltering); if (!entry || typeof(entry) !== 'object') throw new TypeError('entry (SearchEntry) required'); if (nofiltering === undefined) @@ -87,6 +89,7 @@ SearchResponse.prototype.send = function(entry, nofiltering) { } try { + this.log.info('in search response send'); if (this.log.isDebugEnabled()) this.log.debug('%s: sending: %j', this.connection.ldap.id, entry.json); diff --git a/tst/controls/entry_change_notification_control_test.js b/tst/controls/entry_change_notification_control_test.js new file mode 100644 index 0000000..5fc1bb5 --- /dev/null +++ b/tst/controls/entry_change_notification_control_test.js @@ -0,0 +1,88 @@ + +var test = require('tap').test; + +var asn1 = require('asn1'); + +var BerReader = asn1.BerReader; +var BerWriter = asn1.BerWriter; +var getControl; +var EntryChangeNotificationControl; + + + +///--- Tests + + +test('load library', function(t) { + EntryChangeNotificationControl = + require('../../lib').EntryChangeNotificationControl; + t.ok(EntryChangeNotificationControl); + getControl = require('../../lib').getControl; + t.ok(getControl); + t.end(); +}); + + +test('new no args', function(t) { + t.ok(new EntryChangeNotificationControl()); + t.end(); +}); + + +test('new with args', function(t) { + var c = new EntryChangeNotificationControl({ + type: '2.16.840.1.113730.3.4.7', + criticality: true, + value: { + changeType: 8, + previousDN: 'cn=foobarbazcar', + changeNumber: 123456789 + } + }); + t.ok(c); + t.equal(c.type, '2.16.840.1.113730.3.4.7'); + t.ok(c.criticality); + t.equal(c.value.changeType, 8); + t.equal(c.value.previousDN, 'cn=foobarbazcar'); + t.equal(c.value.changeNumber, 123456789); + + + var writer = new BerWriter(); + c.toBer(writer); + var reader = new BerReader(writer.buffer); + var psc = getControl(reader); + t.ok(psc); + console.log('psc', psc.value); + t.equal(psc.type, '2.16.840.1.113730.3.4.7'); + t.ok(psc.criticality); + t.equal(psc.value.changeType, 8); + t.equal(psc.value.previousDN, 'cn=foobarbazcar'); + t.equal(psc.value.changeNumber, 123456789); + + t.end(); +}); + +test('tober', function(t) { + var psc = new EntryChangeNotificationControl({ + type: '2.16.840.1.113730.3.4.7', + criticality: true, + value: { + changeType: 8, + previousDN: 'cn=foobarbazcar', + changeNumber: 123456789 + } + }); + + var ber = new BerWriter(); + psc.toBer(ber); + + var c = getControl(new BerReader(ber.buffer)); + t.ok(c); + t.equal(c.type, '2.16.840.1.113730.3.4.7'); + t.ok(c.criticality); + t.equal(c.value.changeType, 8); + t.equal(c.value.previousDN, 'cn=foobarbazcar'); + t.equal(c.value.changeNumber, 123456789); + + t.end(); +});