added client-side support for paged search
This commit is contained in:
parent
1396c551f8
commit
f082c6eed2
|
@ -9,11 +9,12 @@ var nopt = require('nopt');
|
|||
|
||||
var ldap = require('../lib/index');
|
||||
|
||||
var bunyan = require('bunyan');
|
||||
|
||||
|
||||
///--- Globals
|
||||
|
||||
var log4js = ldap.log4js;
|
||||
var log = bunyan.createLogger({ name: 'ldap-search' });
|
||||
|
||||
nopt.typeDefs.DN = {
|
||||
type: ldap.DN,
|
||||
|
@ -37,6 +38,7 @@ var opts = {
|
|||
'control': Array,
|
||||
'password': String,
|
||||
'persistent': Boolean,
|
||||
'paged': Number,
|
||||
'scope': String,
|
||||
'timeout': Number,
|
||||
'url': url
|
||||
|
@ -49,6 +51,7 @@ var shortOpts = {
|
|||
'D': ['--binddn'],
|
||||
'w': ['--password'],
|
||||
'p': ['--persistent'],
|
||||
'g': ['--paged'],
|
||||
's': ['--scope'],
|
||||
't': ['--timeout'],
|
||||
'u': ['--url']
|
||||
|
@ -93,7 +96,6 @@ function perror(err) {
|
|||
|
||||
///--- Mainline
|
||||
|
||||
log4js.setGlobalLogLevel('INFO');
|
||||
var parsed;
|
||||
|
||||
try {
|
||||
|
@ -115,7 +117,7 @@ try {
|
|||
|
||||
|
||||
if (parsed.debug)
|
||||
log4js.setGlobalLogLevel(parsed.debug > 1 ? 'TRACE' : 'DEBUG');
|
||||
log.level(parsed.debug > 1 ? 'trace' : 'debug')
|
||||
if (!parsed.url)
|
||||
parsed.url = 'ldap://127.0.0.1:389';
|
||||
if (!parsed.binddn)
|
||||
|
@ -131,7 +133,7 @@ if (!parsed.persistent)
|
|||
|
||||
var client = ldap.createClient({
|
||||
url: parsed.url,
|
||||
log4js: log4js,
|
||||
log: log,
|
||||
timeout: parsed.timeout || false
|
||||
});
|
||||
|
||||
|
@ -166,6 +168,11 @@ client.bind(parsed.binddn, parsed.password, function(err, res) {
|
|||
});
|
||||
controls.push(pCtrl);
|
||||
}
|
||||
if (parsed.paged) {
|
||||
log.info('paged search (size %d)', parsed.paged);
|
||||
var ctrl = new ldap.PagedResultsControl({ value: { size: parsed.paged } });
|
||||
controls.push(ctrl);
|
||||
}
|
||||
var req = {
|
||||
scope: parsed.scope || 'sub',
|
||||
filter: parsed.argv.remain[0],
|
||||
|
|
|
@ -10,6 +10,7 @@ var assert = require('assert-plus');
|
|||
var Attribute = require('../attribute');
|
||||
var Change = require('../change');
|
||||
var Control = require('../controls/index').Control;
|
||||
var PagedResultsControl = require('../controls/index').PagedResultsControl;
|
||||
var Protocol = require('../protocol');
|
||||
var dn = require('../dn');
|
||||
var errors = require('../errors');
|
||||
|
@ -770,6 +771,57 @@ Client.prototype._send = function _send(message, expect, emitter, callback) {
|
|||
return callback(null, obj);
|
||||
} // end function _done(event, obj)
|
||||
|
||||
function _continuePagedSearch(msg) {
|
||||
// this function looks for a paged control in the response msg
|
||||
// and continue searching or not according to RFC 2696 - http://www.ietf.org/rfc/rfc2696.txt
|
||||
if (util.isArray(msg.controls) && msg.controls.length > 0) {
|
||||
log.trace('message has %d controls', msg.controls.length);
|
||||
|
||||
for (var i=0; i<msg.controls.length; i++) {
|
||||
var resControl = msg.controls[i];
|
||||
|
||||
// check paged control in response
|
||||
if (resControl instanceof PagedResultsControl) {
|
||||
log.debug('paged search: end of page');
|
||||
if (resControl.value.cookie && resControl.value.cookie.length > 0) {
|
||||
log.trace('paged search: received cookie in response');
|
||||
|
||||
if (util.isArray(message.controls) && message.controls.length > 0) {
|
||||
for (var j=0; j<message.controls.length; j++) {
|
||||
var reqControl = message.controls[j];
|
||||
|
||||
if (reqControl instanceof PagedResultsControl) {
|
||||
// update request cookie and re-send
|
||||
reqControl.value.cookie = resControl.value.cookie;
|
||||
|
||||
try {
|
||||
log.debug('paged search: continuing');
|
||||
conn.write(message.toBer());
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (timer)
|
||||
clearTimeout(timer);
|
||||
|
||||
log.trace({err: e}, 'Error writing message to socket');
|
||||
callback(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.debug('paged search done');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not a paged search or all pages received
|
||||
return false;
|
||||
|
||||
} // end function _continuePagedSearch(msg)
|
||||
|
||||
function messageCallback(msg) {
|
||||
if (timer)
|
||||
clearTimeout(timer);
|
||||
|
@ -784,6 +836,9 @@ Client.prototype._send = function _send(message, expect, emitter, callback) {
|
|||
var event = msg.constructor.name;
|
||||
event = event[0].toLowerCase() + event.slice(1);
|
||||
return _done(event, msg);
|
||||
} else if (_continuePagedSearch(msg)) {
|
||||
// page search continued, just return for now
|
||||
return;
|
||||
} else {
|
||||
delete conn.ldap.messages[message.messageID];
|
||||
|
||||
|
|
Loading…
Reference in New Issue