added client-side support for paged search

This commit is contained in:
Thomas Vanier 2012-08-13 16:17:54 +01:00
parent 1396c551f8
commit f082c6eed2
2 changed files with 66 additions and 4 deletions

View File

@ -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],

View File

@ -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];