Merge remote-tracking branch 'upstream/master'
Conflicts: lib/index.js
This commit is contained in:
commit
763f4630f7
|
@ -0,0 +1,6 @@
|
|||
((nil . ((indent-tabs-mode . nil)
|
||||
(tab-width . 8)
|
||||
(fill-column . 80)))
|
||||
(js-mode . ((js-indent-level . 2)
|
||||
(indent-tabs-mode . nil)
|
||||
)))
|
|
@ -1,5 +1,5 @@
|
|||
build
|
||||
node_modules
|
||||
*.log
|
||||
*.ldif
|
||||
*.tar*
|
||||
docs/pkg
|
||||
*.tar.*
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
[submodule "deps/javascriptlint"]
|
||||
path = deps/javascriptlint
|
||||
url = https://github.com/davepacheco/javascriptlint
|
||||
[submodule "deps/jsstyle"]
|
||||
path = deps/jsstyle
|
||||
url = https://github.com/davepacheco/jsstyle
|
||||
[submodule "deps/restdown"]
|
||||
path = deps/restdown
|
||||
url = https://github.com/trentm/restdown
|
|
@ -0,0 +1,3 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
108
Makefile
108
Makefile
|
@ -1,75 +1,49 @@
|
|||
NAME=ldapjs
|
||||
#
|
||||
# Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
#
|
||||
# Makefile: basic Makefile for template API service
|
||||
#
|
||||
# This Makefile is a template for new repos. It contains only repo-specific
|
||||
# logic and uses included makefiles to supply common targets (javascriptlint,
|
||||
# jsstyle, restdown, etc.), which are used by other repos as well. You may well
|
||||
# need to rewrite most of this file, but you shouldn't need to touch the
|
||||
# included makefiles.
|
||||
#
|
||||
# If you find yourself adding support for new targets that could be useful for
|
||||
# other projects too, you should add these to the original versions of the
|
||||
# included Makefiles (in eng.git) so that other teams can use them too.
|
||||
#
|
||||
|
||||
ifeq ($(VERSION), "")
|
||||
@echo "Use gmake"
|
||||
endif
|
||||
#
|
||||
# Tools
|
||||
#
|
||||
NPM := npm
|
||||
TAP := ./node_modules/.bin/tap
|
||||
|
||||
#
|
||||
# Files
|
||||
#
|
||||
DOC_FILES = client.md \
|
||||
dn.md \
|
||||
errors.md \
|
||||
examples.md \
|
||||
filters.md
|
||||
|
||||
SRC := $(shell pwd)
|
||||
TAR = tar
|
||||
UNAME := $(shell uname)
|
||||
ifeq ($(UNAME), SunOS)
|
||||
TAR = gtar
|
||||
endif
|
||||
JS_FILES := $(shell find lib test -name '*.js')
|
||||
JSL_CONF_NODE = tools/jsl.node.conf
|
||||
JSL_FILES_NODE = $(JS_FILES)
|
||||
JSSTYLE_FILES = $(JS_FILES)
|
||||
JSSTYLE_FLAGS = -f tools/jsstyle.conf
|
||||
|
||||
HAVE_GJSLINT := $(shell which gjslint >/dev/null && echo yes || echo no)
|
||||
NPM := npm_config_tar=$(TAR) npm
|
||||
|
||||
RESTDOWN_VERSION=1.2.13
|
||||
DOCPKGDIR = ./docs/pkg
|
||||
|
||||
RESTDOWN = ./node_modules/.restdown/bin/restdown \
|
||||
-b ./docs/branding \
|
||||
-m ${DOCPKGDIR} \
|
||||
-D mediaroot=media
|
||||
|
||||
.PHONY: dep lint test doc clean all
|
||||
|
||||
all:: test doc
|
||||
|
||||
node_modules/.ldapjs.npm.installed:
|
||||
# Repo-specific targets
|
||||
#
|
||||
.PHONY: all
|
||||
all:
|
||||
$(NPM) install
|
||||
if [[ ! -d node_modules/.restdown ]]; then \
|
||||
git clone git://github.com/trentm/restdown.git node_modules/.restdown; \
|
||||
else \
|
||||
(cd node_modules/.restdown && git fetch origin); \
|
||||
fi
|
||||
@(cd ./node_modules/.restdown && git checkout $(RESTDOWN_VERSION))
|
||||
@touch ./node_modules/.ldapjs.npm.installed
|
||||
|
||||
dep: ./node_modules/.ldapjs.npm.installed
|
||||
|
||||
gjslint:
|
||||
gjslint --nojsdoc -r lib -r tst
|
||||
|
||||
ifeq ($(HAVE_GJSLINT), yes)
|
||||
lint: gjslint
|
||||
else
|
||||
lint:
|
||||
@echo "* * *"
|
||||
@echo "* Warning: Cannot lint with gjslint. Install it from:"
|
||||
@echo "* http://code.google.com/closure/utilities/docs/linter_howto.html"
|
||||
@echo "* * *"
|
||||
endif
|
||||
|
||||
doc: dep
|
||||
@rm -rf ${DOCPKGDIR}
|
||||
@mkdir -p ${DOCPKGDIR}
|
||||
${RESTDOWN} ./docs/client.md
|
||||
${RESTDOWN} ./docs/dn.md
|
||||
${RESTDOWN} ./docs/errors.md
|
||||
${RESTDOWN} ./docs/examples.md
|
||||
${RESTDOWN} ./docs/filters.md
|
||||
${RESTDOWN} ./docs/guide.md
|
||||
${RESTDOWN} ./docs/index.md
|
||||
${RESTDOWN} ./docs/server.md
|
||||
rm docs/*.json
|
||||
mv docs/*.html ${DOCPKGDIR}
|
||||
(cd ${DOCPKGDIR} && $(TAR) -czf ${SRC}/${NAME}-docs-`git log -1 --pretty='format:%h'`.tar.gz *)
|
||||
|
||||
|
||||
test: dep lint
|
||||
.PHONY: test
|
||||
test:
|
||||
$(NPM) test
|
||||
|
||||
clean:
|
||||
@rm -fr ${DOCPKGDIR} node_modules *.log *.tar.gz
|
||||
include ./Makefile.deps
|
||||
include ./Makefile.targ
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
#
|
||||
# Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
#
|
||||
# Makefile.deps: Makefile for including common tools as dependencies
|
||||
#
|
||||
|
||||
#
|
||||
# javascriptlint
|
||||
#
|
||||
JSL_SCRIPT = deps/javascriptlint/build/install/jsl
|
||||
JSL = python $(JSL_SCRIPT)
|
||||
|
||||
$(JSL_SCRIPT): | deps/javascriptlint/.git
|
||||
cd deps/javascriptlint && make install
|
||||
|
||||
deps/javascriptlint/.git:
|
||||
git submodule update --init deps/javascriptlint
|
||||
|
||||
#
|
||||
# jsstyle
|
||||
#
|
||||
JSSTYLE_SCRIPT = deps/jsstyle/jsstyle
|
||||
JSSTYLE = $(JSSTYLE_SCRIPT)
|
||||
|
||||
deps/jsstyle/jsstyle:
|
||||
git submodule update --init deps/jsstyle
|
||||
|
||||
#
|
||||
# restdown
|
||||
#
|
||||
RESTDOWN = python deps/restdown/bin/restdown
|
||||
|
||||
$(RESTDOWN): | deps/restdown/.git
|
||||
|
||||
deps/restdown/.git:
|
||||
git submodule update --init deps/restdown
|
||||
|
||||
#
|
||||
# The restdown submodule should be updated before we build "docs".
|
||||
#
|
||||
docs: $(RESTDOWN)
|
||||
|
||||
#
|
||||
# JSL and JSSTYLE must be around before we build "check".
|
||||
#
|
||||
check: $(JSL_SCRIPT) $(JSSTYLE)
|
|
@ -0,0 +1,220 @@
|
|||
#
|
||||
# Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
#
|
||||
# Makefile.targ: common targets.
|
||||
#
|
||||
# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped
|
||||
# into other repos as-is without requiring any modifications. If you find
|
||||
# yourself changing this file, you should instead update the original copy in
|
||||
# eng.git and then update your repo to use the new version.
|
||||
#
|
||||
# This Makefile defines several useful targets and rules. You can use it by
|
||||
# including it from a Makefile that specifies some of the variables below.
|
||||
#
|
||||
# Targets defined in this Makefile:
|
||||
#
|
||||
# check Checks JavaScript files for lint and style
|
||||
# Checks bash scripts for syntax
|
||||
# Checks SMF manifests for validity against the SMF DTD
|
||||
#
|
||||
# clean Removes built files
|
||||
#
|
||||
# docs Builds restdown documentation in docs/
|
||||
#
|
||||
# prepush Depends on "check" and "test"
|
||||
#
|
||||
# test Does nothing (you should override this)
|
||||
#
|
||||
# xref Generates cscope (source cross-reference index)
|
||||
#
|
||||
# For details on what these targets are supposed to do, see the Joyent
|
||||
# Engineering Guide.
|
||||
#
|
||||
# To make use of these targets, you'll need to set some of these variables. Any
|
||||
# variables left unset will simply not be used.
|
||||
#
|
||||
# BASH_FILES Bash scripts to check for syntax
|
||||
# (paths relative to top-level Makefile)
|
||||
#
|
||||
# CLEAN_FILES Files to remove as part of the "clean" target. Note
|
||||
# that files generated by targets in this Makefile are
|
||||
# automatically included in CLEAN_FILES. These include
|
||||
# restdown-generated HTML and JSON files.
|
||||
#
|
||||
# DOC_FILES Restdown (documentation source) files. These are
|
||||
# assumed to be contained in "docs/", and must NOT
|
||||
# contain the "docs/" prefix.
|
||||
#
|
||||
# JSL_CONF_NODE Specify JavaScriptLint configuration files
|
||||
# JSL_CONF_WEB (paths relative to top-level Makefile)
|
||||
#
|
||||
# Node.js and Web configuration files are separate
|
||||
# because you'll usually want different global variable
|
||||
# configurations. If no file is specified, none is given
|
||||
# to jsl, which causes it to use a default configuration,
|
||||
# which probably isn't what you want.
|
||||
#
|
||||
# JSL_FILES_NODE JavaScript files to check with Node config file.
|
||||
# JSL_FILES_WEB JavaScript files to check with Web config file.
|
||||
#
|
||||
# SMF_MANIFESTS XML files to check for validity using the SMF DTD.
|
||||
#
|
||||
# You can also override these variables:
|
||||
#
|
||||
# BASH Path to bash (default: bash)
|
||||
#
|
||||
# JSL Path to JavaScriptLint (default: "jsl")
|
||||
#
|
||||
# JSL_FLAGS_NODE Additional flags to pass through to JSL
|
||||
# JSL_FLAGS_WEB
|
||||
# JSL_FLAGS
|
||||
#
|
||||
# JSSTYLE Path to jsstyle (default: jsstyle)
|
||||
#
|
||||
# JSSTYLE_FLAGS Additional flags to pass through to jsstyle
|
||||
#
|
||||
|
||||
#
|
||||
# Defaults for the various tools we use.
|
||||
#
|
||||
BASH ?= bash
|
||||
CP ?= cp
|
||||
JSL ?= jsl
|
||||
JSSTYLE ?= jsstyle
|
||||
MKDIR ?= mkdir -p
|
||||
MV ?= mv
|
||||
RESTDOWN ?= restdown
|
||||
RMTREE ?= rm -rf
|
||||
JSL_FLAGS ?= --nologo --nosummary
|
||||
|
||||
#
|
||||
# Defaults for other fixed values.
|
||||
#
|
||||
DOC_BUILD = build/docs/public
|
||||
|
||||
#
|
||||
# Configure JSL_FLAGS_{NODE,WEB} based on JSL_CONF_{NODE,WEB}.
|
||||
#
|
||||
ifneq ($(origin JSL_CONF_NODE), undefined)
|
||||
JSL_FLAGS_NODE += --conf=$(JSL_CONF_NODE)
|
||||
endif
|
||||
|
||||
ifneq ($(origin JSL_CONF_WEB), undefined)
|
||||
JSL_FLAGS_WEB += --conf=$(JSL_CONF_WEB)
|
||||
endif
|
||||
|
||||
.PHONY: check-jsl check-jsl-node check-jsl-web
|
||||
check-jsl: check-jsl-node check-jsl-web
|
||||
|
||||
check-jsl-node: $(JSL_FILES_NODE:%=%.jslnodechk)
|
||||
|
||||
check-jsl-web: $(JSL_FILES_WEB:%=%.jslwebchk)
|
||||
|
||||
%.jslnodechk: % $(JSL_SCRIPT)
|
||||
$(JSL) $(JSL_FLAGS) $(JSL_FLAGS_NODE) $<
|
||||
|
||||
%.jslwebchk: % $(JSL_SCRIPT)
|
||||
$(JSL) $(JSL_FLAGS) $(JSL_FLAGS_WEB) $<
|
||||
|
||||
.PHONY: check-jsstyle
|
||||
check-jsstyle: $(JSSTYLE_FILES:%=%.jsstylechk)
|
||||
|
||||
%.jsstylechk: % $(JSSTYLE_SCRIPT)
|
||||
$(JSSTYLE) $(JSSTYLE_FLAGS) $<
|
||||
|
||||
.PHONY: check
|
||||
check: check-jsl check-jsstyle
|
||||
@echo check ok
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-$(RMTREE) $(CLEAN_FILES)
|
||||
|
||||
#
|
||||
# The "docs" target is complicated because we do several things here:
|
||||
#
|
||||
# (1) Use restdown to build HTML and JSON files from each of DOC_FILES.
|
||||
#
|
||||
# (2) Copy these files into $(DOC_BUILD) (build/docs/public), which
|
||||
# functions as a complete copy of the documentation that could be
|
||||
# mirrored or served over HTTP.
|
||||
#
|
||||
# (3) Then copy any directories and media from docs/media into
|
||||
# $(DOC_BUILD)/media. This allows projects to include their own media,
|
||||
# including files that will override same-named files provided by
|
||||
# restdown.
|
||||
#
|
||||
# Step (3) is the surprisingly complex part: in order to do this, we need to
|
||||
# identify the subdirectories in docs/media, recreate them in
|
||||
# $(DOC_BUILD)/media, then do the same with the files.
|
||||
#
|
||||
DOC_MEDIA_DIRS := $(shell find docs/branding/media -type d | grep -v "^docs/branding/media$$")
|
||||
DOC_MEDIA_DIRS := $(DOC_MEDIA_DIRS:docs/branding/media/%=%)
|
||||
DOC_MEDIA_DIRS_BUILD := $(DOC_MEDIA_DIRS:%=$(DOC_BUILD)/media/%)
|
||||
|
||||
DOC_MEDIA_FILES := $(shell find docs/branding/media -type f)
|
||||
DOC_MEDIA_FILES := $(DOC_MEDIA_FILES:docs/media/%=%)
|
||||
DOC_MEDIA_FILES_BUILD := $(DOC_MEDIA_FILES:%=$(DOC_BUILD)/media/%)
|
||||
|
||||
#
|
||||
# Like the other targets, "docs" just depends on the final files we want to
|
||||
# create in $(DOC_BUILD), leveraging other targets and recipes to define how
|
||||
# to get there.
|
||||
#
|
||||
.PHONY: docs
|
||||
docs: \
|
||||
$(DOC_FILES:%.md=$(DOC_BUILD)/%.html) \
|
||||
$(DOC_FILES:%.md=$(DOC_BUILD)/%.json) \
|
||||
$(DOC_MEDIA_FILES_BUILD)
|
||||
|
||||
#
|
||||
# We keep the intermediate files so that the next build can see whether the
|
||||
# files in DOC_BUILD are up to date.
|
||||
#
|
||||
.PRECIOUS: \
|
||||
$(DOC_FILES:%.md=docs/%.html) \
|
||||
$(DOC_FILES:%.md=docs/%json)
|
||||
|
||||
#
|
||||
# We do clean those intermediate files, as well as all of DOC_BUILD.
|
||||
#
|
||||
CLEAN_FILES += \
|
||||
$(DOC_BUILD) \
|
||||
$(DOC_FILES:%.md=docs/%.html) \
|
||||
$(DOC_FILES:%.md=docs/%.json)
|
||||
|
||||
#
|
||||
# Before installing the files, we must make sure the directories exist. The |
|
||||
# syntax tells make that the dependency need only exist, not be up to date.
|
||||
# Otherwise, it might try to rebuild spuriously because the directory itself
|
||||
# appears out of date.
|
||||
#
|
||||
$(DOC_MEDIA_FILES_BUILD): | $(DOC_MEDIA_DIRS_BUILD)
|
||||
|
||||
$(DOC_BUILD)/%: docs/% | $(DOC_BUILD)
|
||||
$(CP) $< $@
|
||||
$(RM) $<
|
||||
|
||||
docs/%.json docs/%.html: docs/%.md | $(DOC_BUILD)
|
||||
$(RESTDOWN) -b ./docs/branding -m $(DOC_BUILD) $<
|
||||
|
||||
$(DOC_BUILD):
|
||||
$(MKDIR) $@
|
||||
|
||||
info:
|
||||
echo "DOC_MEDIA_FILES is '$(DOC_MEDIA_FILES)'"
|
||||
echo "DOC_MEDIA_FILES_BUILD is '$(DOC_MEDIA_FILES_BUILD)'"
|
||||
|
||||
$(DOC_MEDIA_DIRS_BUILD):
|
||||
$(MKDIR) $@
|
||||
|
||||
#
|
||||
# The default "test" target does nothing. This should usually be overridden by
|
||||
# the parent Makefile. It's included here so we can define "prepush" without
|
||||
# requiring the repo to define "test".
|
||||
#
|
||||
.PHONY: test
|
||||
test:
|
||||
|
||||
.PHONY: prepush
|
||||
prepush: check test
|
|
@ -38,6 +38,7 @@ var opts = {
|
|||
'password': String,
|
||||
'persistent': Boolean,
|
||||
'scope': String,
|
||||
'timeout': Number,
|
||||
'url': url
|
||||
};
|
||||
|
||||
|
@ -49,6 +50,7 @@ var shortOpts = {
|
|||
'w': ['--password'],
|
||||
'p': ['--persistent'],
|
||||
's': ['--scope'],
|
||||
't': ['--timeout'],
|
||||
'u': ['--url']
|
||||
};
|
||||
|
||||
|
@ -129,13 +131,19 @@ if (!parsed.persistent)
|
|||
|
||||
var client = ldap.createClient({
|
||||
url: parsed.url,
|
||||
log4js: log4js
|
||||
log4js: log4js,
|
||||
timeout: parsed.timeout || false
|
||||
});
|
||||
|
||||
client.on('error', function(err) {
|
||||
perror(err);
|
||||
});
|
||||
|
||||
client.on('timeout', function(req) {
|
||||
process.stderr.write('Timeout reached\n');
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
client.bind(parsed.binddn, parsed.password, function(err, res) {
|
||||
if (err)
|
||||
perror(err);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 5693fd3ce6f31f66f85bfde275ab64e609ea04d0
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ab8f1fc8d90db8484bbed8a526ff40add5aa1c15
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 14131f6b33bf45a04b4c66e388d0ce1f3e5b55ef
|
|
@ -28,7 +28,8 @@ client is:
|
|||
||url|| a valid LDAP url.||
|
||||
||socketPath|| If you're running an LDAP server over a Unix Domain Socket, use this.||
|
||||
||log4js|| You can optionally pass in a log4js instance the client will use to acquire a logger. The client logs all messages at the `Trace` level.||
|
||||
||numConnections||The size of the connection pool. Default is 1.||
|
||||
||timeout||How long the client should let operations live for before timing out. Default is Infinity.||
|
||||
||connectTimeout||How long the client should wait before timing out on TCP connections. Default is up to the OS.||
|
||||
||reconnect||Whether or not to automatically reconnect (and rebind) on socket errors. Takes amount of time in millliseconds. Default is 1000. 0/false will disable altogether.||
|
||||
|
||||
## Connection management
|
||||
|
@ -45,6 +46,14 @@ operations be allowed back through; in the meantime all callbacks will receive
|
|||
a `DisconnectedError`. If you never called `bind`, the client will allow
|
||||
operations when the socket is connected.
|
||||
|
||||
Also, note that the client will emit a `timeout` event if an operation
|
||||
times out, and you'll be passed in the request object that was offending. You
|
||||
probably don't _need_ to listen on it, as the client will also return an error
|
||||
in the callback of that request. However, it is useful if you want to have a
|
||||
catch-all. An event of `connectTimout` will be emitted when the client fails to
|
||||
get a socket in time; there are no arguments. Note that this event will be
|
||||
emitted (potentially) in reconnect scenarios as well.
|
||||
|
||||
## Common patterns
|
||||
|
||||
The last two parameters in every API are `controls` and `callback`. `controls`
|
||||
|
|
|
@ -12,9 +12,9 @@ var Protocol = require('./protocol');
|
|||
|
||||
function Attribute(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.type && typeof(options.type) !== 'string')
|
||||
if (options.type && typeof (options.type) !== 'string')
|
||||
throw new TypeError('options.type must be a string');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -25,10 +25,11 @@ function Attribute(options) {
|
|||
this.type = options.type || '';
|
||||
this._vals = [];
|
||||
|
||||
this.__defineGetter__('vals', function() {
|
||||
this.__defineGetter__('vals', function () {
|
||||
var _vals = [];
|
||||
|
||||
self._vals.forEach(function(v) {
|
||||
self._vals.forEach(function (v) {
|
||||
/* JSSTYLED */
|
||||
if (/;binary$/.test(self.type)) {
|
||||
_vals.push(v.toString('base64'));
|
||||
} else {
|
||||
|
@ -39,9 +40,9 @@ function Attribute(options) {
|
|||
return _vals;
|
||||
});
|
||||
|
||||
this.__defineSetter__('vals', function(vals) {
|
||||
this.__defineSetter__('vals', function (vals) {
|
||||
if (Array.isArray(vals)) {
|
||||
vals.forEach(function(v) {
|
||||
vals.forEach(function (v) {
|
||||
self.addValue(v);
|
||||
});
|
||||
} else {
|
||||
|
@ -49,11 +50,11 @@ function Attribute(options) {
|
|||
}
|
||||
});
|
||||
|
||||
this.__defineGetter__('buffers', function() {
|
||||
this.__defineGetter__('buffers', function () {
|
||||
return self._vals;
|
||||
});
|
||||
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: self.type,
|
||||
vals: self.vals
|
||||
|
@ -67,11 +68,12 @@ function Attribute(options) {
|
|||
module.exports = Attribute;
|
||||
|
||||
|
||||
Attribute.prototype.addValue = function(val) {
|
||||
Attribute.prototype.addValue = function (val) {
|
||||
if (Buffer.isBuffer(val)) {
|
||||
this._vals.push(val);
|
||||
} else {
|
||||
var encoding = 'utf8';
|
||||
/* JSSTYLED */
|
||||
if (/;binary$/.test(this.type))
|
||||
encoding = 'base64';
|
||||
this._vals.push(new Buffer(val + '', encoding));
|
||||
|
@ -79,7 +81,8 @@ Attribute.prototype.addValue = function(val) {
|
|||
};
|
||||
|
||||
|
||||
Attribute.compare = function(a, b) {
|
||||
/* BEGIN JSSTYLED */
|
||||
Attribute.compare = function compare(a, b) {
|
||||
if (!(a instanceof Attribute) || !(b instanceof Attribute))
|
||||
throw new TypeError('can only compare Attributes');
|
||||
|
||||
|
@ -95,9 +98,10 @@ Attribute.compare = function(a, b) {
|
|||
|
||||
return 0;
|
||||
};
|
||||
/* END JSSTYLED */
|
||||
|
||||
|
||||
Attribute.prototype.parse = function(ber) {
|
||||
Attribute.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.readSequence();
|
||||
|
@ -115,14 +119,14 @@ Attribute.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
Attribute.prototype.toBer = function(ber) {
|
||||
Attribute.prototype.toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.startSequence();
|
||||
ber.writeString(this.type);
|
||||
ber.startSequence(Protocol.LBER_SET);
|
||||
if (this._vals.length) {
|
||||
this._vals.forEach(function(b) {
|
||||
this._vals.forEach(function (b) {
|
||||
ber.writeByte(asn1.Ber.OctetString);
|
||||
ber.writeLength(b.length);
|
||||
for (var i = 0; i < b.length; i++)
|
||||
|
@ -137,25 +141,28 @@ Attribute.prototype.toBer = function(ber) {
|
|||
return ber;
|
||||
};
|
||||
|
||||
Attribute.toBer = function(attr, ber) {
|
||||
Attribute.toBer = function (attr, ber) {
|
||||
return Attribute.prototype.toBer.call(attr, ber);
|
||||
};
|
||||
|
||||
|
||||
Attribute.isAttribute = function(attr) {
|
||||
/* BEGIN JSSTYLED */
|
||||
Attribute.isAttribute = function (attr) {
|
||||
if (!attr) return false;
|
||||
if (typeof(attr) !== 'object') return false;
|
||||
if (typeof (attr) !== 'object') return false;
|
||||
if (attr instanceof Attribute) return true;
|
||||
if (!attr.type || typeof(attr.type) !== 'string') return false;
|
||||
if (!attr.type || typeof (attr.type) !== 'string') return false;
|
||||
if (!attr.vals || !Array.isArray(attr.vals)) return false;
|
||||
for (var i = 0; i < attr.vals.length; i++)
|
||||
if (typeof(attr.vals[i]) !== 'string' && !Buffer.isBuffer(attr.vals[i]))
|
||||
for (var i = 0; i < attr.vals.length; i++) {
|
||||
if (typeof (attr.vals[i]) !== 'string' && !Buffer.isBuffer(attr.vals[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
/* END JSSTLYED */
|
||||
|
||||
|
||||
Attribute.prototype.toString = function() {
|
||||
Attribute.prototype.toString = function () {
|
||||
return JSON.stringify(this.json);
|
||||
};
|
||||
|
|
|
@ -11,16 +11,18 @@ var Protocol = require('./protocol');
|
|||
|
||||
function Change(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.operation && typeof(options.operation) !== 'string')
|
||||
if (options.operation && typeof (options.operation) !== 'string')
|
||||
throw new TypeError('options.operation must be a string');
|
||||
} else {
|
||||
options = {};
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('operation', function() {
|
||||
this._modification = false;
|
||||
|
||||
this.__defineGetter__('operation', function () {
|
||||
switch (self._operation) {
|
||||
case 0x00: return 'add';
|
||||
case 0x01: return 'delete';
|
||||
|
@ -29,8 +31,8 @@ function Change(options) {
|
|||
throw new Error('0x' + self._operation.toString(16) + ' is invalid');
|
||||
}
|
||||
});
|
||||
this.__defineSetter__('operation', function(val) {
|
||||
if (typeof(val) !== 'string')
|
||||
this.__defineSetter__('operation', function (val) {
|
||||
if (typeof (val) !== 'string')
|
||||
throw new TypeError('operation must be a string');
|
||||
|
||||
switch (val.toLowerCase()) {
|
||||
|
@ -47,10 +49,11 @@ function Change(options) {
|
|||
throw new Error('Invalid operation type: 0x' + val.toString(16));
|
||||
}
|
||||
});
|
||||
this.__defineGetter__('modification', function() {
|
||||
this.__defineGetter__('modification', function () {
|
||||
return self._modification;
|
||||
});
|
||||
this.__defineSetter__('modification', function(attr) {
|
||||
|
||||
this.__defineSetter__('modification', function (attr) {
|
||||
if (Attribute.isAttribute(attr)) {
|
||||
self._modification = attr;
|
||||
return;
|
||||
|
@ -59,10 +62,10 @@ function Change(options) {
|
|||
if (keys.length > 1)
|
||||
throw new Error('Only one attribute per Change allowed');
|
||||
|
||||
keys.forEach(function(k) {
|
||||
keys.forEach(function (k) {
|
||||
var _attr = new Attribute({type: k});
|
||||
if (Array.isArray(attr[k])) {
|
||||
attr[k].forEach(function(v) {
|
||||
attr[k].forEach(function (v) {
|
||||
_attr.addValue(v.toString());
|
||||
});
|
||||
} else {
|
||||
|
@ -71,7 +74,7 @@ function Change(options) {
|
|||
self._modification = _attr;
|
||||
});
|
||||
});
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
operation: self.operation,
|
||||
modification: self._modification ? self._modification.json : {}
|
||||
|
@ -84,18 +87,20 @@ function Change(options) {
|
|||
module.exports = Change;
|
||||
|
||||
|
||||
Change.compare = function(a, b) {
|
||||
Change.compare = function (a, b) {
|
||||
if (!(a instanceof Change) || !(b instanceof Change))
|
||||
throw new TypeError('can only compare Changes');
|
||||
|
||||
if (a.operation < b.operation) return -1;
|
||||
if (a.operation > b.operation) return 1;
|
||||
if (a.operation < b.operation)
|
||||
return -1;
|
||||
if (a.operation > b.operation)
|
||||
return 1;
|
||||
|
||||
return Attribute.compare(a.modification, b.modification);
|
||||
};
|
||||
|
||||
|
||||
Change.prototype.parse = function(ber) {
|
||||
Change.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.readSequence();
|
||||
|
@ -107,7 +112,7 @@ Change.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
Change.prototype.toBer = function(ber) {
|
||||
Change.prototype.toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.startSequence();
|
||||
|
|
711
lib/client.js
711
lib/client.js
File diff suppressed because it is too large
Load Diff
|
@ -19,14 +19,14 @@ var Ber = asn1.Ber;
|
|||
|
||||
function Control(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.type && typeof(options.type) !== 'string')
|
||||
if (options.type && typeof (options.type) !== 'string')
|
||||
throw new TypeError('options.type must be a string');
|
||||
if (options.criticality !== undefined &&
|
||||
typeof(options.criticality) !== 'boolean')
|
||||
typeof (options.criticality) !== 'boolean')
|
||||
throw new TypeError('options.criticality must be a boolean');
|
||||
if (options.value && typeof(options.value) !== 'string')
|
||||
if (options.value && typeof (options.value) !== 'string')
|
||||
throw new TypeError('options.value must be a string');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -37,25 +37,25 @@ function Control(options) {
|
|||
this.value = options.value || null;
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
var obj = {
|
||||
controlType: self.type,
|
||||
criticality: self.criticality,
|
||||
controlValue: self.value
|
||||
};
|
||||
return (typeof(self._json) === 'function' ? self._json(obj) : obj);
|
||||
return (typeof (self._json) === 'function' ? self._json(obj) : obj);
|
||||
});
|
||||
}
|
||||
module.exports = Control;
|
||||
|
||||
|
||||
Control.prototype.toBer = function(ber) {
|
||||
Control.prototype.toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.startSequence();
|
||||
ber.writeString(this.type || '');
|
||||
ber.writeBoolean(this.criticality);
|
||||
if (typeof(this._toBer) === 'function') {
|
||||
if (typeof (this._toBer) === 'function') {
|
||||
this._toBer(ber);
|
||||
} else {
|
||||
if (this.value)
|
||||
|
@ -67,6 +67,6 @@ Control.prototype.toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
Control.prototype.toString = function() {
|
||||
Control.prototype.toString = function () {
|
||||
return this.json;
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@ function EntryChangeNotificationControl(options) {
|
|||
if (options.value) {
|
||||
if (Buffer.isBuffer(options.value)) {
|
||||
this.parse(options.value);
|
||||
} else if (typeof(options.value) === 'object') {
|
||||
} else if (typeof (options.value) === 'object') {
|
||||
this._value = options.value;
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object');
|
||||
|
@ -34,7 +34,7 @@ function EntryChangeNotificationControl(options) {
|
|||
Control.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('value', function() {
|
||||
this.__defineGetter__('value', function () {
|
||||
return self._value || {};
|
||||
});
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ EntryChangeNotificationControl.prototype.parse = function parse(buffer) {
|
|||
};
|
||||
|
||||
|
||||
EntryChangeNotificationControl.prototype._toBer = function(ber) {
|
||||
EntryChangeNotificationControl.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
if (!this._value)
|
||||
|
@ -83,7 +83,7 @@ EntryChangeNotificationControl.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
EntryChangeNotificationControl.prototype._json = function(obj) {
|
||||
EntryChangeNotificationControl.prototype._json = function (obj) {
|
||||
obj.controlValue = this.value;
|
||||
return obj;
|
||||
};
|
||||
|
|
|
@ -56,6 +56,7 @@ module.exports = {
|
|||
critical: critical,
|
||||
value: value ? value.toString('utf8') : null
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
return control;
|
||||
|
|
|
@ -26,7 +26,7 @@ function PersistentSearchControl(options) {
|
|||
if (options.value) {
|
||||
if (Buffer.isBuffer(options.value)) {
|
||||
this.parse(options.value);
|
||||
} else if (typeof(options.value) === 'object') {
|
||||
} else if (typeof (options.value) === 'object') {
|
||||
this._value = options.value;
|
||||
} else {
|
||||
throw new TypeError('options.value must be a Buffer or Object');
|
||||
|
@ -36,7 +36,7 @@ function PersistentSearchControl(options) {
|
|||
Control.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('value', function() {
|
||||
this.__defineGetter__('value', function () {
|
||||
return self._value || {};
|
||||
});
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ PersistentSearchControl.prototype.parse = function parse(buffer) {
|
|||
};
|
||||
|
||||
|
||||
PersistentSearchControl.prototype._toBer = function(ber) {
|
||||
PersistentSearchControl.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
if (!this._value)
|
||||
|
@ -79,7 +79,7 @@ PersistentSearchControl.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
PersistentSearchControl.prototype._json = function(obj) {
|
||||
PersistentSearchControl.prototype._json = function (obj) {
|
||||
obj.controlValue = this.value;
|
||||
return obj;
|
||||
};
|
||||
|
|
48
lib/dn.js
48
lib/dn.js
|
@ -25,18 +25,18 @@ function RDN(obj) {
|
|||
var self = this;
|
||||
|
||||
if (obj) {
|
||||
Object.keys(obj).forEach(function(k) {
|
||||
Object.keys(obj).forEach(function (k) {
|
||||
self[k.toLowerCase()] = obj[k];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RDN.prototype.toString = function() {
|
||||
RDN.prototype.toString = function () {
|
||||
var self = this;
|
||||
|
||||
var str = '';
|
||||
Object.keys(this).forEach(function(k) {
|
||||
Object.keys(this).forEach(function (k) {
|
||||
if (str.length)
|
||||
str += '+';
|
||||
|
||||
|
@ -48,7 +48,7 @@ RDN.prototype.toString = function() {
|
|||
|
||||
// Thank you OpenJDK!
|
||||
function parse(name) {
|
||||
if (typeof(name) !== 'string')
|
||||
if (typeof (name) !== 'string')
|
||||
throw new TypeError('name (string) required');
|
||||
|
||||
var cur = 0;
|
||||
|
@ -190,30 +190,30 @@ function parse(name) {
|
|||
function DN(rdns) {
|
||||
if (!Array.isArray(rdns))
|
||||
throw new TypeError('rdns ([object]) required');
|
||||
rdns.forEach(function(rdn) {
|
||||
if (typeof(rdn) !== 'object')
|
||||
rdns.forEach(function (rdn) {
|
||||
if (typeof (rdn) !== 'object')
|
||||
throw new TypeError('rdns ([object]) required');
|
||||
});
|
||||
|
||||
this.rdns = rdns.slice();
|
||||
|
||||
this.__defineGetter__('length', function() {
|
||||
this.__defineGetter__('length', function () {
|
||||
return this.rdns.length;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
DN.prototype.toString = function() {
|
||||
DN.prototype.toString = function () {
|
||||
var _dn = [];
|
||||
this.rdns.forEach(function(rdn) {
|
||||
this.rdns.forEach(function (rdn) {
|
||||
_dn.push(rdn.toString());
|
||||
});
|
||||
return _dn.join(', ');
|
||||
};
|
||||
|
||||
|
||||
DN.prototype.childOf = function(dn) {
|
||||
if (typeof(dn) !== 'object')
|
||||
DN.prototype.childOf = function (dn) {
|
||||
if (typeof (dn) !== 'object')
|
||||
dn = parse(dn);
|
||||
|
||||
if (this.rdns.length <= dn.rdns.length)
|
||||
|
@ -239,8 +239,8 @@ DN.prototype.childOf = function(dn) {
|
|||
};
|
||||
|
||||
|
||||
DN.prototype.parentOf = function(dn) {
|
||||
if (typeof(dn) !== 'object')
|
||||
DN.prototype.parentOf = function (dn) {
|
||||
if (typeof (dn) !== 'object')
|
||||
dn = parse(dn);
|
||||
|
||||
if (!this.rdns.length || this.rdns.length >= dn.rdns.length)
|
||||
|
@ -266,8 +266,8 @@ DN.prototype.parentOf = function(dn) {
|
|||
};
|
||||
|
||||
|
||||
DN.prototype.equals = function(dn) {
|
||||
if (typeof(dn) !== 'object')
|
||||
DN.prototype.equals = function (dn) {
|
||||
if (typeof (dn) !== 'object')
|
||||
dn = parse(dn);
|
||||
|
||||
if (this.rdns.length !== dn.rdns.length)
|
||||
|
@ -296,7 +296,7 @@ DN.prototype.equals = function(dn) {
|
|||
};
|
||||
|
||||
|
||||
DN.prototype.parent = function() {
|
||||
DN.prototype.parent = function () {
|
||||
if (this.rdns.length > 1) {
|
||||
var save = this.rdns.shift();
|
||||
var dn = new DN(this.rdns);
|
||||
|
@ -308,37 +308,37 @@ DN.prototype.parent = function() {
|
|||
};
|
||||
|
||||
|
||||
DN.prototype.clone = function() {
|
||||
DN.prototype.clone = function () {
|
||||
return new DN(this.rdns);
|
||||
};
|
||||
|
||||
|
||||
DN.prototype.reverse = function() {
|
||||
DN.prototype.reverse = function () {
|
||||
this.rdns.reverse();
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
DN.prototype.pop = function() {
|
||||
DN.prototype.pop = function () {
|
||||
return this.rdns.pop();
|
||||
};
|
||||
|
||||
|
||||
DN.prototype.push = function(rdn) {
|
||||
if (typeof(rdn) !== 'object')
|
||||
DN.prototype.push = function (rdn) {
|
||||
if (typeof (rdn) !== 'object')
|
||||
throw new TypeError('rdn (RDN) required');
|
||||
|
||||
return this.rdns.push(rdn);
|
||||
};
|
||||
|
||||
|
||||
DN.prototype.shift = function() {
|
||||
DN.prototype.shift = function () {
|
||||
return this.rdns.shift();
|
||||
};
|
||||
|
||||
|
||||
DN.prototype.unshift = function(rdn) {
|
||||
if (typeof(rdn) !== 'object')
|
||||
DN.prototype.unshift = function (rdn) {
|
||||
if (typeof (rdn) !== 'object')
|
||||
throw new TypeError('rdn (RDN) required');
|
||||
|
||||
return this.rdns.unshift(rdn);
|
||||
|
|
|
@ -10,7 +10,8 @@ var SERVER_PROVIDER;
|
|||
var DTRACE_ID = 0;
|
||||
var MAX_INT = 4294967295;
|
||||
|
||||
/* Args:
|
||||
/*
|
||||
* Args:
|
||||
* server-*-start:
|
||||
* 0 -> id
|
||||
* 1 -> remoteIP
|
||||
|
@ -76,11 +77,11 @@ var SERVER_PROBES = {
|
|||
|
||||
///--- API
|
||||
|
||||
module.exports = function() {
|
||||
module.exports = function () {
|
||||
if (!SERVER_PROVIDER) {
|
||||
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);
|
||||
args.unshift(p);
|
||||
|
||||
|
@ -89,7 +90,7 @@ module.exports = function() {
|
|||
|
||||
SERVER_PROVIDER.enable();
|
||||
|
||||
SERVER_PROVIDER._nextId = function() {
|
||||
SERVER_PROVIDER._nextId = function () {
|
||||
if (DTRACE_ID === MAX_INT)
|
||||
DTRACE_ID = 0;
|
||||
|
||||
|
@ -99,4 +100,3 @@ module.exports = function() {
|
|||
|
||||
return SERVER_PROVIDER;
|
||||
}();
|
||||
|
||||
|
|
|
@ -59,16 +59,16 @@ function LDAPError(errorName, errorCode, msg, dn, caller) {
|
|||
if (Error.captureStackTrace)
|
||||
Error.captureStackTrace(this, caller || LDAPError);
|
||||
|
||||
this.__defineGetter__('dn', function() {
|
||||
this.__defineGetter__('dn', function () {
|
||||
return (dn ? (dn.toString() || '') : '');
|
||||
});
|
||||
this.__defineGetter__('code', function() {
|
||||
this.__defineGetter__('code', function () {
|
||||
return errorCode;
|
||||
});
|
||||
this.__defineGetter__('name', function() {
|
||||
this.__defineGetter__('name', function () {
|
||||
return errorName;
|
||||
});
|
||||
this.__defineGetter__('message', function() {
|
||||
this.__defineGetter__('message', function () {
|
||||
return msg || errorName;
|
||||
});
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ util.inherits(LDAPError, Error);
|
|||
module.exports = {};
|
||||
module.exports.LDAPError = LDAPError;
|
||||
|
||||
Object.keys(CODES).forEach(function(code) {
|
||||
Object.keys(CODES).forEach(function (code) {
|
||||
module.exports[code] = CODES[code];
|
||||
if (code === 'LDAP_SUCCESS')
|
||||
return;
|
||||
|
@ -102,14 +102,14 @@ Object.keys(CODES).forEach(function(code) {
|
|||
|
||||
// At this point LDAP_OPERATIONS_ERROR is now OperationsError in $err
|
||||
// and 'Operations Error' in $msg
|
||||
module.exports[err] = function(message, dn, caller) {
|
||||
module.exports[err] = function (message, dn, caller) {
|
||||
LDAPError.call(this,
|
||||
err,
|
||||
CODES[code],
|
||||
message || msg,
|
||||
dn || null,
|
||||
caller || module.exports[err]);
|
||||
}
|
||||
};
|
||||
module.exports[err].constructor = module.exports[err];
|
||||
util.inherits(module.exports[err], LDAPError);
|
||||
|
||||
|
@ -120,7 +120,7 @@ Object.keys(CODES).forEach(function(code) {
|
|||
});
|
||||
|
||||
|
||||
module.exports.getError = function(res) {
|
||||
module.exports.getError = function (res) {
|
||||
if (!(res instanceof LDAPResult))
|
||||
throw new TypeError('res (LDAPResult) required');
|
||||
|
||||
|
@ -132,10 +132,10 @@ module.exports.getError = function(res) {
|
|||
};
|
||||
|
||||
|
||||
module.exports.getMessage = function(code) {
|
||||
if (typeof(code) !== 'number')
|
||||
module.exports.getMessage = function (code) {
|
||||
if (typeof (code) !== 'number')
|
||||
throw new TypeError('code (number) required');
|
||||
|
||||
var errObj = ERRORS[res.status];
|
||||
var errObj = ERRORS[code];
|
||||
return (errObj && errObj.message ? errObj.message : '');
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function AndFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.filters || !Array.isArray(options.filters))
|
||||
throw new TypeError('options.filters ([Filter]) required');
|
||||
this.filters = options.filters.slice();
|
||||
|
@ -27,7 +27,7 @@ function AndFilter(options) {
|
|||
this.filters = [];
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'And',
|
||||
filters: self.filters || []
|
||||
|
@ -38,9 +38,9 @@ util.inherits(AndFilter, Filter);
|
|||
module.exports = AndFilter;
|
||||
|
||||
|
||||
AndFilter.prototype.toString = function() {
|
||||
AndFilter.prototype.toString = function () {
|
||||
var str = '(&';
|
||||
this.filters.forEach(function(f) {
|
||||
this.filters.forEach(function (f) {
|
||||
str += f.toString();
|
||||
});
|
||||
str += ')';
|
||||
|
@ -49,32 +49,33 @@ AndFilter.prototype.toString = function() {
|
|||
};
|
||||
|
||||
|
||||
AndFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
AndFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
var matches = this.filters.length ? true : false;
|
||||
|
||||
for (var i = 0; i < this.filters.length; i++)
|
||||
for (var i = 0; i < this.filters.length; i++) {
|
||||
if (!this.filters[i].matches(target))
|
||||
return false;
|
||||
}
|
||||
|
||||
return matches;
|
||||
};
|
||||
|
||||
|
||||
AndFilter.prototype.addFilter = function(filter) {
|
||||
if (!filter || typeof(filter) !== 'object')
|
||||
AndFilter.prototype.addFilter = function (filter) {
|
||||
if (!filter || typeof (filter) !== 'object')
|
||||
throw new TypeError('filter (object) required');
|
||||
|
||||
this.filters.push(filter);
|
||||
};
|
||||
|
||||
|
||||
AndFilter.prototype._toBer = function(ber) {
|
||||
AndFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.filters.forEach(function(f) {
|
||||
this.filters.forEach(function (f) {
|
||||
ber = f.toBer(ber);
|
||||
});
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function ApproximateFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (!options.attribute || typeof(options.attribute) !== 'string')
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.attribute || typeof (options.attribute) !== 'string')
|
||||
throw new TypeError('options.attribute (string) required');
|
||||
if (!options.value || typeof(options.value) !== 'string')
|
||||
if (!options.value || typeof (options.value) !== 'string')
|
||||
throw new TypeError('options.value (string) required');
|
||||
this.attribute = options.attribute;
|
||||
this.value = options.value;
|
||||
|
@ -26,7 +26,7 @@ function ApproximateFilter(options) {
|
|||
Filter.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'ApproximateMatch',
|
||||
attribute: self.attribute || undefined,
|
||||
|
@ -38,13 +38,13 @@ util.inherits(ApproximateFilter, Filter);
|
|||
module.exports = ApproximateFilter;
|
||||
|
||||
|
||||
ApproximateFilter.prototype.toString = function() {
|
||||
ApproximateFilter.prototype.toString = function () {
|
||||
return '(' + this.attribute + '~=' + this.value + ')';
|
||||
};
|
||||
|
||||
|
||||
ApproximateFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
ApproximateFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
var matches = false;
|
||||
|
@ -61,7 +61,7 @@ ApproximateFilter.prototype.matches = function(target) {
|
|||
};
|
||||
|
||||
|
||||
ApproximateFilter.prototype.parse = function(ber) {
|
||||
ApproximateFilter.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.attribute = ber.readString().toLowerCase();
|
||||
|
@ -71,7 +71,7 @@ ApproximateFilter.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ApproximateFilter.prototype._toBer = function(ber) {
|
||||
ApproximateFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.attribute);
|
||||
|
|
|
@ -12,10 +12,10 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function EqualityFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (!options.attribute || typeof(options.attribute) !== 'string')
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.attribute || typeof (options.attribute) !== 'string')
|
||||
throw new TypeError('options.attribute (string) required');
|
||||
if (!options.value || typeof(options.value) !== 'string')
|
||||
if (!options.value || typeof (options.value) !== 'string')
|
||||
throw new TypeError('options.value (string) required');
|
||||
this.attribute = options.attribute;
|
||||
this.value = options.value;
|
||||
|
@ -26,7 +26,7 @@ function EqualityFilter(options) {
|
|||
Filter.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'EqualityMatch',
|
||||
attribute: self.attribute || undefined,
|
||||
|
@ -38,19 +38,19 @@ util.inherits(EqualityFilter, Filter);
|
|||
module.exports = EqualityFilter;
|
||||
|
||||
|
||||
EqualityFilter.prototype.toString = function() {
|
||||
EqualityFilter.prototype.toString = function () {
|
||||
return '(' + this.attribute + '=' + this.value + ')';
|
||||
};
|
||||
|
||||
|
||||
EqualityFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
EqualityFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
if (target.hasOwnProperty(this.attribute)) {
|
||||
var value = this.value;
|
||||
return Filter.multi_test(
|
||||
function(v) { return value === v; },
|
||||
function (v) { return value === v; },
|
||||
target[this.attribute]);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ EqualityFilter.prototype.matches = function(target) {
|
|||
};
|
||||
|
||||
|
||||
EqualityFilter.prototype.parse = function(ber) {
|
||||
EqualityFilter.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.attribute = ber.readString().toLowerCase();
|
||||
|
@ -71,7 +71,7 @@ EqualityFilter.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
EqualityFilter.prototype._toBer = function(ber) {
|
||||
EqualityFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.attribute);
|
||||
|
|
|
@ -12,12 +12,12 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function ExtensibleFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (options.rule && typeof(options.rule) !== 'string')
|
||||
if (typeof (options) === 'object') {
|
||||
if (options.rule && typeof (options.rule) !== 'string')
|
||||
throw new TypeError('options.rule must be a string');
|
||||
if (options.matchType && typeof(options.matchType) !== 'string')
|
||||
if (options.matchType && typeof (options.matchType) !== 'string')
|
||||
throw new TypeError('options.type must be a string');
|
||||
if (options.value && typeof(options.value) !== 'string')
|
||||
if (options.value && typeof (options.value) !== 'string')
|
||||
throw new TypeError('options.value (string) required');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -31,7 +31,7 @@ function ExtensibleFilter(options) {
|
|||
Filter.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'ExtensibleMatch',
|
||||
matchRule: self.rule,
|
||||
|
@ -40,10 +40,10 @@ function ExtensibleFilter(options) {
|
|||
dnAttributes: self.dnAttributes
|
||||
};
|
||||
});
|
||||
this.__defineGetter__('matchingRule', function() {
|
||||
this.__defineGetter__('matchingRule', function () {
|
||||
return self.rule;
|
||||
});
|
||||
this.__defineGetter__('matchValue', function() {
|
||||
this.__defineGetter__('matchValue', function () {
|
||||
return self.value;
|
||||
});
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ util.inherits(ExtensibleFilter, Filter);
|
|||
module.exports = ExtensibleFilter;
|
||||
|
||||
|
||||
ExtensibleFilter.prototype.toString = function() {
|
||||
ExtensibleFilter.prototype.toString = function () {
|
||||
var str = '(';
|
||||
|
||||
if (this.matchType)
|
||||
|
@ -78,8 +78,8 @@ ExtensibleFilter.prototype.toString = function() {
|
|||
* @param {Object} target the target object.
|
||||
* @return {Boolean} false always.
|
||||
*/
|
||||
ExtensibleFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
ExtensibleFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
if (this.dnAttribute)
|
||||
|
@ -90,7 +90,7 @@ ExtensibleFilter.prototype.matches = function(target) {
|
|||
|
||||
var self = this;
|
||||
if (this.matchType && target.hasOwnProperty(this.matchType)) {
|
||||
return Filter.multi_test(function(v) {
|
||||
return Filter.multi_test(function (v) {
|
||||
if (self.rule === '2.5.13.2')
|
||||
return self.value.toLowerCase() === v.toLowerCase();
|
||||
|
||||
|
@ -102,7 +102,7 @@ ExtensibleFilter.prototype.matches = function(target) {
|
|||
};
|
||||
|
||||
|
||||
ExtensibleFilter.prototype.parse = function(ber) {
|
||||
ExtensibleFilter.prototype.parse = function (ber) {
|
||||
var end = ber.offset + ber.length;
|
||||
while (ber.offset < end) {
|
||||
var tag = ber.peek();
|
||||
|
@ -128,7 +128,7 @@ ExtensibleFilter.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ExtensibleFilter.prototype._toBer = function(ber) {
|
||||
ExtensibleFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
if (this.rule)
|
||||
|
|
|
@ -18,15 +18,15 @@ var BerWriter = asn1.BerWriter;
|
|||
///--- API
|
||||
|
||||
function Filter(options) {
|
||||
if (!options || typeof(options) !== 'object')
|
||||
if (!options || typeof (options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
if (typeof(options.type) !== 'number')
|
||||
if (typeof (options.type) !== 'number')
|
||||
throw new TypeError('options.type (number) required');
|
||||
|
||||
this._type = options.type;
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() {
|
||||
this.__defineGetter__('type', function () {
|
||||
switch (self._type) {
|
||||
case Protocol.FILTER_AND: return 'and';
|
||||
case Protocol.FILTER_OR: return 'or';
|
||||
|
@ -47,7 +47,7 @@ function Filter(options) {
|
|||
module.exports = Filter;
|
||||
|
||||
|
||||
Filter.prototype.toBer = function(ber) {
|
||||
Filter.prototype.toBer = function (ber) {
|
||||
if (!ber || !(ber instanceof BerWriter))
|
||||
throw new TypeError('ber (BerWriter) required');
|
||||
|
||||
|
@ -61,7 +61,7 @@ Filter.prototype.toBer = function(ber) {
|
|||
/*
|
||||
* Test a rule against one or more values.
|
||||
*/
|
||||
Filter.multi_test = function(rule, value) {
|
||||
Filter.multi_test = function (rule, value) {
|
||||
if (Array.isArray(value)) {
|
||||
var response = false;
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
|
|
|
@ -12,10 +12,10 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function GreaterThanEqualsFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (!options.attribute || typeof(options.attribute) !== 'string')
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.attribute || typeof (options.attribute) !== 'string')
|
||||
throw new TypeError('options.attribute (string) required');
|
||||
if (!options.value || typeof(options.value) !== 'string')
|
||||
if (!options.value || typeof (options.value) !== 'string')
|
||||
throw new TypeError('options.value (string) required');
|
||||
this.attribute = options.attribute;
|
||||
this.value = options.value;
|
||||
|
@ -27,7 +27,7 @@ function GreaterThanEqualsFilter(options) {
|
|||
Filter.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'GreaterThanEqualsMatch',
|
||||
attribute: self.attribute || undefined,
|
||||
|
@ -39,19 +39,19 @@ util.inherits(GreaterThanEqualsFilter, Filter);
|
|||
module.exports = GreaterThanEqualsFilter;
|
||||
|
||||
|
||||
GreaterThanEqualsFilter.prototype.toString = function() {
|
||||
GreaterThanEqualsFilter.prototype.toString = function () {
|
||||
return '(' + this.attribute + '>=' + this.value + ')';
|
||||
};
|
||||
|
||||
|
||||
GreaterThanEqualsFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
GreaterThanEqualsFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
if (target.hasOwnProperty(this.attribute)) {
|
||||
var value = this.value;
|
||||
return Filter.multi_test(
|
||||
function(v) { return value <= v; },
|
||||
function (v) { return value <= v; },
|
||||
target[this.attribute]);
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ GreaterThanEqualsFilter.prototype.matches = function(target) {
|
|||
};
|
||||
|
||||
|
||||
GreaterThanEqualsFilter.prototype.parse = function(ber) {
|
||||
GreaterThanEqualsFilter.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.attribute = ber.readString().toLowerCase();
|
||||
|
@ -69,7 +69,7 @@ GreaterThanEqualsFilter.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
GreaterThanEqualsFilter.prototype._toBer = function(ber) {
|
||||
GreaterThanEqualsFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.attribute);
|
||||
|
|
|
@ -28,184 +28,317 @@ var BerReader = asn1.BerReader;
|
|||
|
||||
///--- Internal Parsers
|
||||
|
||||
|
||||
/*
|
||||
* This is a pretty naive approach to parsing, but it's relatively short amount
|
||||
* of code. Basically, we just build a stack as we go.
|
||||
*/
|
||||
function _filterStringToStack(str) {
|
||||
assert.ok(str);
|
||||
|
||||
var tmp = '';
|
||||
var esc = false;
|
||||
// expression parsing
|
||||
// returns the index of the closing parenthesis matching the open paren
|
||||
// specified by openParenIndex
|
||||
function matchParens(str, openParenIndex) {
|
||||
var stack = [];
|
||||
var depth = -1;
|
||||
var open = false;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var esc = false;
|
||||
for (var i = openParenIndex || 0; i < str.length; i++) {
|
||||
var c = str[i];
|
||||
|
||||
if (esc) {
|
||||
esc = false;
|
||||
tmp += c;
|
||||
if (c === '\\') {
|
||||
if (!esc)
|
||||
esc = true;
|
||||
continue;
|
||||
} else if (c === '(' && !esc) {
|
||||
stack.push(1);
|
||||
} else if (c === ')' && !esc) {
|
||||
stack.pop();
|
||||
if (stack.length === 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '(':
|
||||
open = true;
|
||||
tmp = '';
|
||||
stack[++depth] = '';
|
||||
break;
|
||||
case ')':
|
||||
if (open) {
|
||||
stack[depth].value = tmp;
|
||||
tmp = '';
|
||||
}
|
||||
open = false;
|
||||
break;
|
||||
case '&':
|
||||
case '|':
|
||||
case '!':
|
||||
stack[depth] = c;
|
||||
break;
|
||||
case '=':
|
||||
stack[depth] = { attribute: tmp, op: c };
|
||||
tmp = '';
|
||||
break;
|
||||
case '>':
|
||||
case '<':
|
||||
case '~':
|
||||
if (!(str[++i] === '='))
|
||||
throw new Error('Invalid filter: ' + tmp + c + str[i]);
|
||||
esc = false;
|
||||
}
|
||||
|
||||
stack[depth] = {attribute: tmp, op: c};
|
||||
tmp = '';
|
||||
break;
|
||||
case '\\':
|
||||
esc = true;
|
||||
default:
|
||||
tmp += c;
|
||||
break;
|
||||
return str.length - 1;
|
||||
}
|
||||
|
||||
|
||||
// recursive function that builds a filter tree from a string expression
|
||||
// the filter tree is an intermediary step between the incoming expression and
|
||||
// the outgoing Filter Class structure.
|
||||
function _buildFilterTree(expr) {
|
||||
var c;
|
||||
var child;
|
||||
var clean = false;
|
||||
var endParen;
|
||||
var esc = false;
|
||||
var i = 0;
|
||||
var tree = {};
|
||||
var split;
|
||||
var substrNdx = 0;
|
||||
var val = '';
|
||||
|
||||
if (expr.length === 0)
|
||||
return tree;
|
||||
|
||||
// Chop the parens (the call to matchParens below gets rid of the trailer)
|
||||
if (expr.charAt(0) == '(')
|
||||
expr = expr.substring(1, expr.length - 1);
|
||||
|
||||
//store prefix operator
|
||||
if (expr.charAt(0) === '&') {
|
||||
tree.op = 'and';
|
||||
expr = expr.substring(1);
|
||||
} else if (expr.charAt(0) === '|') {
|
||||
tree.op = 'or';
|
||||
expr = expr.substring(1);
|
||||
} else if (expr.charAt(0) === '!') {
|
||||
tree.op = 'not';
|
||||
expr = expr.substring(1);
|
||||
} else {
|
||||
tree.op = 'expr';
|
||||
}
|
||||
|
||||
if (tree.op != 'expr') {
|
||||
tree.children = [];
|
||||
|
||||
// logical operators are k-ary, so we go until our expression string runs
|
||||
// out (at least for this recursion level)
|
||||
while (expr.length !== 0) {
|
||||
endParen = matchParens(expr);
|
||||
if (endParen == expr.length - 1) {
|
||||
tree.children[i] = _buildFilterTree(expr);
|
||||
expr = '';
|
||||
} else {
|
||||
child = expr.slice(0, endParen + 1);
|
||||
expr = expr.substring(endParen + 1);
|
||||
tree.children[i] = _buildFilterTree(child);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
//else its some sort of non-logical expression, parse and return as such
|
||||
var operatorStr = '';
|
||||
tree.name = '';
|
||||
tree.value = '';
|
||||
if (expr.indexOf('~=') !== -1) {
|
||||
operatorStr = '~=';
|
||||
tree.tag = 'approxMatch';
|
||||
} else if (expr.indexOf('>=') !== -1) {
|
||||
operatorStr = '>=';
|
||||
tree.tag = 'greaterOrEqual';
|
||||
} else if (expr.indexOf('<=') !== -1) {
|
||||
operatorStr = '<=';
|
||||
tree.tag = 'lessOrEqual';
|
||||
} else if (expr.indexOf(':=') !== -1) {
|
||||
operatorStr = ':=';
|
||||
tree.tag = 'extensibleMatch';
|
||||
} else if (expr.indexOf('=') !== -1) {
|
||||
operatorStr = '=';
|
||||
tree.tag = 'equalityMatch';
|
||||
} else {
|
||||
tree.tag = 'present';
|
||||
}
|
||||
|
||||
if (operatorStr === '') {
|
||||
tree.name = expr;
|
||||
} else {
|
||||
// pull out lhs and rhs of equality operator
|
||||
var splitAry = expr.split(operatorStr);
|
||||
tree.name = splitAry.shift();
|
||||
tree.value = splitAry.join(operatorStr);
|
||||
|
||||
// substrings fall into the equality bin in the
|
||||
// switch above so we need more processing here
|
||||
if (tree.tag === 'equalityMatch') {
|
||||
if (tree.value.length === 0) {
|
||||
tree.tag = 'present';
|
||||
} else {
|
||||
|
||||
// Effectively a hand-rolled .shift() to support \* sequences
|
||||
clean = true;
|
||||
split = [];
|
||||
substrNdx = 0;
|
||||
split[substrNdx] = '';
|
||||
for (i = 0; i < tree.value.length; i++) {
|
||||
c = tree.value[i];
|
||||
if (esc) {
|
||||
split[substrNdx] += c;
|
||||
esc = false;
|
||||
} else if (c === '*') {
|
||||
split[++substrNdx] = '';
|
||||
} else if (c === '\\') {
|
||||
esc = true;
|
||||
} else {
|
||||
split[substrNdx] += c;
|
||||
}
|
||||
}
|
||||
|
||||
if (split.length > 1) {
|
||||
tree.tag = 'substrings';
|
||||
clean = true;
|
||||
|
||||
// if the value string doesn't start with a * then theres no initial
|
||||
// value else split will have an empty string in its first array
|
||||
// index...
|
||||
// we need to remove that empty string
|
||||
if (tree.value.indexOf('*') !== 0) {
|
||||
tree.initial = split.shift();
|
||||
} else {
|
||||
split.shift();
|
||||
}
|
||||
|
||||
// if the value string doesn't end with a * then theres no final
|
||||
// value also same split stuff as the initial stuff above
|
||||
if (tree.value.lastIndexOf('*') !== tree.value.length - 1) {
|
||||
tree['final'] = split.pop();
|
||||
} else {
|
||||
split.pop();
|
||||
}
|
||||
tree.any = split;
|
||||
} else {
|
||||
tree.value = split[0]; // pick up the cleaned version
|
||||
}
|
||||
}
|
||||
|
||||
} else if (tree.tag == 'extensibleMatch') {
|
||||
split = tree.name.split(':');
|
||||
tree.extensible = {
|
||||
matchType: split[0],
|
||||
value: tree.value
|
||||
};
|
||||
switch (split.length) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
if (split[1].toLowerCase() === 'dn') {
|
||||
tree.extensible.dnAttributes = true;
|
||||
} else {
|
||||
tree.extensible.rule = split[1];
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
tree.extensible.dnAttributes = true;
|
||||
tree.extensible.rule = split[2];
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid extensible filter');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup any escape sequences
|
||||
if (!clean) {
|
||||
|
||||
for (i = 0; i < tree.value.length; i++) {
|
||||
c = tree.value[i];
|
||||
if (esc) {
|
||||
val += c;
|
||||
esc = false;
|
||||
} else if (c === '\\') {
|
||||
esc = true;
|
||||
} else {
|
||||
val += c;
|
||||
}
|
||||
}
|
||||
tree.value = val;
|
||||
}
|
||||
}
|
||||
|
||||
if (open)
|
||||
throw new Error('Invalid filter: ' + str);
|
||||
return tree;
|
||||
}
|
||||
|
||||
return stack;
|
||||
|
||||
function serializeTree(tree, filter) {
|
||||
if (tree === undefined || tree.length === 0)
|
||||
return;
|
||||
|
||||
// if the current tree object is not an expression then its a logical
|
||||
// operator (ie an internal node in the tree)
|
||||
var current = null;
|
||||
if (tree.op !== 'expr') {
|
||||
switch (tree.op) {
|
||||
case 'and':
|
||||
current = new AndFilter();
|
||||
break;
|
||||
case 'or':
|
||||
current = new OrFilter();
|
||||
break;
|
||||
case 'not':
|
||||
current = new NotFilter();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
filter.addFilter(current || filter);
|
||||
if (current || tree.children.length) {
|
||||
tree.children.forEach(function (child) {
|
||||
serializeTree(child, current);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// else its a leaf node in the tree, and represents some type of
|
||||
// non-logical expression
|
||||
var tmp;
|
||||
|
||||
// convert the tag name to a filter class type
|
||||
switch (tree.tag) {
|
||||
case 'approxMatch':
|
||||
tmp = new ApproximateFilter({
|
||||
attribute: tree.name,
|
||||
value: tree.value
|
||||
});
|
||||
break;
|
||||
case 'extensibleMatch':
|
||||
tmp = new ExtensibleFilter(tree.extensible);
|
||||
break;
|
||||
case 'greaterOrEqual':
|
||||
tmp = new GreaterThanEqualsFilter({
|
||||
attribute: tree.name,
|
||||
value: tree.value
|
||||
});
|
||||
break;
|
||||
case 'lessOrEqual':
|
||||
tmp = new LessThanEqualsFilter({
|
||||
attribute: tree.name,
|
||||
value: tree.value
|
||||
});
|
||||
break;
|
||||
case 'equalityMatch':
|
||||
tmp = new EqualityFilter({
|
||||
attribute: tree.name,
|
||||
value: tree.value
|
||||
});
|
||||
break;
|
||||
case 'substrings':
|
||||
tmp = new SubstringFilter({
|
||||
attribute: tree.name,
|
||||
initial: tree.initial,
|
||||
any: tree.any,
|
||||
'final': tree['final']
|
||||
});
|
||||
break;
|
||||
case 'present':
|
||||
tmp = new PresenceFilter({
|
||||
attribute: tree.name
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (tmp)
|
||||
filter.addFilter(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _parseString(str) {
|
||||
assert.ok(str);
|
||||
|
||||
var stack = _filterStringToStack(str);
|
||||
// create a blank object to pass into treeToObjs
|
||||
// since its recursive we have to prime it ourselves.
|
||||
// this gets stripped off before the filter structure is returned
|
||||
// at the bottom of this function.
|
||||
var filterObj = new AndFilter({
|
||||
filters: []
|
||||
});
|
||||
|
||||
if (!stack || !stack.length)
|
||||
throw new Error('Invalid filter: ' + str);
|
||||
|
||||
debugger;
|
||||
var f;
|
||||
var filters = [];
|
||||
for (var i = stack.length - 1; i >= 0; i--) {
|
||||
if (stack[i] === '&') {
|
||||
filters.unshift(new AndFilter({
|
||||
filters: filters
|
||||
}));
|
||||
filters.length = 1;
|
||||
} else if (stack[i] === '|') {
|
||||
filters.unshift(new OrFilter({
|
||||
filters: filters
|
||||
}));
|
||||
filters.length = 1;
|
||||
} else if (stack[i] === '!') {
|
||||
filters.push(new NotFilter({
|
||||
filter: filters.pop()
|
||||
}));
|
||||
} else {
|
||||
switch (stack[i].op) {
|
||||
case '=': // could be presence, equality, substr or ext
|
||||
if (stack[i].value === '*') {
|
||||
filters.push(new PresenceFilter(stack[i]));
|
||||
} else {
|
||||
var vals = [''];
|
||||
var ndx = 0;
|
||||
var esc = false;
|
||||
for (var j = 0; j < stack[i].value.length; j++) {
|
||||
var c = stack[i].value[j];
|
||||
if (c === '\\') {
|
||||
if (esc) {
|
||||
esc = true;
|
||||
} else {
|
||||
vals[ndx] += c;
|
||||
esc = false;
|
||||
}
|
||||
} else if (c === '*') {
|
||||
if (esc) {
|
||||
vals[ndx] = c;
|
||||
} else {
|
||||
vals[++ndx] = '';
|
||||
}
|
||||
} else {
|
||||
vals[ndx] += c;
|
||||
}
|
||||
}
|
||||
if (vals.length === 1) {
|
||||
if (stack[i].attribute.indexOf(':') !== -1) {
|
||||
var extTmp = stack[i].attribute.split(':');
|
||||
var extOpts = {};
|
||||
extOpts.matchType = extTmp[0];
|
||||
switch (extTmp.length) {
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
if (extTmp[1].toLowerCase() === 'dn') {
|
||||
extOpts.dnAttributes = true;
|
||||
} else {
|
||||
extOpts.rule = extTmp[1];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
extOpts.dnAttributes = true;
|
||||
extOpts.rule = extTmp[2];
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid extensible filter');
|
||||
}
|
||||
extOpts.value = vals[0];
|
||||
filters.push(new ExtensibleFilter(extOpts));
|
||||
} else {
|
||||
filters.push(new EqualityFilter(stack[i]));
|
||||
}
|
||||
} else {
|
||||
filters.push(new SubstringFilter({
|
||||
attribute: stack[i].attribute,
|
||||
initial: vals.shift() || null,
|
||||
'final': vals.pop() || null,
|
||||
any: vals || null
|
||||
}));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '~':
|
||||
filters.push(new ApproximateFilter(stack[i]));
|
||||
break;
|
||||
case '>':
|
||||
filters.push(new GreaterThanEqualsFilter(stack[i]));
|
||||
break;
|
||||
case '<':
|
||||
filters.push(new LessThanEqualsFilter(stack[i]));
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid filter (op=' + stack[i].op + '): ' + str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filters.length !== 1)
|
||||
throw new Error('Invalid filter: ' + str);
|
||||
|
||||
return filters.pop();
|
||||
serializeTree(_buildFilterTree(str), filterObj);
|
||||
return filterObj.filters[0];
|
||||
}
|
||||
|
||||
|
||||
|
@ -323,15 +456,15 @@ function _parse(ber) {
|
|||
|
||||
module.exports = {
|
||||
|
||||
parse: function(ber) {
|
||||
parse: function (ber) {
|
||||
if (!ber || !(ber instanceof BerReader))
|
||||
throw new TypeError('ber (BerReader) required');
|
||||
|
||||
return _parse(ber);
|
||||
},
|
||||
|
||||
parseString: function(filter) {
|
||||
if (!filter || typeof(filter) !== 'string')
|
||||
parseString: function (filter) {
|
||||
if (!filter || typeof (filter) !== 'string')
|
||||
throw new TypeError('filter (string) required');
|
||||
|
||||
return _parseString(filter);
|
||||
|
@ -349,4 +482,3 @@ module.exports = {
|
|||
SubstringFilter: SubstringFilter,
|
||||
Filter: Filter
|
||||
};
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function LessThanEqualsFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (!options.attribute || typeof(options.attribute) !== 'string')
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.attribute || typeof (options.attribute) !== 'string')
|
||||
throw new TypeError('options.attribute (string) required');
|
||||
if (!options.value || typeof(options.value) !== 'string')
|
||||
if (!options.value || typeof (options.value) !== 'string')
|
||||
throw new TypeError('options.value (string) required');
|
||||
this.attribute = options.attribute;
|
||||
this.value = options.value;
|
||||
|
@ -27,7 +27,7 @@ function LessThanEqualsFilter(options) {
|
|||
Filter.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'LessThanEqualsMatch',
|
||||
attribute: self.attribute || undefined,
|
||||
|
@ -39,19 +39,19 @@ util.inherits(LessThanEqualsFilter, Filter);
|
|||
module.exports = LessThanEqualsFilter;
|
||||
|
||||
|
||||
LessThanEqualsFilter.prototype.toString = function() {
|
||||
LessThanEqualsFilter.prototype.toString = function () {
|
||||
return '(' + this.attribute + '<=' + this.value + ')';
|
||||
};
|
||||
|
||||
|
||||
LessThanEqualsFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
LessThanEqualsFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
if (target.hasOwnProperty(this.attribute)) {
|
||||
var value = this.value;
|
||||
return Filter.multi_test(
|
||||
function(v) { return value >= v; },
|
||||
function (v) { return value >= v; },
|
||||
target[this.attribute]);
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ LessThanEqualsFilter.prototype.matches = function(target) {
|
|||
};
|
||||
|
||||
|
||||
LessThanEqualsFilter.prototype.parse = function(ber) {
|
||||
LessThanEqualsFilter.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.attribute = ber.readString().toLowerCase();
|
||||
|
@ -69,7 +69,7 @@ LessThanEqualsFilter.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
LessThanEqualsFilter.prototype._toBer = function(ber) {
|
||||
LessThanEqualsFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.attribute);
|
||||
|
|
|
@ -12,18 +12,20 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function NotFilter(options) {
|
||||
if (typeof(options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
if (!options.filter || !(options.filter instanceof Filter))
|
||||
throw new TypeError('options.filter (Filter) required');
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.filter || !(options.filter instanceof Filter))
|
||||
throw new TypeError('options.filter (Filter) required');
|
||||
|
||||
} else {
|
||||
options = {};
|
||||
}
|
||||
|
||||
this.filter = options.filter || {};
|
||||
options.type = Protocol.FILTER_NOT;
|
||||
Filter.call(this, options);
|
||||
|
||||
this.filter = options.filter;
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'Not',
|
||||
filter: self.filter
|
||||
|
@ -34,17 +36,23 @@ util.inherits(NotFilter, Filter);
|
|||
module.exports = NotFilter;
|
||||
|
||||
|
||||
NotFilter.prototype.toString = function() {
|
||||
NotFilter.prototype.addFilter = function (f) {
|
||||
if (!(f instanceof Filter))
|
||||
throw new TypeError('filter (Filter) required');
|
||||
this.filter = f;
|
||||
};
|
||||
|
||||
NotFilter.prototype.toString = function () {
|
||||
return '(!' + this.filter.toString() + ')';
|
||||
};
|
||||
|
||||
|
||||
NotFilter.prototype.matches = function(target) {
|
||||
NotFilter.prototype.matches = function (target) {
|
||||
return !this.filter.matches(target);
|
||||
};
|
||||
|
||||
|
||||
NotFilter.prototype._toBer = function(ber) {
|
||||
NotFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
return this.filter.toBer(ber);
|
||||
|
|
|
@ -12,7 +12,7 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function OrFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.filters || !Array.isArray(options.filters))
|
||||
throw new TypeError('options.filters ([Filter]) required');
|
||||
this.filters = options.filters.slice();
|
||||
|
@ -27,7 +27,7 @@ function OrFilter(options) {
|
|||
this.filters = [];
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'Or',
|
||||
filters: self.filters || []
|
||||
|
@ -38,9 +38,9 @@ util.inherits(OrFilter, Filter);
|
|||
module.exports = OrFilter;
|
||||
|
||||
|
||||
OrFilter.prototype.toString = function() {
|
||||
OrFilter.prototype.toString = function () {
|
||||
var str = '(|';
|
||||
this.filters.forEach(function(f) {
|
||||
this.filters.forEach(function (f) {
|
||||
str += f.toString();
|
||||
});
|
||||
str += ')';
|
||||
|
@ -49,30 +49,31 @@ OrFilter.prototype.toString = function() {
|
|||
};
|
||||
|
||||
|
||||
OrFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
OrFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
for (var i = 0; i < this.filters.length; i++)
|
||||
for (var i = 0; i < this.filters.length; i++) {
|
||||
if (this.filters[i].matches(target))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
OrFilter.prototype.addFilter = function(filter) {
|
||||
if (!filter || typeof(filter) !== 'object')
|
||||
OrFilter.prototype.addFilter = function (filter) {
|
||||
if (!filter || typeof (filter) !== 'object')
|
||||
throw new TypeError('filter (object) required');
|
||||
|
||||
this.filters.push(filter);
|
||||
};
|
||||
|
||||
|
||||
OrFilter.prototype._toBer = function(ber) {
|
||||
OrFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.filters.forEach(function(f) {
|
||||
this.filters.forEach(function (f) {
|
||||
ber = f.toBer(ber);
|
||||
});
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function PresenceFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (!options.attribute || typeof(options.attribute) !== 'string')
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.attribute || typeof (options.attribute) !== 'string')
|
||||
throw new TypeError('options.attribute (string) required');
|
||||
this.attribute = options.attribute;
|
||||
} else {
|
||||
|
@ -22,7 +22,7 @@ function PresenceFilter(options) {
|
|||
Filter.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'PresenceMatch',
|
||||
attribute: self.attribute || undefined
|
||||
|
@ -33,20 +33,20 @@ util.inherits(PresenceFilter, Filter);
|
|||
module.exports = PresenceFilter;
|
||||
|
||||
|
||||
PresenceFilter.prototype.toString = function() {
|
||||
PresenceFilter.prototype.toString = function () {
|
||||
return '(' + this.attribute + '=*)';
|
||||
};
|
||||
|
||||
|
||||
PresenceFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
PresenceFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
return target.hasOwnProperty(this.attribute);
|
||||
};
|
||||
|
||||
|
||||
PresenceFilter.prototype.parse = function(ber) {
|
||||
PresenceFilter.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.attribute =
|
||||
|
@ -58,7 +58,7 @@ PresenceFilter.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
PresenceFilter.prototype._toBer = function(ber) {
|
||||
PresenceFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
for (var i = 0; i < this.attribute.length; i++)
|
||||
|
|
|
@ -12,8 +12,8 @@ var Protocol = require('../protocol');
|
|||
///--- API
|
||||
|
||||
function SubstringFilter(options) {
|
||||
if (typeof(options) === 'object') {
|
||||
if (!options.attribute || typeof(options.attribute) !== 'string')
|
||||
if (typeof (options) === 'object') {
|
||||
if (!options.attribute || typeof (options.attribute) !== 'string')
|
||||
throw new TypeError('options.attribute (string) required');
|
||||
this.attribute = options.attribute;
|
||||
this.initial = options.initial || null;
|
||||
|
@ -30,7 +30,7 @@ function SubstringFilter(options) {
|
|||
Filter.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('json', function () {
|
||||
return {
|
||||
type: 'SubstringMatch',
|
||||
initial: self.initial || undefined,
|
||||
|
@ -43,7 +43,7 @@ util.inherits(SubstringFilter, Filter);
|
|||
module.exports = SubstringFilter;
|
||||
|
||||
|
||||
SubstringFilter.prototype.toString = function() {
|
||||
SubstringFilter.prototype.toString = function () {
|
||||
var str = '(' + this.attribute + '=';
|
||||
|
||||
if (this.initial)
|
||||
|
@ -51,7 +51,7 @@ SubstringFilter.prototype.toString = function() {
|
|||
|
||||
str += '*';
|
||||
|
||||
this.any.forEach(function(s) {
|
||||
this.any.forEach(function (s) {
|
||||
str += s + '*';
|
||||
});
|
||||
|
||||
|
@ -64,8 +64,8 @@ SubstringFilter.prototype.toString = function() {
|
|||
};
|
||||
|
||||
|
||||
SubstringFilter.prototype.matches = function(target) {
|
||||
if (typeof(target) !== 'object')
|
||||
SubstringFilter.prototype.matches = function (target) {
|
||||
if (typeof (target) !== 'object')
|
||||
throw new TypeError('target (object) required');
|
||||
|
||||
if (target.hasOwnProperty(this.attribute)) {
|
||||
|
@ -73,7 +73,7 @@ SubstringFilter.prototype.matches = function(target) {
|
|||
if (this.initial)
|
||||
re += '^' + this.initial + '.*';
|
||||
|
||||
this.any.forEach(function(s) {
|
||||
this.any.forEach(function (s) {
|
||||
re += s + '.*';
|
||||
});
|
||||
|
||||
|
@ -82,7 +82,7 @@ SubstringFilter.prototype.matches = function(target) {
|
|||
|
||||
var matcher = new RegExp(re);
|
||||
return Filter.multi_test(
|
||||
function(v) { return matcher.test(v); },
|
||||
function (v) { return matcher.test(v); },
|
||||
target[this.attribute]);
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ SubstringFilter.prototype.matches = function(target) {
|
|||
};
|
||||
|
||||
|
||||
SubstringFilter.prototype.parse = function(ber) {
|
||||
SubstringFilter.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.attribute = ber.readString().toLowerCase();
|
||||
|
@ -125,7 +125,7 @@ SubstringFilter.prototype.parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
SubstringFilter.prototype._toBer = function(ber) {
|
||||
SubstringFilter.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.attribute);
|
||||
|
@ -135,7 +135,7 @@ SubstringFilter.prototype._toBer = function(ber) {
|
|||
ber.writeString(this.initial, 0x80);
|
||||
|
||||
if (this.any && this.any.length)
|
||||
this.any.forEach(function(s) {
|
||||
this.any.forEach(function (s) {
|
||||
ber.writeString(s, 0x81);
|
||||
});
|
||||
|
||||
|
|
45
lib/index.js
45
lib/index.js
|
@ -1,5 +1,7 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var Logger = require('bunyan');
|
||||
|
||||
var Client = require('./client');
|
||||
var Attribute = require('./attribute');
|
||||
var Change = require('./change');
|
||||
|
@ -12,9 +14,7 @@ var controls = require('./controls');
|
|||
var dn = require('./dn');
|
||||
var errors = require('./errors');
|
||||
var filters = require('./filters');
|
||||
var logStub = require('./log_stub');
|
||||
var messages = require('./messages');
|
||||
var schema = require('./schema');
|
||||
var url = require('./url');
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@ var url = require('./url');
|
|||
/// Hack a few things we need (i.e., "monkey patch" the prototype)
|
||||
|
||||
if (!String.prototype.startsWith) {
|
||||
String.prototype.startsWith = function(str) {
|
||||
String.prototype.startsWith = function (str) {
|
||||
var re = new RegExp('^' + str);
|
||||
return re.test(this);
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ if (!String.prototype.startsWith) {
|
|||
|
||||
|
||||
if (!String.prototype.endsWith) {
|
||||
String.prototype.endsWith = function(str) {
|
||||
String.prototype.endsWith = function (str) {
|
||||
var re = new RegExp(str + '$');
|
||||
return re.test(this);
|
||||
};
|
||||
|
@ -43,15 +43,36 @@ if (!String.prototype.endsWith) {
|
|||
module.exports = {
|
||||
|
||||
Client: Client,
|
||||
createClient: function(options) {
|
||||
if (typeof(options) !== 'object')
|
||||
createClient: function (options) {
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
|
||||
if (!options.log) {
|
||||
options.log = new Logger({
|
||||
name: 'ldapjs',
|
||||
component: 'client',
|
||||
stream: process.stderr
|
||||
});
|
||||
}
|
||||
return new Client(options);
|
||||
},
|
||||
|
||||
Server: Server,
|
||||
createServer: function(options) {
|
||||
createServer: function (options) {
|
||||
if (options === undefined)
|
||||
options = {};
|
||||
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
|
||||
if (!options.log) {
|
||||
options.log = new Logger({
|
||||
name: 'ldapjs',
|
||||
component: 'client',
|
||||
stream: process.stderr
|
||||
});
|
||||
}
|
||||
|
||||
return new Server(options);
|
||||
},
|
||||
|
||||
|
@ -66,16 +87,10 @@ module.exports = {
|
|||
filters: filters,
|
||||
parseFilter: filters.parseString,
|
||||
|
||||
log4js: logStub,
|
||||
parseURL: url.parse,
|
||||
url: url,
|
||||
|
||||
loadSchema: schema.load,
|
||||
createSchemaAddHandler: schema.createAddHandler,
|
||||
createSchemaModifyHandler: schema.createModifyHandler,
|
||||
createSchemaSearchHandler: schema.createSearchHandler,
|
||||
|
||||
PersistentSearch: PersistentSearch
|
||||
PersistentSearch: PersistentSearch,
|
||||
url: url
|
||||
};
|
||||
|
||||
|
||||
|
|
155
lib/log_stub.js
155
lib/log_stub.js
|
@ -1,155 +0,0 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
|
||||
|
||||
///--- Globals
|
||||
|
||||
var FMT_STR = '%d-%s-%s %s:%s:%sZ %s - %s: ';
|
||||
|
||||
var _i = 0;
|
||||
var LEVELS = {
|
||||
Trace: _i++,
|
||||
Debug: _i++,
|
||||
Info: _i++,
|
||||
Warn: _i++,
|
||||
Error: _i++,
|
||||
Fatal: _i++
|
||||
};
|
||||
|
||||
var level = 'Info';
|
||||
|
||||
|
||||
|
||||
// --- Helpers
|
||||
|
||||
function pad(val) {
|
||||
if (parseInt(val, 10) < 10) {
|
||||
val = '0' + val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
function format(level, name, args) {
|
||||
var d = new Date();
|
||||
var fmtStr = args.shift();
|
||||
var fmtArgs = [
|
||||
d.getUTCFullYear(),
|
||||
pad(d.getUTCMonth() + 1),
|
||||
pad(d.getUTCDate()),
|
||||
pad(d.getUTCHours()),
|
||||
pad(d.getUTCMinutes()),
|
||||
pad(d.getUTCSeconds()),
|
||||
level,
|
||||
name
|
||||
];
|
||||
|
||||
args = fmtArgs.concat(args);
|
||||
|
||||
var output = (FMT_STR + fmtStr).replace(/%[sdj]/g, function(match) {
|
||||
switch (match) {
|
||||
case '%s': return new String(args.shift());
|
||||
case '%d': return new Number(args.shift());
|
||||
case '%j': return JSON.stringify(args.shift());
|
||||
default:
|
||||
return match;
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///--- API
|
||||
|
||||
function Log(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Log.prototype._write = function(level, args) {
|
||||
var data = format(level, this.name, args);
|
||||
console.error(data);
|
||||
};
|
||||
|
||||
Log.prototype.isTraceEnabled = function() {
|
||||
return (LEVELS.Trace >= LEVELS[level]);
|
||||
};
|
||||
|
||||
Log.prototype.trace = function() {
|
||||
if (this.isTraceEnabled())
|
||||
this._write('TRACE', Array.prototype.slice.call(arguments));
|
||||
};
|
||||
|
||||
Log.prototype.isDebugEnabled = function() {
|
||||
return (LEVELS.Debug >= LEVELS[level]);
|
||||
};
|
||||
|
||||
Log.prototype.debug = function() {
|
||||
if (this.isDebugEnabled())
|
||||
this._write('DEBUG', Array.prototype.slice.call(arguments));
|
||||
};
|
||||
|
||||
Log.prototype.isInfoEnabled = function() {
|
||||
return (LEVELS.Info >= LEVELS[level]);
|
||||
};
|
||||
|
||||
Log.prototype.info = function() {
|
||||
if (this.isInfoEnabled())
|
||||
this._write('INFO', Array.prototype.slice.call(arguments));
|
||||
};
|
||||
|
||||
Log.prototype.isWarnEnabled = function() {
|
||||
return (LEVELS.Warn >= LEVELS[level]);
|
||||
};
|
||||
|
||||
Log.prototype.warn = function() {
|
||||
if (this.isWarnEnabled())
|
||||
this._write('WARN', Array.prototype.slice.call(arguments));
|
||||
};
|
||||
|
||||
Log.prototype.isErrorEnabled = function() {
|
||||
return (LEVELS.Error >= LEVELS[level]);
|
||||
};
|
||||
|
||||
Log.prototype.error = function() {
|
||||
if (this.isErrorEnabled())
|
||||
this._write('ERROR', Array.prototype.slice.call(arguments));
|
||||
};
|
||||
|
||||
Log.prototype.isFatalEnabled = function() {
|
||||
return (LEVELS.Fatal >= LEVELS[level]);
|
||||
};
|
||||
|
||||
Log.prototype.fatal = function() {
|
||||
if (this.isFatalEnabled())
|
||||
this._write('FATAL', Array.prototype.slice.call(arguments));
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
|
||||
setLevel: function(l) {
|
||||
l = l.charAt(0).toUpperCase() + l.slice(1).toLowerCase();
|
||||
if (LEVELS[l] !== undefined)
|
||||
level = l;
|
||||
|
||||
return level;
|
||||
},
|
||||
|
||||
getLogger: function(name) {
|
||||
if (!name || typeof(name) !== 'string')
|
||||
throw new TypeError('name (string) required');
|
||||
|
||||
return new Log(name);
|
||||
},
|
||||
|
||||
setGlobalLogLevel: function(l) {
|
||||
l = l.charAt(0).toUpperCase() + l.slice(1).toLowerCase();
|
||||
if (LEVELS[l] !== undefined)
|
||||
level = l;
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
};
|
|
@ -22,9 +22,9 @@ var Ber = asn1.Ber;
|
|||
|
||||
function AbandonRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.abandonID && typeof(options.abandonID) !== 'number')
|
||||
if (options.abandonID && typeof (options.abandonID) !== 'number')
|
||||
throw new TypeError('abandonID must be a number');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -35,14 +35,13 @@ function AbandonRequest(options) {
|
|||
|
||||
this.abandonID = options.abandonID || 0;
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'AbandonRequest'; });
|
||||
this.__defineGetter__('type', function () { return 'AbandonRequest'; });
|
||||
}
|
||||
util.inherits(AbandonRequest, LDAPMessage);
|
||||
module.exports = AbandonRequest;
|
||||
|
||||
|
||||
AbandonRequest.prototype._parse = function(ber, length) {
|
||||
AbandonRequest.prototype._parse = function (ber, length) {
|
||||
assert.ok(ber);
|
||||
assert.ok(length);
|
||||
|
||||
|
@ -71,13 +70,13 @@ AbandonRequest.prototype._parse = function(ber, length) {
|
|||
};
|
||||
|
||||
|
||||
AbandonRequest.prototype._toBer = function(ber) {
|
||||
AbandonRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
var i = this.abandonID;
|
||||
var sz = 4;
|
||||
|
||||
while ((((i & 0xff800000) == 0) || ((i & 0xff800000) == 0xff800000)) &&
|
||||
while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000)) &&
|
||||
(sz > 1)) {
|
||||
sz--;
|
||||
i <<= 8;
|
||||
|
@ -93,11 +92,10 @@ AbandonRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
AbandonRequest.prototype._json = function(j) {
|
||||
AbandonRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.abandonID = this.abandonID;
|
||||
|
||||
return j;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,20 +13,20 @@ var Protocol = require('../protocol');
|
|||
function AbandonResponse(options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
|
||||
options.protocolOp = 0;
|
||||
LDAPMessage.call(this, options);
|
||||
this.__defineGetter__('type', function() { return 'AbandonResponse'; });
|
||||
this.__defineGetter__('type', function () { return 'AbandonResponse'; });
|
||||
}
|
||||
util.inherits(AbandonResponse, LDAPMessage);
|
||||
module.exports = AbandonResponse;
|
||||
|
||||
|
||||
AbandonResponse.prototype.end = function(status) {};
|
||||
AbandonResponse.prototype.end = function (status) {};
|
||||
|
||||
|
||||
AbandonResponse.prototype._json = function(j) {
|
||||
AbandonResponse.prototype._json = function (j) {
|
||||
return j;
|
||||
};
|
||||
|
|
|
@ -22,14 +22,14 @@ var Ber = asn1.Ber;
|
|||
|
||||
function AddRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.entry && !(options.entry instanceof dn.DN))
|
||||
throw new TypeError('options.entry must be a DN');
|
||||
if (options.attributes) {
|
||||
if (!Array.isArray(options.attributes))
|
||||
throw new TypeError('options.attributes must be [Attribute]');
|
||||
options.attributes.forEach(function(a) {
|
||||
options.attributes.forEach(function (a) {
|
||||
if (!Attribute.isAttribute(a))
|
||||
throw new TypeError('options.attributes must be [Attribute]');
|
||||
});
|
||||
|
@ -45,14 +45,14 @@ function AddRequest(options) {
|
|||
this.attributes = options.attributes ? options.attributes.slice(0) : [];
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'AddRequest'; });
|
||||
this.__defineGetter__('_dn', function() { return self.entry; });
|
||||
this.__defineGetter__('type', function () { return 'AddRequest'; });
|
||||
this.__defineGetter__('_dn', function () { return self.entry; });
|
||||
}
|
||||
util.inherits(AddRequest, LDAPMessage);
|
||||
module.exports = AddRequest;
|
||||
|
||||
|
||||
AddRequest.prototype._parse = function(ber) {
|
||||
AddRequest.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.entry = dn.parse(ber.readString());
|
||||
|
@ -76,12 +76,12 @@ AddRequest.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
AddRequest.prototype._toBer = function(ber) {
|
||||
AddRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.entry.toString());
|
||||
ber.startSequence();
|
||||
this.attributes.forEach(function(a) {
|
||||
this.attributes.forEach(function (a) {
|
||||
a.toBer(ber);
|
||||
});
|
||||
ber.endSequence();
|
||||
|
@ -90,13 +90,13 @@ AddRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
AddRequest.prototype._json = function(j) {
|
||||
AddRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.entry = this.entry.toString();
|
||||
j.attributes = [];
|
||||
|
||||
this.attributes.forEach(function(a) {
|
||||
this.attributes.forEach(function (a) {
|
||||
j.attributes.push(a.json);
|
||||
});
|
||||
|
||||
|
@ -104,45 +104,47 @@ AddRequest.prototype._json = function(j) {
|
|||
};
|
||||
|
||||
|
||||
AddRequest.prototype.indexOf = function(attr) {
|
||||
if (!attr || typeof(attr) !== 'string')
|
||||
AddRequest.prototype.indexOf = function (attr) {
|
||||
if (!attr || typeof (attr) !== 'string')
|
||||
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)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
||||
AddRequest.prototype.attributeNames = function() {
|
||||
AddRequest.prototype.attributeNames = function () {
|
||||
var attrs = [];
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
AddRequest.prototype.getAttribute = function(name) {
|
||||
if (!name || typeof(name) !== 'string')
|
||||
AddRequest.prototype.getAttribute = function (name) {
|
||||
if (!name || typeof (name) !== 'string')
|
||||
throw new TypeError('attribute name (string) required');
|
||||
|
||||
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)
|
||||
return this.attribute[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
AddRequest.prototype.addAttribute = function(attr) {
|
||||
AddRequest.prototype.addAttribute = function (attr) {
|
||||
if (!(attr instanceof Attribute))
|
||||
throw new TypeEroror('attribute (Attribute) required');
|
||||
throw new TypeError('attribute (Attribute) required');
|
||||
|
||||
return this.attributes.push(attr);
|
||||
};
|
||||
|
@ -163,7 +165,7 @@ AddRequest.prototype.addAttribute = function(attr) {
|
|||
*
|
||||
* @return {Object} that looks like the above.
|
||||
*/
|
||||
AddRequest.prototype.toObject = function() {
|
||||
AddRequest.prototype.toObject = function () {
|
||||
var self = this;
|
||||
|
||||
var obj = {
|
||||
|
@ -174,11 +176,11 @@ AddRequest.prototype.toObject = function() {
|
|||
if (!this.attributes || !this.attributes.length)
|
||||
return obj;
|
||||
|
||||
this.attributes.forEach(function(a) {
|
||||
this.attributes.forEach(function (a) {
|
||||
if (!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)
|
||||
obj.attributes[a.type].push(v);
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ var Protocol = require('../protocol');
|
|||
|
||||
function AddResponse(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
} else {
|
||||
options = {};
|
||||
|
|
|
@ -24,7 +24,7 @@ var LDAP_BIND_SASL = 'sasl';
|
|||
///--- API
|
||||
|
||||
function BindRequest(options) {
|
||||
if (options && typeof(options) !== 'object')
|
||||
if (options && typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
|
||||
options = options || {};
|
||||
|
@ -38,14 +38,14 @@ function BindRequest(options) {
|
|||
this.credentials = options.credentials || '';
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'BindRequest'; });
|
||||
this.__defineGetter__('_dn', function() { return self.name; });
|
||||
this.__defineGetter__('type', function () { return 'BindRequest'; });
|
||||
this.__defineGetter__('_dn', function () { return self.name; });
|
||||
}
|
||||
util.inherits(BindRequest, LDAPMessage);
|
||||
module.exports = BindRequest;
|
||||
|
||||
|
||||
BindRequest.prototype._parse = function(ber) {
|
||||
BindRequest.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.version = ber.readInt();
|
||||
|
@ -64,7 +64,7 @@ BindRequest.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
BindRequest.prototype._toBer = function(ber) {
|
||||
BindRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeInt(this.version);
|
||||
|
@ -76,7 +76,7 @@ BindRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
BindRequest.prototype._json = function(j) {
|
||||
BindRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.version = this.version;
|
||||
|
|
|
@ -11,7 +11,7 @@ var Protocol = require('../protocol');
|
|||
|
||||
function BindResponse(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -22,4 +22,3 @@ function BindResponse(options) {
|
|||
}
|
||||
util.inherits(BindResponse, LDAPResult);
|
||||
module.exports = BindResponse;
|
||||
|
||||
|
|
|
@ -15,13 +15,13 @@ var Protocol = require('../protocol');
|
|||
|
||||
function CompareRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.entry && !(options.entry instanceof dn.DN))
|
||||
throw new TypeError('options.entry must be a DN');
|
||||
if (options.attribute && typeof(options.attribute) !== 'string')
|
||||
if (options.attribute && typeof (options.attribute) !== 'string')
|
||||
throw new TypeError('options.attribute must be a string');
|
||||
if (options.value && typeof(options.value) !== 'string')
|
||||
if (options.value && typeof (options.value) !== 'string')
|
||||
throw new TypeError('options.value must be a string');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -35,8 +35,8 @@ function CompareRequest(options) {
|
|||
this.value = options.value || '';
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'CompareRequest'; });
|
||||
this.__defineGetter__('_dn', function() {
|
||||
this.__defineGetter__('type', function () { return 'CompareRequest'; });
|
||||
this.__defineGetter__('_dn', function () {
|
||||
return self.entry ? self.entry.toString() : '';
|
||||
});
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ util.inherits(CompareRequest, LDAPMessage);
|
|||
module.exports = CompareRequest;
|
||||
|
||||
|
||||
CompareRequest.prototype._parse = function(ber) {
|
||||
CompareRequest.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.entry = dn.parse(ber.readString());
|
||||
|
@ -57,7 +57,7 @@ CompareRequest.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
CompareRequest.prototype._toBer = function(ber) {
|
||||
CompareRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.entry.toString());
|
||||
|
@ -70,7 +70,7 @@ CompareRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
CompareRequest.prototype._json = function(j) {
|
||||
CompareRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.entry = this.entry.toString();
|
||||
|
|
|
@ -11,7 +11,7 @@ var Protocol = require('../protocol');
|
|||
|
||||
function CompareResponse(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -24,9 +24,9 @@ util.inherits(CompareResponse, LDAPResult);
|
|||
module.exports = CompareResponse;
|
||||
|
||||
|
||||
CompareResponse.prototype.end = function(matches) {
|
||||
CompareResponse.prototype.end = function (matches) {
|
||||
var status = 0x06;
|
||||
if (typeof(matches) === 'boolean') {
|
||||
if (typeof (matches) === 'boolean') {
|
||||
if (!matches)
|
||||
status = 0x05; // Compare false
|
||||
} else {
|
||||
|
|
|
@ -22,7 +22,7 @@ var Ber = asn1.Ber;
|
|||
|
||||
function DeleteRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.entry && !(options.entry instanceof dn.DN))
|
||||
throw new TypeError('options.entry must be a DN');
|
||||
|
@ -36,14 +36,14 @@ function DeleteRequest(options) {
|
|||
this.entry = options.entry || null;
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'DeleteRequest'; });
|
||||
this.__defineGetter__('_dn', function() { return self.entry; });
|
||||
this.__defineGetter__('type', function () { return 'DeleteRequest'; });
|
||||
this.__defineGetter__('_dn', function () { return self.entry; });
|
||||
}
|
||||
util.inherits(DeleteRequest, LDAPMessage);
|
||||
module.exports = DeleteRequest;
|
||||
|
||||
|
||||
DeleteRequest.prototype._parse = function(ber, length) {
|
||||
DeleteRequest.prototype._parse = function (ber, length) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.entry = dn.parse(ber.buffer.slice(0, length).toString('utf8'));
|
||||
|
@ -53,7 +53,7 @@ DeleteRequest.prototype._parse = function(ber, length) {
|
|||
};
|
||||
|
||||
|
||||
DeleteRequest.prototype._toBer = function(ber) {
|
||||
DeleteRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
var buf = new Buffer(this.entry.toString());
|
||||
|
@ -64,7 +64,7 @@ DeleteRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
DeleteRequest.prototype._json = function(j) {
|
||||
DeleteRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.entry = this.entry;
|
||||
|
|
|
@ -10,7 +10,7 @@ var Protocol = require('../protocol');
|
|||
|
||||
function DeleteResponse(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
} else {
|
||||
options = {};
|
||||
|
|
|
@ -23,11 +23,11 @@ var Ber = asn1.Ber;
|
|||
|
||||
function ExtendedRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.requestName && typeof(options.requestName) !== 'string')
|
||||
if (options.requestName && typeof (options.requestName) !== 'string')
|
||||
throw new TypeError('options.requestName must be a string');
|
||||
if (options.requestValue && typeof(options.requestValue) !== 'string')
|
||||
if (options.requestValue && typeof (options.requestValue) !== 'string')
|
||||
throw new TypeError('options.requestValue must be a string');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -39,22 +39,22 @@ function ExtendedRequest(options) {
|
|||
this.requestName = options.requestName || '';
|
||||
this.requestValue = options.requestValue || undefined;
|
||||
|
||||
this.__defineGetter__('type', function() { return 'ExtendedRequest'; });
|
||||
this.__defineGetter__('_dn', function() { return this.requestName; });
|
||||
this.__defineGetter__('name', function() {
|
||||
this.__defineGetter__('type', function () { return 'ExtendedRequest'; });
|
||||
this.__defineGetter__('_dn', function () { return this.requestName; });
|
||||
this.__defineGetter__('name', function () {
|
||||
return this.requestName;
|
||||
});
|
||||
this.__defineGetter__('value', function() {
|
||||
this.__defineGetter__('value', function () {
|
||||
return this.requestValue;
|
||||
});
|
||||
this.__defineSetter__('name', function(name) {
|
||||
if (typeof(name) !== 'string')
|
||||
this.__defineSetter__('name', function (name) {
|
||||
if (typeof (name) !== 'string')
|
||||
throw new TypeError('name must be a string');
|
||||
|
||||
this.requestName = name;
|
||||
});
|
||||
this.__defineSetter__('value', function(val) {
|
||||
if (typeof(val) !== 'string')
|
||||
this.__defineSetter__('value', function (val) {
|
||||
if (typeof (val) !== 'string')
|
||||
throw new TypeError('value must be a string');
|
||||
|
||||
this.requestValue = val;
|
||||
|
@ -64,7 +64,7 @@ util.inherits(ExtendedRequest, LDAPMessage);
|
|||
module.exports = ExtendedRequest;
|
||||
|
||||
|
||||
ExtendedRequest.prototype._parse = function(ber) {
|
||||
ExtendedRequest.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.requestName = ber.readString(0x80);
|
||||
|
@ -75,7 +75,7 @@ ExtendedRequest.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ExtendedRequest.prototype._toBer = function(ber) {
|
||||
ExtendedRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.requestName, 0x80);
|
||||
|
@ -86,7 +86,7 @@ ExtendedRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ExtendedRequest.prototype._json = function(j) {
|
||||
ExtendedRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.requestName = this.requestName;
|
||||
|
|
|
@ -11,11 +11,11 @@ var Protocol = require('../protocol');
|
|||
|
||||
function ExtendedResponse(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.responseName && typeof(options.responseName) !== 'string')
|
||||
if (options.responseName && typeof (options.responseName) !== 'string')
|
||||
throw new TypeError('options.responseName must be a string');
|
||||
if (options.responseValue && typeof(options.responseValue) !== 'string')
|
||||
if (options.responseValue && typeof (options.responseValue) !== 'string')
|
||||
throw new TypeError('options.responseValue must be a string');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -27,20 +27,20 @@ function ExtendedResponse(options) {
|
|||
options.protocolOp = Protocol.LDAP_REP_EXTENSION;
|
||||
LDAPResult.call(this, options);
|
||||
|
||||
this.__defineGetter__('name', function() {
|
||||
this.__defineGetter__('name', function () {
|
||||
return this.responseName;
|
||||
});
|
||||
this.__defineGetter__('value', function() {
|
||||
this.__defineGetter__('value', function () {
|
||||
return this.responseValue;
|
||||
});
|
||||
this.__defineSetter__('name', function(name) {
|
||||
if (typeof(name) !== 'string')
|
||||
this.__defineSetter__('name', function (name) {
|
||||
if (typeof (name) !== 'string')
|
||||
throw new TypeError('name must be a string');
|
||||
|
||||
this.responseName = name;
|
||||
});
|
||||
this.__defineSetter__('value', function(val) {
|
||||
if (typeof(val) !== 'string')
|
||||
this.__defineSetter__('value', function (val) {
|
||||
if (typeof (val) !== 'string')
|
||||
throw new TypeError('value must be a string');
|
||||
|
||||
this.responseValue = val;
|
||||
|
@ -50,7 +50,7 @@ util.inherits(ExtendedResponse, LDAPResult);
|
|||
module.exports = ExtendedResponse;
|
||||
|
||||
|
||||
ExtendedResponse.prototype._parse = function(ber) {
|
||||
ExtendedResponse.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
if (!LDAPResult.prototype._parse.call(this, ber))
|
||||
|
@ -65,7 +65,7 @@ ExtendedResponse.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ExtendedResponse.prototype._toBer = function(ber) {
|
||||
ExtendedResponse.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
if (!LDAPResult.prototype._toBer.call(this, ber))
|
||||
|
@ -80,7 +80,7 @@ ExtendedResponse.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ExtendedResponse.prototype._json = function(j) {
|
||||
ExtendedResponse.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j = LDAPResult.prototype._json.call(this, j);
|
||||
|
|
|
@ -8,8 +8,6 @@ var asn1 = require('asn1');
|
|||
var Control = require('../controls').Control;
|
||||
var Protocol = require('../protocol');
|
||||
|
||||
var logStub = require('../log_stub');
|
||||
|
||||
|
||||
|
||||
///--- Globals
|
||||
|
@ -30,20 +28,20 @@ var getControl = require('../controls').getControl;
|
|||
* @param {Object} options stuff.
|
||||
*/
|
||||
function LDAPMessage(options) {
|
||||
if (!options || typeof(options) !== 'object')
|
||||
if (!options || typeof (options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
|
||||
this.messageID = options.messageID || 0;
|
||||
this.protocolOp = options.protocolOp || undefined;
|
||||
this.controls = options.controls ? options.controls.slice(0) : [];
|
||||
|
||||
this.log4js = options.log4js || logStub;
|
||||
this.log = options.log;
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('id', function() { return self.messageID; });
|
||||
this.__defineGetter__('dn', function() { return self._dn || ''; });
|
||||
this.__defineGetter__('type', function() { return 'LDAPMessage'; });
|
||||
this.__defineGetter__('json', function() {
|
||||
this.__defineGetter__('id', function () { return self.messageID; });
|
||||
this.__defineGetter__('dn', function () { return self._dn || ''; });
|
||||
this.__defineGetter__('type', function () { return 'LDAPMessage'; });
|
||||
this.__defineGetter__('json', function () {
|
||||
var j = {
|
||||
messageID: self.messageID,
|
||||
protocolOp: self.type
|
||||
|
@ -52,24 +50,19 @@ function LDAPMessage(options) {
|
|||
j.controls = self.controls;
|
||||
return j;
|
||||
});
|
||||
this.__defineGetter__('log', function() {
|
||||
if (!self._log)
|
||||
self._log = self.log4js.getLogger(self.type);
|
||||
return self._log;
|
||||
});
|
||||
}
|
||||
module.exports = LDAPMessage;
|
||||
|
||||
|
||||
LDAPMessage.prototype.toString = function() {
|
||||
LDAPMessage.prototype.toString = function () {
|
||||
return JSON.stringify(this.json);
|
||||
};
|
||||
|
||||
|
||||
LDAPMessage.prototype.parse = function(ber) {
|
||||
LDAPMessage.prototype.parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
if (this.log.isTraceEnabled())
|
||||
if (this.log.trace())
|
||||
this.log.trace('parse: data=%s', util.inspect(ber.buffer));
|
||||
|
||||
// Delegate off to the specific type to parse
|
||||
|
@ -86,13 +79,13 @@ LDAPMessage.prototype.parse = function(ber) {
|
|||
}
|
||||
}
|
||||
|
||||
if (this.log.isTraceEnabled())
|
||||
if (this.log.trace())
|
||||
this.log.trace('Parsing done: %j', this.json);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
LDAPMessage.prototype.toBer = function() {
|
||||
LDAPMessage.prototype.toBer = function () {
|
||||
var writer = new BerWriter();
|
||||
writer.startSequence();
|
||||
writer.writeInt(this.messageID);
|
||||
|
@ -104,7 +97,7 @@ LDAPMessage.prototype.toBer = function() {
|
|||
|
||||
if (this.controls && this.controls.length) {
|
||||
writer.startSequence(0xa0);
|
||||
this.controls.forEach(function(c) {
|
||||
this.controls.forEach(function (c) {
|
||||
c.toBer(writer);
|
||||
});
|
||||
writer.endSequence();
|
||||
|
|
|
@ -22,14 +22,14 @@ var Ber = asn1.Ber;
|
|||
|
||||
function ModifyDNRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.entry && !(options.entry instanceof dn.DN))
|
||||
throw new TypeError('options.entry must be a DN');
|
||||
if (options.newRdn && !(options.newRdn instanceof dn.DN))
|
||||
throw new TypeError('options.newRdn must be a DN');
|
||||
if (options.deleteOldRdn !== undefined &&
|
||||
typeof(options.deleteOldRdn) !== 'boolean')
|
||||
typeof (options.deleteOldRdn) !== 'boolean')
|
||||
throw new TypeError('options.deleteOldRdn must be a boolean');
|
||||
if (options.newSuperior && !(options.newSuperior instanceof dn.DN))
|
||||
throw new TypeError('options.newSuperior must be a DN');
|
||||
|
@ -47,14 +47,14 @@ function ModifyDNRequest(options) {
|
|||
this.newSuperior = options.newSuperior || null;
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'ModifyDNRequest'; });
|
||||
this.__defineGetter__('_dn', function() { return self.entry; });
|
||||
this.__defineGetter__('type', function () { return 'ModifyDNRequest'; });
|
||||
this.__defineGetter__('_dn', function () { return self.entry; });
|
||||
}
|
||||
util.inherits(ModifyDNRequest, LDAPMessage);
|
||||
module.exports = ModifyDNRequest;
|
||||
|
||||
|
||||
ModifyDNRequest.prototype._parse = function(ber) {
|
||||
ModifyDNRequest.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.entry = dn.parse(ber.readString());
|
||||
|
@ -67,7 +67,7 @@ ModifyDNRequest.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ModifyDNRequest.prototype._toBer = function(ber) {
|
||||
ModifyDNRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.entry.toString());
|
||||
|
@ -80,7 +80,7 @@ ModifyDNRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ModifyDNRequest.prototype._json = function(j) {
|
||||
ModifyDNRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.entry = this.entry.toString();
|
||||
|
|
|
@ -10,7 +10,7 @@ var Protocol = require('../protocol');
|
|||
|
||||
function ModifyDNResponse(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
} else {
|
||||
options = {};
|
||||
|
|
|
@ -7,6 +7,7 @@ var LDAPMessage = require('./message');
|
|||
var LDAPResult = require('./result');
|
||||
|
||||
var dn = require('../dn');
|
||||
var Attribute = require('../attribute');
|
||||
var Change = require('../change');
|
||||
var Protocol = require('../protocol');
|
||||
|
||||
|
@ -16,14 +17,14 @@ var Protocol = require('../protocol');
|
|||
|
||||
function ModifyRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.object && !(options.object instanceof dn.DN))
|
||||
throw new TypeError('options.object must be a DN');
|
||||
if (options.attributes) {
|
||||
if (!Array.isArray(options.attributes))
|
||||
throw new TypeError('options.attributes must be [Attribute]');
|
||||
options.attributes.forEach(function(a) {
|
||||
options.attributes.forEach(function (a) {
|
||||
if (!(a instanceof Attribute))
|
||||
throw new TypeError('options.attributes must be [Attribute]');
|
||||
});
|
||||
|
@ -39,14 +40,14 @@ function ModifyRequest(options) {
|
|||
this.changes = options.changes ? options.changes.slice(0) : [];
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'ModifyRequest'; });
|
||||
this.__defineGetter__('_dn', function() { return self.object; });
|
||||
this.__defineGetter__('type', function () { return 'ModifyRequest'; });
|
||||
this.__defineGetter__('_dn', function () { return self.object; });
|
||||
}
|
||||
util.inherits(ModifyRequest, LDAPMessage);
|
||||
module.exports = ModifyRequest;
|
||||
|
||||
|
||||
ModifyRequest.prototype._parse = function(ber) {
|
||||
ModifyRequest.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.object = dn.parse(ber.readString());
|
||||
|
@ -65,12 +66,12 @@ ModifyRequest.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ModifyRequest.prototype._toBer = function(ber) {
|
||||
ModifyRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.object.toString());
|
||||
ber.startSequence();
|
||||
this.changes.forEach(function(c) {
|
||||
this.changes.forEach(function (c) {
|
||||
c.toBer(ber);
|
||||
});
|
||||
ber.endSequence();
|
||||
|
@ -79,13 +80,13 @@ ModifyRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
ModifyRequest.prototype._json = function(j) {
|
||||
ModifyRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.object = this.object;
|
||||
j.changes = [];
|
||||
|
||||
this.changes.forEach(function(c) {
|
||||
this.changes.forEach(function (c) {
|
||||
j.changes.push(c.json);
|
||||
});
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ var Protocol = require('../protocol');
|
|||
|
||||
function ModifyResponse(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
} else {
|
||||
options = {};
|
||||
|
|
|
@ -48,26 +48,24 @@ var BerReader = asn1.BerReader;
|
|||
///--- API
|
||||
|
||||
function Parser(options) {
|
||||
if (!options || typeof(options) !== 'object')
|
||||
if (!options || typeof (options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
if (!options.log4js || typeof(options.log4js) !== 'object')
|
||||
throw new TypeError('options.log4js (object) required');
|
||||
if (typeof (options.log) !== 'object')
|
||||
throw new TypeError('options.log (object) required');
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.buffer = null;
|
||||
this.log4js = options.log4js;
|
||||
this.log = this.log4js.getLogger('Parser');
|
||||
this.log = options.log;
|
||||
}
|
||||
util.inherits(Parser, EventEmitter);
|
||||
module.exports = Parser;
|
||||
|
||||
|
||||
Parser.prototype.write = function(data) {
|
||||
Parser.prototype.write = function (data) {
|
||||
if (!data || !Buffer.isBuffer(data))
|
||||
throw new TypeError('data (buffer) required');
|
||||
|
||||
var log = this.log;
|
||||
var nextMessage = null;
|
||||
var self = this;
|
||||
|
||||
|
@ -113,10 +111,9 @@ Parser.prototype.write = function(data) {
|
|||
};
|
||||
|
||||
|
||||
Parser.prototype.getMessage = function(ber) {
|
||||
Parser.prototype.getMessage = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
var log = this.log;
|
||||
var self = this;
|
||||
|
||||
var messageID = ber.readInt();
|
||||
|
@ -209,8 +206,7 @@ Parser.prototype.getMessage = function(ber) {
|
|||
this.emit('error',
|
||||
new Error('protocolOp 0x' +
|
||||
(type ? type.toString(16) : '??') +
|
||||
' not supported'
|
||||
),
|
||||
' not supported'),
|
||||
new LDAPResult({
|
||||
messageID: messageID,
|
||||
protocolOp: type || Protocol.LDAP_REP_EXTENSION
|
||||
|
@ -222,7 +218,6 @@ Parser.prototype.getMessage = function(ber) {
|
|||
|
||||
return new Message({
|
||||
messageID: messageID,
|
||||
log4js: self.log4js
|
||||
log: self.log
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -22,20 +22,20 @@ var BerWriter = asn1.BerWriter;
|
|||
|
||||
function LDAPResult(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
if (options.status && typeof(options.status) !== 'number')
|
||||
if (options.status && typeof (options.status) !== 'number')
|
||||
throw new TypeError('options.status must be a number');
|
||||
if (options.matchedDN && typeof(options.matchedDN) !== 'string')
|
||||
if (options.matchedDN && typeof (options.matchedDN) !== 'string')
|
||||
throw new TypeError('options.matchedDN must be a string');
|
||||
if (options.errorMessage && typeof(options.errorMessage) !== 'string')
|
||||
if (options.errorMessage && typeof (options.errorMessage) !== 'string')
|
||||
throw new TypeError('options.errorMessage must be a string');
|
||||
|
||||
if (options.referrals) {
|
||||
if (!(options.referrals instanceof Array))
|
||||
throw new TypeError('options.referrrals must be an array[string]');
|
||||
options.referrals.forEach(function(r) {
|
||||
if (typeof(r) !== 'string')
|
||||
options.referrals.forEach(function (r) {
|
||||
if (typeof (r) !== 'string')
|
||||
throw new TypeError('options.referrals must be an array[string]');
|
||||
});
|
||||
}
|
||||
|
@ -52,20 +52,20 @@ function LDAPResult(options) {
|
|||
|
||||
this.connection = options.connection || null;
|
||||
|
||||
this.__defineGetter__('type', function() { return 'LDAPResult'; });
|
||||
this.__defineGetter__('type', function () { return 'LDAPResult'; });
|
||||
}
|
||||
util.inherits(LDAPResult, LDAPMessage);
|
||||
module.exports = LDAPResult;
|
||||
|
||||
|
||||
LDAPResult.prototype.end = function(status) {
|
||||
LDAPResult.prototype.end = function (status) {
|
||||
assert.ok(this.connection);
|
||||
|
||||
if (typeof(status) === 'number')
|
||||
if (typeof (status) === 'number')
|
||||
this.status = status;
|
||||
|
||||
var ber = this.toBer();
|
||||
if (this.log.isDebugEnabled())
|
||||
if (this.log.debug())
|
||||
this.log.debug('%s: sending: %j', this.connection.ldap.id, this.json);
|
||||
|
||||
try {
|
||||
|
@ -73,7 +73,7 @@ LDAPResult.prototype.end = function(status) {
|
|||
this.connection.write(ber);
|
||||
|
||||
if (self._dtraceOp && self._dtraceId) {
|
||||
dtrace.fire('server-' + self._dtraceOp + '-done', function() {
|
||||
dtrace.fire('server-' + self._dtraceOp + '-done', function () {
|
||||
var c = self.connection || {ldap: {}};
|
||||
return [
|
||||
self._dtraceId || 0,
|
||||
|
@ -94,7 +94,7 @@ LDAPResult.prototype.end = function(status) {
|
|||
};
|
||||
|
||||
|
||||
LDAPResult.prototype._parse = function(ber) {
|
||||
LDAPResult.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.status = ber.readEnumeration();
|
||||
|
@ -113,7 +113,7 @@ LDAPResult.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
LDAPResult.prototype._toBer = function(ber) {
|
||||
LDAPResult.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeEnumeration(this.status);
|
||||
|
@ -130,7 +130,7 @@ LDAPResult.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
LDAPResult.prototype._json = function(j) {
|
||||
LDAPResult.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.status = this.status;
|
||||
|
|
|
@ -22,7 +22,7 @@ var BerWriter = asn1.BerWriter;
|
|||
|
||||
function SearchEntry(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.objectName && !(options.objectName instanceof dn.DN))
|
||||
throw new TypeError('options.objectName must be a DN');
|
||||
|
@ -37,13 +37,13 @@ function SearchEntry(options) {
|
|||
this.setAttributes(options.attributes || []);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'SearchEntry'; });
|
||||
this.__defineGetter__('object', function() {
|
||||
this.__defineGetter__('type', function () { return 'SearchEntry'; });
|
||||
this.__defineGetter__('object', function () {
|
||||
var obj = {
|
||||
dn: self.dn.toString(),
|
||||
controls: []
|
||||
};
|
||||
self.attributes.forEach(function(a) {
|
||||
self.attributes.forEach(function (a) {
|
||||
if (a.vals && a.vals.length) {
|
||||
if (a.vals.length > 1) {
|
||||
obj[a.type] = a.vals.slice();
|
||||
|
@ -54,12 +54,12 @@ function SearchEntry(options) {
|
|||
obj[a.type] = [];
|
||||
}
|
||||
});
|
||||
self.controls.forEach(function(element, index, array) {
|
||||
self.controls.forEach(function (element, index, array) {
|
||||
obj.controls.push(element.json);
|
||||
});
|
||||
return obj;
|
||||
});
|
||||
this.__defineGetter__('_dn', function() {
|
||||
this.__defineGetter__('_dn', function () {
|
||||
return self.objectName;
|
||||
});
|
||||
}
|
||||
|
@ -67,21 +67,21 @@ util.inherits(SearchEntry, LDAPMessage);
|
|||
module.exports = SearchEntry;
|
||||
|
||||
|
||||
SearchEntry.prototype.addAttribute = function(attr) {
|
||||
if (!attr || typeof(attr) !== 'object')
|
||||
SearchEntry.prototype.addAttribute = function (attr) {
|
||||
if (!attr || typeof (attr) !== 'object')
|
||||
throw new TypeError('attr (attribute) required');
|
||||
|
||||
this.attributes.push(attr);
|
||||
};
|
||||
|
||||
|
||||
SearchEntry.prototype.toObject = function() {
|
||||
SearchEntry.prototype.toObject = function () {
|
||||
return this.object;
|
||||
};
|
||||
|
||||
|
||||
SearchEntry.prototype.fromObject = function(obj) {
|
||||
if (typeof(obj) !== 'object')
|
||||
SearchEntry.prototype.fromObject = function (obj) {
|
||||
if (typeof (obj) !== 'object')
|
||||
throw new TypeError('object required');
|
||||
|
||||
var self = this;
|
||||
|
@ -92,19 +92,19 @@ SearchEntry.prototype.fromObject = function(obj) {
|
|||
obj = obj.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]}));
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
SearchEntry.prototype.setAttributes = function(obj) {
|
||||
if (typeof(obj) !== 'object')
|
||||
SearchEntry.prototype.setAttributes = function (obj) {
|
||||
if (typeof (obj) !== 'object')
|
||||
throw new TypeError('object required');
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
obj.forEach(function(a) {
|
||||
obj.forEach(function (a) {
|
||||
if (!Attribute.isAttribute(a))
|
||||
throw new TypeError('entry must be an Array of Attributes');
|
||||
});
|
||||
|
@ -113,10 +113,10 @@ SearchEntry.prototype.setAttributes = function(obj) {
|
|||
var self = this;
|
||||
|
||||
self.attributes = [];
|
||||
Object.keys(obj).forEach(function(k) {
|
||||
Object.keys(obj).forEach(function (k) {
|
||||
var attr = new Attribute({type: k});
|
||||
if (Array.isArray(obj[k])) {
|
||||
obj[k].forEach(function(v) {
|
||||
obj[k].forEach(function (v) {
|
||||
attr.addValue(v.toString());
|
||||
});
|
||||
} else {
|
||||
|
@ -128,12 +128,12 @@ SearchEntry.prototype.setAttributes = function(obj) {
|
|||
};
|
||||
|
||||
|
||||
SearchEntry.prototype._json = function(j) {
|
||||
SearchEntry.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.objectName = this.objectName.toString();
|
||||
j.attributes = [];
|
||||
this.attributes.forEach(function(a) {
|
||||
this.attributes.forEach(function (a) {
|
||||
j.attributes.push(a.json || a);
|
||||
});
|
||||
|
||||
|
@ -141,7 +141,7 @@ SearchEntry.prototype._json = function(j) {
|
|||
};
|
||||
|
||||
|
||||
SearchEntry.prototype._parse = function(ber) {
|
||||
SearchEntry.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.objectName = ber.readString();
|
||||
|
@ -158,12 +158,12 @@ SearchEntry.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
SearchEntry.prototype._toBer = function(ber) {
|
||||
SearchEntry.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.objectName.toString());
|
||||
ber.startSequence();
|
||||
this.attributes.forEach(function(a) {
|
||||
this.attributes.forEach(function (a) {
|
||||
// This may or may not be an attribute
|
||||
ber = Attribute.toBer(a, ber);
|
||||
});
|
||||
|
@ -171,6 +171,3 @@ SearchEntry.prototype._toBer = function(ber) {
|
|||
|
||||
return ber;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ var parseURL = url.parse;
|
|||
|
||||
function SearchReference(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
if (options.objectName && !(options.objectName instanceof dn.DN))
|
||||
throw new TypeError('options.objectName must be a DN');
|
||||
|
@ -37,20 +37,20 @@ function SearchReference(options) {
|
|||
this.uris = options.uris || [];
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'SearchReference'; });
|
||||
this.__defineGetter__('object', function() {
|
||||
this.__defineGetter__('type', function () { return 'SearchReference'; });
|
||||
this.__defineGetter__('object', function () {
|
||||
return {
|
||||
dn: self.dn.toString(),
|
||||
uris: self.uris.slice()
|
||||
};
|
||||
});
|
||||
this.__defineGetter__('_dn', function() {
|
||||
this.__defineGetter__('_dn', function () {
|
||||
return new dn.DN('');
|
||||
});
|
||||
this.__defineGetter__('urls', function() {
|
||||
this.__defineGetter__('urls', function () {
|
||||
return self.uris;
|
||||
});
|
||||
this.__defineSetter__('urls', function(u) {
|
||||
this.__defineSetter__('urls', function (u) {
|
||||
self.uris = u.slice();
|
||||
});
|
||||
}
|
||||
|
@ -58,13 +58,13 @@ util.inherits(SearchReference, LDAPMessage);
|
|||
module.exports = SearchReference;
|
||||
|
||||
|
||||
SearchReference.prototype.toObject = function() {
|
||||
SearchReference.prototype.toObject = function () {
|
||||
return this.object;
|
||||
};
|
||||
|
||||
|
||||
SearchReference.prototype.fromObject = function(obj) {
|
||||
if (typeof(obj) !== 'object')
|
||||
SearchReference.prototype.fromObject = function (obj) {
|
||||
if (typeof (obj) !== 'object')
|
||||
throw new TypeError('object required');
|
||||
|
||||
this.uris = obj.uris ? obj.uris.slice() : [];
|
||||
|
@ -72,14 +72,14 @@ SearchReference.prototype.fromObject = function(obj) {
|
|||
return true;
|
||||
};
|
||||
|
||||
SearchReference.prototype._json = function(j) {
|
||||
SearchReference.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
j.uris = this.uris.slice();
|
||||
return j;
|
||||
};
|
||||
|
||||
|
||||
SearchReference.prototype._parse = function(ber, length) {
|
||||
SearchReference.prototype._parse = function (ber, length) {
|
||||
assert.ok(ber);
|
||||
|
||||
while (ber.offset < length) {
|
||||
|
@ -92,15 +92,12 @@ SearchReference.prototype._parse = function(ber, length) {
|
|||
};
|
||||
|
||||
|
||||
SearchReference.prototype._toBer = function(ber) {
|
||||
SearchReference.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.uris.forEach(function(u) {
|
||||
this.uris.forEach(function (u) {
|
||||
ber.writeString(u.href || u);
|
||||
});
|
||||
|
||||
return ber;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ var Ber = asn1.Ber;
|
|||
|
||||
function SearchRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -34,11 +34,11 @@ function SearchRequest(options) {
|
|||
LDAPMessage.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'SearchRequest'; });
|
||||
this.__defineGetter__('_dn', function() {
|
||||
this.__defineGetter__('type', function () { return 'SearchRequest'; });
|
||||
this.__defineGetter__('_dn', function () {
|
||||
return self.baseObject;
|
||||
});
|
||||
this.__defineGetter__('scope', function() {
|
||||
this.__defineGetter__('scope', function () {
|
||||
switch (self._scope) {
|
||||
case Protocol.SCOPE_BASE_OBJECT: return 'base';
|
||||
case Protocol.SCOPE_ONE_LEVEL: return 'one';
|
||||
|
@ -47,8 +47,8 @@ function SearchRequest(options) {
|
|||
throw new Error(self._scope + ' is an invalid search scope');
|
||||
}
|
||||
});
|
||||
this.__defineSetter__('scope', function(s) {
|
||||
if (typeof(s) === 'string') {
|
||||
this.__defineSetter__('scope', function (s) {
|
||||
if (typeof (s) === 'string') {
|
||||
switch (s) {
|
||||
case 'base':
|
||||
self._scope = Protocol.SCOPE_BASE_OBJECT;
|
||||
|
@ -67,7 +67,7 @@ function SearchRequest(options) {
|
|||
}
|
||||
});
|
||||
|
||||
this.baseObject = options.baseObject || new dn.DN([{}]);
|
||||
this.baseObject = options.baseObject || new dn.DN([ {} ]);
|
||||
this.scope = options.scope || 'base';
|
||||
this.derefAliases = options.derefAliases || Protocol.NEVER_DEREF_ALIASES;
|
||||
this.sizeLimit = options.sizeLimit || 0;
|
||||
|
@ -80,7 +80,7 @@ util.inherits(SearchRequest, LDAPMessage);
|
|||
module.exports = SearchRequest;
|
||||
|
||||
|
||||
SearchRequest.prototype.newResult = function() {
|
||||
SearchRequest.prototype.newResult = function () {
|
||||
var self = this;
|
||||
|
||||
return new LDAPResult({
|
||||
|
@ -90,7 +90,7 @@ SearchRequest.prototype.newResult = function() {
|
|||
};
|
||||
|
||||
|
||||
SearchRequest.prototype._parse = function(ber) {
|
||||
SearchRequest.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
this.baseObject = dn.parse(ber.readString());
|
||||
|
@ -114,7 +114,7 @@ SearchRequest.prototype._parse = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
SearchRequest.prototype._toBer = function(ber) {
|
||||
SearchRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
ber.writeString(this.baseObject.toString());
|
||||
|
@ -129,7 +129,7 @@ SearchRequest.prototype._toBer = function(ber) {
|
|||
|
||||
ber.startSequence(Ber.Sequence | Ber.Constructor);
|
||||
if (this.attributes && this.attributes.length) {
|
||||
this.attributes.forEach(function(a) {
|
||||
this.attributes.forEach(function (a) {
|
||||
ber.writeString(a);
|
||||
});
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ SearchRequest.prototype._toBer = function(ber) {
|
|||
};
|
||||
|
||||
|
||||
SearchRequest.prototype._json = function(j) {
|
||||
SearchRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
j.baseObject = this.baseObject;
|
||||
|
|
|
@ -19,7 +19,7 @@ var Protocol = require('../protocol');
|
|||
function SearchResponse(options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
|
||||
options.protocolOp = Protocol.LDAP_REP_SEARCH;
|
||||
|
@ -40,12 +40,12 @@ module.exports = SearchResponse;
|
|||
* @param {Boolean} nofiltering skip filtering notAttributes and '_' attributes.
|
||||
* Defaults to 'false'.
|
||||
*/
|
||||
SearchResponse.prototype.send = function(entry, nofiltering) {
|
||||
if (!entry || typeof(entry) !== 'object')
|
||||
SearchResponse.prototype.send = function (entry, nofiltering) {
|
||||
if (!entry || typeof (entry) !== 'object')
|
||||
throw new TypeError('entry (SearchEntry) required');
|
||||
if (nofiltering === undefined)
|
||||
nofiltering = false;
|
||||
if (typeof(nofiltering) !== 'boolean')
|
||||
if (typeof (nofiltering) !== 'boolean')
|
||||
throw new TypeError('noFiltering must be a boolean');
|
||||
|
||||
var self = this;
|
||||
|
@ -61,7 +61,7 @@ SearchResponse.prototype.send = function(entry, nofiltering) {
|
|||
|
||||
var savedAttrs = {};
|
||||
var all = (self.attributes.indexOf('*') !== -1);
|
||||
Object.keys(entry.attributes).forEach(function(a) {
|
||||
Object.keys(entry.attributes).forEach(function (a) {
|
||||
var _a = a.toLowerCase();
|
||||
if (!nofiltering && _a.length && _a[0] === '_') {
|
||||
savedAttrs[a] = entry.attributes[a];
|
||||
|
@ -70,7 +70,7 @@ SearchResponse.prototype.send = function(entry, nofiltering) {
|
|||
savedAttrs[a] = entry.attributes[a];
|
||||
delete entry.attributes[a];
|
||||
} else if (all) {
|
||||
// noop
|
||||
return;
|
||||
} else if (self.attributes.length && self.attributes.indexOf(_a) === -1) {
|
||||
savedAttrs[a] = entry.attributes[a];
|
||||
delete entry.attributes[a];
|
||||
|
@ -79,22 +79,22 @@ SearchResponse.prototype.send = function(entry, nofiltering) {
|
|||
|
||||
var save = entry;
|
||||
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,
|
||||
log4js: self.log4js
|
||||
log: self.log
|
||||
});
|
||||
entry.fromObject(save);
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.log.isDebugEnabled())
|
||||
if (this.log.debug())
|
||||
this.log.debug('%s: sending: %j', this.connection.ldap.id, entry.json);
|
||||
|
||||
this.connection.write(entry.toBer());
|
||||
this.sentEntries++;
|
||||
|
||||
if (self._dtraceOp && self._dtraceId) {
|
||||
dtrace.fire('server-search-entry', function() {
|
||||
dtrace.fire('server-search-entry', function () {
|
||||
var c = self.connection || {ldap: {}};
|
||||
return [
|
||||
self._dtraceId || 0,
|
||||
|
@ -108,7 +108,7 @@ SearchResponse.prototype.send = function(entry, nofiltering) {
|
|||
}
|
||||
|
||||
// Restore attributes
|
||||
Object.keys(savedAttrs).forEach(function(k) {
|
||||
Object.keys(savedAttrs).forEach(function (k) {
|
||||
save.attributes[k] = savedAttrs[k];
|
||||
});
|
||||
|
||||
|
@ -120,15 +120,15 @@ SearchResponse.prototype.send = function(entry, nofiltering) {
|
|||
|
||||
|
||||
|
||||
SearchResponse.prototype.createSearchEntry = function(object) {
|
||||
if (!object || typeof(object) !== 'object')
|
||||
SearchResponse.prototype.createSearchEntry = function (object) {
|
||||
if (!object || typeof (object) !== 'object')
|
||||
throw new TypeError('object required');
|
||||
|
||||
var self = this;
|
||||
|
||||
var entry = new SearchEntry({
|
||||
messageID: self.messageID,
|
||||
log4js: self.log4js,
|
||||
log: self.log,
|
||||
objectName: object.objectName || object.dn
|
||||
});
|
||||
entry.fromObject((object.attributes || object));
|
||||
|
@ -137,7 +137,7 @@ SearchResponse.prototype.createSearchEntry = function(object) {
|
|||
};
|
||||
|
||||
|
||||
SearchResponse.prototype.createSearchReference = function(uris) {
|
||||
SearchResponse.prototype.createSearchReference = function (uris) {
|
||||
if (!uris)
|
||||
throw new TypeError('uris ([string]) required');
|
||||
|
||||
|
@ -145,14 +145,14 @@ SearchResponse.prototype.createSearchReference = function(uris) {
|
|||
uris = [uris];
|
||||
|
||||
for (var i = 0; i < uris.length; i++) {
|
||||
if (typeof(uris[i]) == 'string')
|
||||
if (typeof (uris[i]) == 'string')
|
||||
uris[i] = parseURL(uris[i]);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
return new SearchReference({
|
||||
messageID: self.messageID,
|
||||
log4js: self.log4js,
|
||||
log: self.log,
|
||||
uris: uris
|
||||
});
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ var RDN = dn.RDN;
|
|||
|
||||
function UnbindRequest(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
} else {
|
||||
options = {};
|
||||
|
@ -35,8 +35,8 @@ function UnbindRequest(options) {
|
|||
LDAPMessage.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.__defineGetter__('type', function() { return 'UnbindRequest'; });
|
||||
this.__defineGetter__('_dn', function() {
|
||||
this.__defineGetter__('type', function () { return 'UnbindRequest'; });
|
||||
this.__defineGetter__('_dn', function () {
|
||||
if (self.connection)
|
||||
return self.connection.ldap.bindDN;
|
||||
|
||||
|
@ -47,21 +47,18 @@ util.inherits(UnbindRequest, LDAPMessage);
|
|||
module.exports = UnbindRequest;
|
||||
|
||||
|
||||
UnbindRequest.prototype.newResult = function() {
|
||||
var self = this;
|
||||
|
||||
UnbindRequest.prototype.newResult = function () {
|
||||
// This one is special, so just hack up the result object
|
||||
function UnbindResponse(options) {
|
||||
LDAPMessage.call(this, options);
|
||||
this.__defineGetter__('type', function() { return 'UnbindResponse'; });
|
||||
this.__defineGetter__('type', function () { return 'UnbindResponse'; });
|
||||
}
|
||||
util.inherits(UnbindResponse, LDAPMessage);
|
||||
UnbindResponse.prototype.end = function(status) {
|
||||
if (this.log.isTraceEnabled())
|
||||
log.trace('%s: unbinding!', this.connection.ldap.id);
|
||||
UnbindResponse.prototype.end = function (status) {
|
||||
this.log.trace('%s: unbinding!', this.connection.ldap.id);
|
||||
this.connection.end();
|
||||
};
|
||||
UnbindResponse.prototype._json = function(j) { return j; };
|
||||
UnbindResponse.prototype._json = function (j) { return j; };
|
||||
|
||||
return new UnbindResponse({
|
||||
messageID: 0,
|
||||
|
@ -71,21 +68,21 @@ UnbindRequest.prototype.newResult = function() {
|
|||
};
|
||||
|
||||
|
||||
UnbindRequest.prototype._parse = function(ber) {
|
||||
UnbindRequest.prototype._parse = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
UnbindRequest.prototype._toBer = function(ber) {
|
||||
UnbindRequest.prototype._toBer = function (ber) {
|
||||
assert.ok(ber);
|
||||
|
||||
return ber;
|
||||
};
|
||||
|
||||
|
||||
UnbindRequest.prototype._json = function(j) {
|
||||
UnbindRequest.prototype._json = function (j) {
|
||||
assert.ok(j);
|
||||
|
||||
return j;
|
||||
|
|
|
@ -17,12 +17,12 @@ var Protocol = require('../protocol');
|
|||
function UnbindResponse(options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options must be an object');
|
||||
|
||||
options.protocolOp = 0;
|
||||
LDAPMessage.call(this, options);
|
||||
this.__defineGetter__('type', function() { return 'UnbindResponse'; });
|
||||
this.__defineGetter__('type', function () { return 'UnbindResponse'; });
|
||||
}
|
||||
util.inherits(UnbindResponse, LDAPMessage);
|
||||
module.exports = UnbindResponse;
|
||||
|
@ -33,17 +33,16 @@ module.exports = UnbindResponse;
|
|||
*
|
||||
* @param {Number} status completely ignored.
|
||||
*/
|
||||
UnbindResponse.prototype.end = function(status) {
|
||||
UnbindResponse.prototype.end = function (status) {
|
||||
assert.ok(this.connection);
|
||||
|
||||
if (this.log.isTraceEnabled())
|
||||
this.log.trace('%s: unbinding!', this.connection.ldap.id);
|
||||
this.log.trace('%s: unbinding!', this.connection.ldap.id);
|
||||
|
||||
this.connection.end();
|
||||
|
||||
var self = this;
|
||||
if (self._dtraceOp && self._dtraceId) {
|
||||
dtrace.fire('server-' + self._dtraceOp + '-done', function() {
|
||||
dtrace.fire('server-' + self._dtraceOp + '-done', function () {
|
||||
var c = self.connection || {ldap: {}};
|
||||
return [
|
||||
self._dtraceId || 0,
|
||||
|
@ -58,6 +57,6 @@ UnbindResponse.prototype.end = function(status) {
|
|||
};
|
||||
|
||||
|
||||
UnbindResponse.prototype._json = function(j) {
|
||||
UnbindResponse.prototype._json = function (j) {
|
||||
return j;
|
||||
};
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var dn = require('../dn');
|
||||
var errors = require('../errors');
|
||||
var logStub = require('../log_stub');
|
||||
|
||||
var getTransformer = require('./transform').getTransformer;
|
||||
|
||||
|
||||
|
||||
function createAddHandler(options) {
|
||||
if (!options || typeof(options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
if (!options.schema || typeof(options.schema) !== 'object')
|
||||
throw new TypeError('options.schema (object) required');
|
||||
|
||||
var log4js = options.log4js || logStub;
|
||||
var log = log4js.getLogger('SchemaAddHandler');
|
||||
var schema = options.schema;
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug('Creating add schema handler with: %s',
|
||||
JSON.stringify(options.schema, null, 2));
|
||||
|
||||
var CVErr = errors.ConstraintViolationError;
|
||||
var NSAErr = errors.NoSuchAttributeError;
|
||||
var OCVErr = errors.ObjectclassViolationError;
|
||||
|
||||
return function schemaAddHandler(req, res, next) {
|
||||
var allowed = [];
|
||||
var attributes = req.toObject().attributes;
|
||||
var attrNames = Object.keys(attributes);
|
||||
var i;
|
||||
var j;
|
||||
var k;
|
||||
var key;
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug('%s running %j against schema', req.logId, attributes);
|
||||
|
||||
if (!attributes.objectclass)
|
||||
return next(new OCVErr('no objectclass'));
|
||||
|
||||
for (i = 0; i < attributes.objectclass.length; i++) {
|
||||
var oc = attributes.objectclass[i].toLowerCase();
|
||||
if (!schema.objectclasses[oc])
|
||||
return next(new NSAErr(oc + ' is not a known objectClass'));
|
||||
|
||||
// We can check required attributes right here in line. Mays we have to
|
||||
// get the complete set of though. Also, to make checking much simpler,
|
||||
// we just push the musts into the may list.
|
||||
var must = schema.objectclasses[oc].must;
|
||||
for (j = 0; j < must.length; j++) {
|
||||
if (attrNames.indexOf(must[j]) === -1)
|
||||
return next(new OCVErr(must[j] + ' is a required attribute'));
|
||||
if (allowed.indexOf(must[j]) === -1)
|
||||
allowed.push(must[j]);
|
||||
}
|
||||
|
||||
schema.objectclasses[oc].may.forEach(function(attr) {
|
||||
if (allowed.indexOf(attr) === -1)
|
||||
allowed.push(attr);
|
||||
});
|
||||
}
|
||||
|
||||
// Now check that the entry's attributes are in the allowed list, and go
|
||||
// ahead and transform the values as appropriate
|
||||
for (i = 0; i < attrNames.length; i++) {
|
||||
key = attrNames[i];
|
||||
if (allowed.indexOf(key) === -1)
|
||||
return next(new OCVErr(key + ' is not valid for the objectClasses ' +
|
||||
attributes.objectclass.join()));
|
||||
|
||||
var transform = getTransformer(schema, key);
|
||||
if (transform) {
|
||||
for (j = 0; j < attributes[key].length; j++) {
|
||||
try {
|
||||
attributes[key][j] = transform(attributes[key][j]);
|
||||
} catch (e) {
|
||||
log.debug('%s Error parsing %s: %s', req.logId, k,
|
||||
attributes[key][j],
|
||||
e.stack);
|
||||
return next(new CVErr(attrNames[i]));
|
||||
}
|
||||
}
|
||||
for (j = 0; j < req.attributes.length; j++) {
|
||||
if (req.attributes[j].type === key) {
|
||||
req.attributes[j].vals = attributes[key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = createAddHandler;
|
||||
|
||||
// Now we have a modified attributes object we want to update
|
||||
// "transparently" in the request.
|
||||
// if (xformedValues) {
|
||||
// attrNames.forEach(function(k) {
|
||||
// for (var i = 0; i < req.attributes.length; i++) {
|
||||
// if (req.attributes[i].type === k) {
|
||||
// req.attributes[i].vals = attributes[k];
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var createAddHandler = require('./add_handler');
|
||||
var createModifyHandler = require('./mod_handler');
|
||||
var createSearchHandler = require('./search_handler');
|
||||
var parser = require('./parser');
|
||||
|
||||
|
||||
|
||||
///--- API
|
||||
|
||||
module.exports = {
|
||||
|
||||
createAddHandler: createAddHandler,
|
||||
|
||||
createModifyHandler: createModifyHandler,
|
||||
|
||||
createSearchHandler: createSearchHandler,
|
||||
|
||||
load: parser.load
|
||||
|
||||
};
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var dn = require('../dn');
|
||||
var errors = require('../errors');
|
||||
var logStub = require('../log_stub');
|
||||
|
||||
var getTransformer = require('./transform').getTransformer;
|
||||
|
||||
|
||||
|
||||
function createModifyHandler(options) {
|
||||
if (!options || typeof(options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
if (!options.schema || typeof(options.schema) !== 'object')
|
||||
throw new TypeError('options.schema (object) required');
|
||||
// TODO add a callback mechanism here so objectclass constraints can be
|
||||
// enforced
|
||||
|
||||
var log4js = options.log4js || logStub;
|
||||
var log = log4js.getLogger('SchemaModifyHandler');
|
||||
var schema = options.schema;
|
||||
|
||||
var CVErr = errors.ConstraintViolationError;
|
||||
var NSAErr = errors.NoSuchAttributeError;
|
||||
var OCVErr = errors.ObjectclassViolationError;
|
||||
|
||||
return function schemaModifyHandler(req, res, next) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug('%s running %j against schema', req.logId, req.changes);
|
||||
|
||||
for (var i = 0; i < req.changes.length; i++) {
|
||||
var mod = req.changes[i].modification;
|
||||
var attribute = schema.attributes[mod.type];
|
||||
if (!attribute)
|
||||
return next(new NSAErr(mod.type));
|
||||
|
||||
if (!mod.vals || !mod.vals.length)
|
||||
continue;
|
||||
|
||||
var transform = getTransformer(schema, mod.type);
|
||||
if (transform) {
|
||||
for (var j = 0; j < mod.vals.length; j++) {
|
||||
try {
|
||||
mod.vals[j] = transform(mod.vals[j]);
|
||||
} catch (e) {
|
||||
log.debug('%s Error parsing %s: %s', req.logId, mod.vals[j],
|
||||
e.stack);
|
||||
return next(new CVErr(mod.type + ': ' + mod.vals[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = createModifyHandler;
|
|
@ -1,437 +0,0 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
|
||||
var dn = require('../dn');
|
||||
var errors = require('../errors');
|
||||
var logStub = require('../log_stub');
|
||||
|
||||
|
||||
|
||||
//// Attribute BNF
|
||||
//
|
||||
// AttributeTypeDescription = "(" whsp
|
||||
// numericoid whsp ; AttributeType identifier
|
||||
// [ "NAME" qdescrs ] ; name used in AttributeType
|
||||
// [ "DESC" qdstring ] ; description
|
||||
// [ "OBSOLETE" whsp ]
|
||||
// [ "SUP" woid ] ; derived from this other
|
||||
// ; AttributeType
|
||||
// [ "EQUALITY" woid ; Matching Rule name
|
||||
// [ "ORDERING" woid ; Matching Rule name
|
||||
// [ "SUBSTR" woid ] ; Matching Rule name
|
||||
// [ "SYNTAX" whsp noidlen whsp ] ; Syntax OID
|
||||
// [ "SINGLE-VALUE" whsp ] ; default multi-valued
|
||||
// [ "COLLECTIVE" whsp ] ; default not collective
|
||||
// [ "NO-USER-MODIFICATION" whsp ]; default user modifiable
|
||||
// [ "USAGE" whsp AttributeUsage ]; default userApplications
|
||||
// whsp ")"
|
||||
//
|
||||
// AttributeUsage =
|
||||
// "userApplications" /
|
||||
// "directoryOperation" /
|
||||
// "distributedOperation" / ; DSA-shared
|
||||
// "dSAOperation" ; DSA-specific, value depends on server
|
||||
|
||||
/// Objectclass BNF
|
||||
//
|
||||
// ObjectClassDescription = "(" whsp
|
||||
// numericoid whsp ; ObjectClass identifier
|
||||
// [ "NAME" qdescrs ]
|
||||
// [ "DESC" qdstring ]
|
||||
// [ "OBSOLETE" whsp ]
|
||||
// [ "SUP" oids ] ; Superior ObjectClasses
|
||||
// [ ( "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" ) whsp ]
|
||||
// ; default structural
|
||||
// [ "MUST" oids ] ; AttributeTypes
|
||||
// [ "MAY" oids ] ; AttributeTypes
|
||||
// whsp ")"
|
||||
|
||||
// This is some fugly code, and really not that robust, but LDAP schema
|
||||
// is a pita with its optional ('s. So, whatever, it's good enough for our
|
||||
// purposes (namely, dropping in the OpenLDAP schema). This took me a little
|
||||
// over an hour to write, so there you go ;)
|
||||
|
||||
function parse(data) {
|
||||
if (!data || typeof(data) !== 'string')
|
||||
throw new TypeError('data (string) required');
|
||||
|
||||
var lines = [];
|
||||
data.split('\n').forEach(function(l) {
|
||||
if (/^#/.test(l) ||
|
||||
/^objectidentifier/i.test(l) ||
|
||||
!l.length)
|
||||
return;
|
||||
|
||||
lines.push(l);
|
||||
});
|
||||
|
||||
var attr;
|
||||
var oc;
|
||||
var syntax;
|
||||
var attributes = [];
|
||||
var objectclasses = [];
|
||||
var depth = 0;
|
||||
lines.join('\n').split(/\s+/).forEach(function(w) {
|
||||
if (attr) {
|
||||
if (w === '(') {
|
||||
depth++;
|
||||
} else if (w === ')') {
|
||||
if (--depth === 0) {
|
||||
if (attr._skip)
|
||||
delete attr._skip;
|
||||
|
||||
attributes.push(attr);
|
||||
attr = null;
|
||||
}
|
||||
return;
|
||||
} else if (!attr.oid) {
|
||||
attr.oid = w;
|
||||
} else if (w === 'NAME') {
|
||||
attr._names = [];
|
||||
} else if (w === 'DESC') {
|
||||
attr._desc = '';
|
||||
} else if (w === 'OBSOLETE') {
|
||||
attr.obsolete = true;
|
||||
} else if (w === 'SUP') {
|
||||
attr._sup = true;
|
||||
} else if (attr._sup) {
|
||||
attr.sup = w;
|
||||
delete attr._sup;
|
||||
} else if (w === 'EQUALITY') {
|
||||
attr._equality = true;
|
||||
} else if (w === 'ORDERING') {
|
||||
attr._ordering = true;
|
||||
} else if (w === 'SUBSTR') {
|
||||
attr._substr = true;
|
||||
} else if (w === 'SYNTAX') {
|
||||
attr._syntax = true;
|
||||
} else if (w === 'SINGLE-VALUE') {
|
||||
attr.singleValue = true;
|
||||
} else if (w === 'COLLECTIVE') {
|
||||
attr.collective = true;
|
||||
} else if (w === 'NO-USER-MODIFICATION') {
|
||||
attr.noUserModification = true;
|
||||
} else if (w === 'USAGE') {
|
||||
attr._usage = true;
|
||||
} else if (/^X-/.test(w)) {
|
||||
attr._skip = true;
|
||||
} else if (attr._skip) {
|
||||
// noop
|
||||
} else if (attr._usage) {
|
||||
attr.usage = w;
|
||||
delete attr._usage;
|
||||
} else if (attr._syntax) {
|
||||
attr.syntax = w;
|
||||
delete attr._syntax;
|
||||
} else if (attr._substr) {
|
||||
attr.substr = w;
|
||||
delete attr._substr;
|
||||
} else if (attr._ordering) {
|
||||
attr.ordering = w;
|
||||
delete attr._ordering;
|
||||
} else if (attr._equality) {
|
||||
attr.equality = w;
|
||||
delete attr._equality;
|
||||
} else if (attr._desc !== undefined) {
|
||||
attr._desc += w.replace(/\'/g, '');
|
||||
if (/\'$/.test(w)) {
|
||||
attr.desc = attr._desc;
|
||||
delete attr._desc;
|
||||
} else {
|
||||
attr._desc += ' ';
|
||||
}
|
||||
} else if (attr._names) {
|
||||
attr._names.push(w.replace(/\'/g, '').toLowerCase());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (oc) {
|
||||
if (w === '(') {
|
||||
depth++;
|
||||
} else if (w === ')') {
|
||||
if (--depth === 0) {
|
||||
objectclasses.push(oc);
|
||||
oc = null;
|
||||
}
|
||||
return;
|
||||
} else if (w === '$') {
|
||||
return;
|
||||
} else if (!oc.oid) {
|
||||
oc.oid = w;
|
||||
} else if (w === 'NAME') {
|
||||
oc._names = [];
|
||||
} else if (w === 'DESC') {
|
||||
oc._desc = '';
|
||||
} else if (w === 'OBSOLETE') {
|
||||
oc.obsolete = true;
|
||||
} else if (w === 'SUP') {
|
||||
oc._sup = [];
|
||||
} else if (w === 'ABSTRACT') {
|
||||
oc['abstract'] = true;
|
||||
} else if (w === 'AUXILIARY') {
|
||||
oc.auxiliary = true;
|
||||
} else if (w === 'STRUCTURAL') {
|
||||
oc.structural = true;
|
||||
} else if (w === 'MUST') {
|
||||
oc._must = [];
|
||||
} else if (w === 'MAY') {
|
||||
oc._may = [];
|
||||
} else if (oc._may) {
|
||||
oc._may.push(w.toLowerCase());
|
||||
} else if (oc._must) {
|
||||
oc._must.push(w.toLowerCase());
|
||||
} else if (oc._sup) {
|
||||
oc._sup.push(w.replace(/\'/g, '').toLowerCase());
|
||||
} else if (oc._desc !== undefined) {
|
||||
oc._desc += w.replace(/\'/g, '');
|
||||
if (/\'$/.test(w)) {
|
||||
oc.desc = oc._desc;
|
||||
delete oc._desc;
|
||||
} else {
|
||||
oc._desc += ' ';
|
||||
}
|
||||
} else if (oc._names) {
|
||||
oc._names.push(w.replace(/\'/g, '').toLowerCase());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Throw this away for now.
|
||||
if (syntax) {
|
||||
if (w === '(') {
|
||||
depth++;
|
||||
} else if (w === ')') {
|
||||
if (--depth === 0) {
|
||||
syntax = false;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (/^attributetype/i.test(w)) {
|
||||
attr = {};
|
||||
} else if (/^objectclass/i.test(w)) {
|
||||
oc = {};
|
||||
} else if (/^ldapsyntax/i.test(w)) {
|
||||
syntax = true;
|
||||
} else if (!w) {
|
||||
// noop
|
||||
} else {
|
||||
throw new Error('Invalid token ' + w + ' in file ' + file);
|
||||
}
|
||||
});
|
||||
|
||||
// cleanup all the temporary arrays
|
||||
var i;
|
||||
for (i = 0; i < attributes.length; i++) {
|
||||
if (!attributes[i]._names)
|
||||
continue;
|
||||
|
||||
attributes[i].names = attributes[i]._names;
|
||||
delete attributes[i]._names;
|
||||
}
|
||||
for (i = 0; i < objectclasses.length; i++) {
|
||||
oc = objectclasses[i];
|
||||
if (oc._names) {
|
||||
oc.names = oc._names;
|
||||
delete oc._names;
|
||||
} else {
|
||||
oc.names = [];
|
||||
}
|
||||
if (oc._sup) {
|
||||
oc.sup = oc._sup;
|
||||
delete oc._sup;
|
||||
} else {
|
||||
oc.sup = [];
|
||||
}
|
||||
if (oc._must) {
|
||||
oc.must = oc._must;
|
||||
delete oc._must;
|
||||
} else {
|
||||
oc.must = [];
|
||||
}
|
||||
if (oc._may) {
|
||||
oc.may = oc._may;
|
||||
delete oc._may;
|
||||
} else {
|
||||
oc.may = [];
|
||||
}
|
||||
}
|
||||
|
||||
var _attributes = {};
|
||||
var _objectclasses = {};
|
||||
attributes.forEach(function(a) {
|
||||
for (var i = 0; i < a.names.length; i++) {
|
||||
a.names[i] = a.names[i].toLowerCase();
|
||||
_attributes[a.names[i]] = a;
|
||||
}
|
||||
});
|
||||
|
||||
objectclasses.forEach(function(oc) {
|
||||
for (var i = 0; i < oc.names.length; i++) {
|
||||
oc.names[i] = oc.names[i].toLowerCase();
|
||||
_objectclasses[oc.names[i]] = oc;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
attributes: _attributes,
|
||||
objectclasses: _objectclasses
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function parseFile(file, callback) {
|
||||
if (!file || typeof(file) !== 'string')
|
||||
throw new TypeError('file (string) required');
|
||||
if (!callback || typeof(callback) !== 'function')
|
||||
throw new TypeError('callback (function) required');
|
||||
|
||||
fs.readFile(file, 'utf8', function(err, data) {
|
||||
if (err)
|
||||
return callback(new errors.OperationsError(err.message));
|
||||
|
||||
try {
|
||||
return callback(null, parse(data));
|
||||
} catch (e) {
|
||||
return callback(new errors.OperationsError(e.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function _merge(child, parent) {
|
||||
Object.keys(parent).forEach(function(k) {
|
||||
if (Array.isArray(parent[k])) {
|
||||
if (k === 'names' || k === 'sup')
|
||||
return;
|
||||
|
||||
if (!child[k])
|
||||
child[k] = [];
|
||||
|
||||
parent[k].forEach(function(v) {
|
||||
if (child[k].indexOf(v) === -1)
|
||||
child[k].push(v);
|
||||
});
|
||||
} else if (!child[k]) {
|
||||
child[k] = parent[k];
|
||||
}
|
||||
});
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
function compile(attributes, objectclasses) {
|
||||
assert.ok(attributes);
|
||||
assert.ok(objectclasses);
|
||||
|
||||
var _attributes = {};
|
||||
var _objectclasses = {};
|
||||
|
||||
Object.keys(attributes).forEach(function(k) {
|
||||
_attributes[k] = attributes[k];
|
||||
|
||||
var sup;
|
||||
if (attributes[k].sup && (sup = attributes[attributes[k].sup]))
|
||||
_attributes[k] = _merge(_attributes[k], sup);
|
||||
|
||||
_attributes[k].names.sort();
|
||||
});
|
||||
|
||||
Object.keys(objectclasses).forEach(function(k) {
|
||||
_objectclasses[k] = objectclasses[k];
|
||||
var sup;
|
||||
if (objectclasses[k].sup && (sup = objectclasses[objectclasses[k].sup]))
|
||||
_objectclasses[k] = _merge(_objectclasses[k], sup);
|
||||
|
||||
_objectclasses[k].names.sort();
|
||||
_objectclasses[k].sup.sort();
|
||||
_objectclasses[k].must.sort();
|
||||
_objectclasses[k].may.sort();
|
||||
});
|
||||
|
||||
return {
|
||||
attributes: _attributes,
|
||||
objectclasses: _objectclasses
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Loads all the `.schema` files in a directory, and parses them.
|
||||
*
|
||||
* This method returns the set of schema from all files, and the "last one"
|
||||
* wins, so don't do something stupid like have the same attribute defined
|
||||
* N times with varying definitions.
|
||||
*
|
||||
* @param {String} directory the directory of *.schema files to load.
|
||||
* @param {Function} callback of the form f(err, attributes, objectclasses).
|
||||
* @throws {TypeEror} on bad input.
|
||||
*/
|
||||
function load(directory, callback) {
|
||||
if (!directory || typeof(directory) !== 'string')
|
||||
throw new TypeError('directory (string) required');
|
||||
if (!callback || typeof(callback) !== 'function')
|
||||
throw new TypeError('callback (function) required');
|
||||
|
||||
fs.readdir(directory, function(err, files) {
|
||||
if (err)
|
||||
return callback(new errors.OperationsError(err.message));
|
||||
|
||||
var finished = 0;
|
||||
var attributes = {};
|
||||
var objectclasses = {};
|
||||
files.forEach(function(f) {
|
||||
if (!/\.schema$/.test(f)) {
|
||||
++finished;
|
||||
return;
|
||||
}
|
||||
|
||||
f = directory + '/' + f;
|
||||
parseFile(f, function(err, schema) {
|
||||
var cb = callback;
|
||||
if (err) {
|
||||
callback = null;
|
||||
if (cb)
|
||||
return cb(new errors.OperationsError(err.message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(schema.attributes).forEach(function(a) {
|
||||
attributes[a] = schema.attributes[a];
|
||||
});
|
||||
Object.keys(schema.objectclasses).forEach(function(oc) {
|
||||
objectclasses[oc] = schema.objectclasses[oc];
|
||||
});
|
||||
|
||||
if (++finished === files.length) {
|
||||
if (cb) {
|
||||
schema = compile(attributes, objectclasses);
|
||||
return cb(null, schema);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
///--- Exported API
|
||||
|
||||
module.exports = {
|
||||
|
||||
load: load,
|
||||
parse: parse,
|
||||
parseFile: parseFile
|
||||
|
||||
|
||||
};
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var dn = require('../dn');
|
||||
var errors = require('../errors');
|
||||
var logStub = require('../log_stub');
|
||||
|
||||
var getTransformer = require('./transform').getTransformer;
|
||||
|
||||
|
||||
function transformFilter(schema, filter) {
|
||||
assert.ok(schema);
|
||||
assert.ok(filter);
|
||||
|
||||
var attributes = schema.attributes;
|
||||
|
||||
switch (filter.type) {
|
||||
case 'equal':
|
||||
case 'approx':
|
||||
case 'ge':
|
||||
case 'le':
|
||||
if (!attributes[filter.attribute.toLowerCase()])
|
||||
throw new errors.NoSuchAttributeError(filter.attribute);
|
||||
|
||||
var transform = getTransformer(schema, filter.attribute);
|
||||
if (transform)
|
||||
filter.value = transform(filter.value) || filter.value;
|
||||
|
||||
break;
|
||||
|
||||
case 'substring':
|
||||
case 'present':
|
||||
if (!attributes[filter.attribute.toLowerCase()])
|
||||
throw new errors.NoSuchAttributeError(filter.attribute);
|
||||
|
||||
break;
|
||||
|
||||
case 'and':
|
||||
case 'or':
|
||||
for (var i = 0; i < filter.filters.length; i++)
|
||||
filter.filters[i] = transformFilter(schema, filter.filters[i]);
|
||||
|
||||
break;
|
||||
|
||||
case 'not':
|
||||
filter.filter = trasnformFilter(schema, filter.filter);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function createSearchHandler(options) {
|
||||
if (!options || typeof(options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
if (!options.schema || typeof(options.schema) !== 'object')
|
||||
throw new TypeError('options.schema (object) required');
|
||||
|
||||
var log4js = options.log4js || logStub;
|
||||
var log = log4js.getLogger('SchemaSearchHandler');
|
||||
var schema = options.schema;
|
||||
|
||||
var CVErr = errors.ConstraintViolationError;
|
||||
var NSAErr = errors.NoSuchAttributeError;
|
||||
var OCVErr = errors.ObjectclassViolationError;
|
||||
|
||||
return function schemaSearchHandler(req, res, next) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug('%s running %j against schema', req.logId, req.filter);
|
||||
|
||||
try {
|
||||
req.filter = transformFilter(schema, req.filter);
|
||||
} catch (e) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug('%s error transforming filter: %s', req.logId, e.stack);
|
||||
return next(e);
|
||||
}
|
||||
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = createSearchHandler;
|
|
@ -1,139 +0,0 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var dn = require('../dn');
|
||||
|
||||
|
||||
|
||||
///--- API
|
||||
|
||||
function _getTransformer(syntax) {
|
||||
assert.ok(syntax);
|
||||
|
||||
// TODO size enforcement
|
||||
if (/\}$/.test(syntax))
|
||||
syntax = syntax.replace(/\{.+\}$/, '');
|
||||
|
||||
switch (syntax) {
|
||||
case '1.3.6.1.4.1.1466.115.121.1.27': // int
|
||||
case '1.3.6.1.4.1.1466.115.121.1.36': // numeric string
|
||||
return function(value) {
|
||||
return parseInt(value, 10);
|
||||
};
|
||||
|
||||
case '1.3.6.1.4.1.1466.115.121.1.7': // boolean
|
||||
return function(value) {
|
||||
return /^true$/i.test(value);
|
||||
};
|
||||
|
||||
case '1.3.6.1.4.1.1466.115.121.1.5': // binary
|
||||
return function(value) {
|
||||
return new Buffer(value).toString('base64');
|
||||
};
|
||||
|
||||
case '1.3.6.1.4.1.1466.115.121.1.12': // dn syntax
|
||||
return function(value) {
|
||||
return dn.parse(value).toString();
|
||||
};
|
||||
default:
|
||||
// noop
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getTransformer(schema, type) {
|
||||
assert.ok(schema);
|
||||
assert.ok(type);
|
||||
|
||||
if (!schema.attributes[type] || !schema.attributes[type].syntax)
|
||||
return null;
|
||||
|
||||
return _getTransformer(schema.attributes[type].syntax);
|
||||
}
|
||||
|
||||
|
||||
function transformValue(schema, type, value) {
|
||||
assert.ok(schema);
|
||||
assert.ok(type);
|
||||
assert.ok(value);
|
||||
|
||||
if (!schema.attributes[type] || !schema.attributes[type].syntax)
|
||||
return value;
|
||||
|
||||
var transformer = _getTransformer(schema.attributes[type].syntax);
|
||||
|
||||
return transformer ? transformer(value) : null;
|
||||
}
|
||||
|
||||
|
||||
function transformObject(schema, attributes, keys) {
|
||||
assert.ok(schema);
|
||||
assert.ok(attributes);
|
||||
|
||||
if (!keys)
|
||||
keys = Object.keys(attributes);
|
||||
|
||||
var xformed = false;
|
||||
|
||||
keys.forEach(function(k) {
|
||||
k = k.toLowerCase();
|
||||
|
||||
var transform = _getTransformer(schema.attributes[k].syntax);
|
||||
if (transform) {
|
||||
xformed = true;
|
||||
|
||||
var vals = attributes[k];
|
||||
console.log('%s -> %j', k, vals);
|
||||
for (var i = 0; i < vals.length; i++)
|
||||
vals[i] = transform(vals[i]);
|
||||
}
|
||||
});
|
||||
|
||||
return xformed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
|
||||
transformObject: transformObject,
|
||||
transformValue: transformValue,
|
||||
getTransformer: getTransformer
|
||||
};
|
||||
|
||||
|
||||
|
||||
// var syntax = schema.attributes[k].syntax;
|
||||
// if (/\}$/.test(syntax))
|
||||
// syntax = syntax.replace(/\{.+\}$/, '');
|
||||
|
||||
// switch (syntax) {
|
||||
// case '1.3.6.1.4.1.1466.115.121.1.27': // int
|
||||
// case '1.3.6.1.4.1.1466.115.121.1.36': // numeric string
|
||||
// for (j = 0; j < attr.length; j++)
|
||||
// attr[j] = parseInt(attr[j], 10);
|
||||
// xformed = true;
|
||||
// break;
|
||||
// case '1.3.6.1.4.1.1466.115.121.1.7': // boolean
|
||||
// for (j = 0; j < attr.length; j++)
|
||||
// attr[j] = /^true$/i.test(attr[j]);
|
||||
// xformed = true;
|
||||
// break;
|
||||
// case '1.3.6.1.4.1.1466.115.121.1.5': // binary
|
||||
// for (j = 0; j < attr.length; j++)
|
||||
// attr[j] = new Buffer(attr[j]).toString('base64');
|
||||
// xformed = true;
|
||||
// break;
|
||||
// case '1.3.6.1.4.1.1466.115.121.1.12': // dn syntax
|
||||
// for (j = 0; j < attr.length; j++)
|
||||
// attr[j] = dn.parse(attr[j]).toString();
|
||||
// xformed = true;
|
||||
// break;
|
||||
// default:
|
||||
// // noop
|
||||
// }
|
217
lib/server.js
217
lib/server.js
|
@ -7,13 +7,11 @@ var tls = require('tls');
|
|||
var util = require('util');
|
||||
|
||||
var asn1 = require('asn1');
|
||||
var sprintf = require('sprintf').sprintf;
|
||||
|
||||
var dn = require('./dn');
|
||||
var dtrace = require('./dtrace');
|
||||
var errors = require('./errors');
|
||||
var Protocol = require('./protocol');
|
||||
var logStub = require('./log_stub');
|
||||
|
||||
var Parser = require('./messages').Parser;
|
||||
var AbandonResponse = require('./messages/abandon_response');
|
||||
|
@ -37,6 +35,8 @@ var Ber = asn1.Ber;
|
|||
var BerReader = asn1.BerReader;
|
||||
var DN = dn.DN;
|
||||
|
||||
var sprintf = util.format;
|
||||
|
||||
|
||||
///--- Helpers
|
||||
|
||||
|
@ -55,14 +55,14 @@ function mergeFunctionArgs(argv, start, end) {
|
|||
var arr = argv[i];
|
||||
for (var j = 0; j < arr.length; j++) {
|
||||
if (!(arr[j] instanceof Function)) {
|
||||
throw new TypeError('Invalid argument type: ' + typeof(arr[j]));
|
||||
throw new TypeError('Invalid argument type: ' + typeof (arr[j]));
|
||||
}
|
||||
handlers.push(arr[j]);
|
||||
}
|
||||
} else if (argv[i] instanceof Function) {
|
||||
handlers.push(argv[i]);
|
||||
} else {
|
||||
throw new TypeError('Invalid argument type: ' + typeof(argv[i]));
|
||||
throw new TypeError('Invalid argument type: ' + typeof (argv[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ function getResponse(req) {
|
|||
|
||||
var res = new Response({
|
||||
messageID: req.messageID,
|
||||
log4js: req.log4js,
|
||||
log: req.log,
|
||||
attributes: ((req instanceof SearchRequest) ? req.attributes : undefined)
|
||||
});
|
||||
res.connection = req.connection;
|
||||
|
@ -220,10 +220,12 @@ function fireDTraceProbe(req, res) {
|
|||
case Protocol.LDAP_REQ_UNBIND:
|
||||
op = 'unbind';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
res._dtraceOp = op;
|
||||
dtrace.fire('server-' + op + '-start', function() {
|
||||
dtrace.fire('server-' + op + '-start', function () {
|
||||
return probeArgs;
|
||||
});
|
||||
}
|
||||
|
@ -238,7 +240,7 @@ function fireDTraceProbe(req, res) {
|
|||
* LDAP operations however.
|
||||
*
|
||||
* The options object currently only takes a certificate/private key, and a
|
||||
* log4js handle.
|
||||
* bunyan logger handle.
|
||||
*
|
||||
* This object exposes the following events:
|
||||
* - 'error'
|
||||
|
@ -249,15 +251,15 @@ function fireDTraceProbe(req, res) {
|
|||
*/
|
||||
function Server(options) {
|
||||
if (options) {
|
||||
if (typeof(options) !== 'object')
|
||||
if (typeof (options) !== 'object')
|
||||
throw new TypeError('options (object) required');
|
||||
if (options.log4js && typeof(options.log4js) !== 'object')
|
||||
throw new TypeError('options.log4s must be an object');
|
||||
if (typeof (options.log) !== 'object')
|
||||
throw new TypeError('options.log must be an object');
|
||||
|
||||
if (options.certificate || options.key) {
|
||||
if (!(options.certificate && options.key) ||
|
||||
typeof(options.certificate) !== 'string' ||
|
||||
typeof(options.key) !== 'string') {
|
||||
typeof (options.certificate) !== 'string' ||
|
||||
typeof (options.key) !== 'string') {
|
||||
throw new TypeError('options.certificate and options.key (string) ' +
|
||||
'are both required for TLS');
|
||||
}
|
||||
|
@ -266,14 +268,11 @@ function Server(options) {
|
|||
options = {};
|
||||
}
|
||||
var self = this;
|
||||
if (!options.log4js)
|
||||
options.log4js = logStub;
|
||||
|
||||
EventEmitter.call(this, options);
|
||||
|
||||
this._chain = [];
|
||||
this.log4js = options.log4js;
|
||||
this.log = this.log4js.getLogger('Server');
|
||||
this.log = options.log;
|
||||
|
||||
var log = this.log;
|
||||
|
||||
|
@ -296,26 +295,26 @@ function Server(options) {
|
|||
config: options,
|
||||
_bindDN: new DN([rdn])
|
||||
};
|
||||
c.addListener('timeout', function() {
|
||||
c.addListener('timeout', function () {
|
||||
log.trace('%s timed out', c.ldap.id);
|
||||
c.destroy();
|
||||
});
|
||||
c.addListener('end', function() {
|
||||
c.addListener('end', function () {
|
||||
log.trace('%s shutdown', c.ldap.id);
|
||||
});
|
||||
c.addListener('error', function(err) {
|
||||
c.addListener('error', function (err) {
|
||||
log.warn('%s unexpected connection error', c.ldap.id, err);
|
||||
c.destroy();
|
||||
});
|
||||
c.addListener('close', function(had_err) {
|
||||
c.addListener('close', function (had_err) {
|
||||
log.trace('%s close; had_err=%j', c.ldap.id, had_err);
|
||||
c.end();
|
||||
});
|
||||
|
||||
c.ldap.__defineGetter__('bindDN', function() {
|
||||
c.ldap.__defineGetter__('bindDN', function () {
|
||||
return c.ldap._bindDN;
|
||||
});
|
||||
c.ldap.__defineSetter__('bindDN', function(val) {
|
||||
c.ldap.__defineSetter__('bindDN', function (val) {
|
||||
if (!(val instanceof DN))
|
||||
throw new TypeError('DN required');
|
||||
|
||||
|
@ -327,29 +326,28 @@ function Server(options) {
|
|||
|
||||
function newConnection(c) {
|
||||
setupConnection(c);
|
||||
if (log.isTraceEnabled())
|
||||
log.trace('new connection from %s', c.ldap.id);
|
||||
log.trace('new connection from %s', c.ldap.id);
|
||||
|
||||
dtrace.fire('server-connection', function() {
|
||||
dtrace.fire('server-connection', function () {
|
||||
return [c.remoteAddress];
|
||||
});
|
||||
|
||||
c.parser = new Parser({
|
||||
log4js: options.log4js
|
||||
log: options.log
|
||||
});
|
||||
c.parser.on('message', function(req) {
|
||||
c.parser.on('message', function (req) {
|
||||
req.connection = c;
|
||||
req.logId = c.ldap.id + '::' + req.messageID;
|
||||
req.startTime = new Date().getTime();
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
if (log.debug())
|
||||
log.debug('%s: message received: req=%j', c.ldap.id, req.json);
|
||||
|
||||
var res = getResponse(req);
|
||||
if (!res) {
|
||||
log.warn('Unimplemented server method: %s', req.type);
|
||||
c.destroy();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
res.connection = c;
|
||||
|
@ -359,7 +357,7 @@ function Server(options) {
|
|||
var chain = self._getHandlerChain(req, res);
|
||||
|
||||
var i = 0;
|
||||
return function(err) {
|
||||
return function (err) {
|
||||
function sendError(err) {
|
||||
res.status = err.code || errors.LDAP_OPERATIONS_ERROR;
|
||||
res.matchedDN = req.suffix ? req.suffix.toString() : '';
|
||||
|
@ -373,7 +371,7 @@ function Server(options) {
|
|||
|
||||
function next() {} // stub out next for the post chain
|
||||
|
||||
self._postChain.forEach(function(c) {
|
||||
self._postChain.forEach(function (c) {
|
||||
c.call(self, req, res, next);
|
||||
});
|
||||
}
|
||||
|
@ -403,7 +401,7 @@ function Server(options) {
|
|||
}();
|
||||
});
|
||||
|
||||
c.parser.on('error', function(err, message) {
|
||||
c.parser.on('error', function (err, message) {
|
||||
log.error('Exception happened parsing for %s: %s',
|
||||
c.ldap.id, err.stack);
|
||||
|
||||
|
@ -417,26 +415,26 @@ function Server(options) {
|
|||
|
||||
res.status = 0x02; // protocol error
|
||||
res.errorMessage = err.toString();
|
||||
c.end(res.toBer());
|
||||
return c.end(res.toBer());
|
||||
});
|
||||
|
||||
c.on('data', function(data) {
|
||||
if (log.isTraceEnabled())
|
||||
c.on('data', function (data) {
|
||||
if (log.trace())
|
||||
log.trace('data on %s: %s', c.ldap.id, util.inspect(data));
|
||||
|
||||
try {
|
||||
c.parser.write(data);
|
||||
c.parser.write(data);
|
||||
} catch (e) {
|
||||
log.warn('Unable to parse message [c.on(\'data\')]: %s', e.stack);
|
||||
c.end(new LDAPResult({
|
||||
status: 0x02,
|
||||
errorMessage: e.toString(),
|
||||
connection: c
|
||||
}).toBer());
|
||||
log.warn('Unable to parse message [c.on(\'data\')]: %s', e.stack);
|
||||
c.end(new LDAPResult({
|
||||
status: 0x02,
|
||||
errorMessage: e.toString(),
|
||||
connection: c
|
||||
}).toBer());
|
||||
}
|
||||
});
|
||||
|
||||
}; // end newConnection
|
||||
} // end newConnection
|
||||
|
||||
this.routes = {};
|
||||
if ((options.cert || options.certificate) && options.key) {
|
||||
|
@ -445,30 +443,30 @@ function Server(options) {
|
|||
} else {
|
||||
this.server = net.createServer(newConnection);
|
||||
}
|
||||
this.server.log4js = options.log4js;
|
||||
this.server.log = options.log;
|
||||
this.server.ldap = {
|
||||
config: options
|
||||
};
|
||||
this.server.on('close', function() {
|
||||
this.server.on('close', function () {
|
||||
self.emit('close');
|
||||
});
|
||||
this.server.on('error', function(err) {
|
||||
this.server.on('error', function (err) {
|
||||
self.emit('error', err);
|
||||
});
|
||||
|
||||
this.__defineGetter__('maxConnections', function() {
|
||||
this.__defineGetter__('maxConnections', function () {
|
||||
return self.server.maxConnections;
|
||||
});
|
||||
this.__defineSetter__('maxConnections', function(val) {
|
||||
this.__defineSetter__('maxConnections', function (val) {
|
||||
self.server.maxConnections = val;
|
||||
});
|
||||
this.__defineGetter__('connections', function() {
|
||||
this.__defineGetter__('connections', function () {
|
||||
return self.server.connections;
|
||||
});
|
||||
this.__defineGetter__('name', function() {
|
||||
this.__defineGetter__('name', function () {
|
||||
return 'LDAPServer';
|
||||
});
|
||||
this.__defineGetter__('url', function() {
|
||||
this.__defineGetter__('url', function () {
|
||||
var str;
|
||||
if (this.server instanceof tls.Server) {
|
||||
str = 'ldaps://';
|
||||
|
@ -495,7 +493,7 @@ module.exports = Server;
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input
|
||||
*/
|
||||
Server.prototype.add = function(name) {
|
||||
Server.prototype.add = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this._mount(Protocol.LDAP_REQ_ADD, name, args);
|
||||
};
|
||||
|
@ -511,7 +509,7 @@ Server.prototype.add = function(name) {
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input
|
||||
*/
|
||||
Server.prototype.bind = function(name) {
|
||||
Server.prototype.bind = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this._mount(Protocol.LDAP_REQ_BIND, name, args);
|
||||
};
|
||||
|
@ -527,7 +525,7 @@ Server.prototype.bind = function(name) {
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input
|
||||
*/
|
||||
Server.prototype.compare = function(name) {
|
||||
Server.prototype.compare = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this._mount(Protocol.LDAP_REQ_COMPARE, name, args);
|
||||
};
|
||||
|
@ -543,7 +541,7 @@ Server.prototype.compare = function(name) {
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input
|
||||
*/
|
||||
Server.prototype.del = function(name) {
|
||||
Server.prototype.del = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this._mount(Protocol.LDAP_REQ_DELETE, name, args);
|
||||
};
|
||||
|
@ -559,7 +557,7 @@ Server.prototype.del = function(name) {
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input.
|
||||
*/
|
||||
Server.prototype.exop = function(name) {
|
||||
Server.prototype.exop = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this._mount(Protocol.LDAP_REQ_EXTENSION, name, args, true);
|
||||
};
|
||||
|
@ -575,7 +573,7 @@ Server.prototype.exop = function(name) {
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input
|
||||
*/
|
||||
Server.prototype.modify = function(name) {
|
||||
Server.prototype.modify = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this._mount(Protocol.LDAP_REQ_MODIFY, name, args);
|
||||
};
|
||||
|
@ -591,7 +589,7 @@ Server.prototype.modify = function(name) {
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input
|
||||
*/
|
||||
Server.prototype.modifyDN = function(name) {
|
||||
Server.prototype.modifyDN = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this._mount(Protocol.LDAP_REQ_MODRDN, name, args);
|
||||
};
|
||||
|
@ -607,7 +605,7 @@ Server.prototype.modifyDN = function(name) {
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input
|
||||
*/
|
||||
Server.prototype.search = function(name) {
|
||||
Server.prototype.search = function (name) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
return this._mount(Protocol.LDAP_REQ_SEARCH, name, args);
|
||||
};
|
||||
|
@ -622,7 +620,7 @@ Server.prototype.search = function(name) {
|
|||
* @return {Server} this so you can chain calls.
|
||||
* @throws {TypeError} on bad input
|
||||
*/
|
||||
Server.prototype.unbind = function() {
|
||||
Server.prototype.unbind = function () {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
return this._mount(Protocol.LDAP_REQ_UNBIND, 'unbind', args, true);
|
||||
};
|
||||
|
@ -632,36 +630,36 @@ Server.prototype.use = function use() {
|
|||
var args = Array.prototype.slice.call(arguments);
|
||||
var chain = mergeFunctionArgs(args, 0, args.length);
|
||||
var self = this;
|
||||
chain.forEach(function(c) {
|
||||
chain.forEach(function (c) {
|
||||
self._chain.push(c);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Server.prototype.after = function() {
|
||||
Server.prototype.after = function () {
|
||||
if (!this._postChain)
|
||||
this._postChain = [];
|
||||
|
||||
var self = this;
|
||||
mergeFunctionArgs(arguments).forEach(function(h) {
|
||||
mergeFunctionArgs(arguments).forEach(function (h) {
|
||||
self._postChain.push(h);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// All these just reexpose the requisite net.Server APIs
|
||||
Server.prototype.listen = function(port, host, callback) {
|
||||
Server.prototype.listen = function (port, host, callback) {
|
||||
if (!port)
|
||||
throw new TypeError('port (number) required');
|
||||
|
||||
if (typeof(host) === 'function') {
|
||||
if (typeof (host) === 'function') {
|
||||
callback = host;
|
||||
host = '0.0.0.0';
|
||||
}
|
||||
var self = this;
|
||||
|
||||
function _callback() {
|
||||
if (typeof(port) === 'number') {
|
||||
if (typeof (port) === 'number') {
|
||||
self.host = host;
|
||||
self.port = port;
|
||||
} else {
|
||||
|
@ -669,30 +667,30 @@ Server.prototype.listen = function(port, host, callback) {
|
|||
self.port = self.server.fd;
|
||||
}
|
||||
|
||||
if (typeof(callback) === 'function')
|
||||
return callback();
|
||||
if (typeof (callback) === 'function')
|
||||
callback();
|
||||
}
|
||||
|
||||
if (typeof(port) === 'number') {
|
||||
if (typeof (port) === 'number') {
|
||||
return this.server.listen(port, host, _callback);
|
||||
} else {
|
||||
return this.server.listen(port, _callback);
|
||||
}
|
||||
};
|
||||
Server.prototype.listenFD = function(fd) {
|
||||
self.host = 'unix-domain-socket';
|
||||
self.port = fd;
|
||||
Server.prototype.listenFD = function (fd) {
|
||||
this.host = 'unix-domain-socket';
|
||||
this.port = fd;
|
||||
return this.server.listenFD(fd);
|
||||
};
|
||||
Server.prototype.close = function() {
|
||||
Server.prototype.close = function () {
|
||||
return this.server.close();
|
||||
};
|
||||
Server.prototype.address = function() {
|
||||
Server.prototype.address = function () {
|
||||
return this.server.address();
|
||||
};
|
||||
|
||||
|
||||
Server.prototype._getRoute = function(_dn, backend) {
|
||||
Server.prototype._getRoute = function (_dn, backend) {
|
||||
assert.ok(dn);
|
||||
|
||||
if (!backend)
|
||||
|
@ -715,7 +713,7 @@ Server.prototype._getRoute = function(_dn, backend) {
|
|||
};
|
||||
|
||||
|
||||
Server.prototype._getHandlerChain = function(req, res) {
|
||||
Server.prototype._getHandlerChain = function _getHandlerChain(req, res) {
|
||||
assert.ok(req);
|
||||
|
||||
fireDTraceProbe(req, res);
|
||||
|
@ -741,49 +739,42 @@ Server.prototype._getHandlerChain = function(req, res) {
|
|||
|
||||
// Special cases are abandons, exops and unbinds, handle those first.
|
||||
if (req.protocolOp === Protocol.LDAP_REQ_EXTENSION) {
|
||||
if (r !== req.requestName)
|
||||
continue;
|
||||
|
||||
return {
|
||||
backend: routes.backend,
|
||||
handlers: route[op] || [noExOpHandler]
|
||||
};
|
||||
} else if (req.protocolOp === Protocol.LDAP_REQ_UNBIND) {
|
||||
function getUnbindChain() {
|
||||
if (routes['unbind'] && routes['unbind'][op])
|
||||
return routes['unbind'][op];
|
||||
|
||||
self.log.debug('%s unbind request %j', req.logId, req.json);
|
||||
return [defaultNoOpHandler];
|
||||
if (r === req.requestName) {
|
||||
return {
|
||||
backend: routes.backend,
|
||||
handlers: route[op] || [noExOpHandler]
|
||||
};
|
||||
}
|
||||
|
||||
} else if (req.protocolOp === Protocol.LDAP_REQ_UNBIND) {
|
||||
return {
|
||||
backend: routes['unbind'] ? routes['unbind'].backend : self,
|
||||
handlers: getUnbindChain()
|
||||
handlers: function getUnbindChain() {
|
||||
if (routes['unbind'] && routes['unbind'][op])
|
||||
return routes['unbind'][op];
|
||||
|
||||
self.log.debug('%s unbind request %j', req.logId, req.json);
|
||||
return [defaultNoOpHandler];
|
||||
}
|
||||
};
|
||||
} else if (req.protocolOp === Protocol.LDAP_REQ_ABANDON) {
|
||||
return {
|
||||
backend: self,
|
||||
handlers: [defaultNoOpHandler]
|
||||
};
|
||||
} else if (route[op]) {
|
||||
// Otherwise, match via DN rules
|
||||
assert.ok(req.dn);
|
||||
assert.ok(route.dn);
|
||||
|
||||
if (route.dn.equals(req.dn) || route.dn.parentOf(req.dn)) {
|
||||
// We should be good to go.
|
||||
req.suffix = route.dn;
|
||||
return {
|
||||
backend: route.backend,
|
||||
handlers: route[op] || [defaultHandler]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!route[op])
|
||||
continue;
|
||||
|
||||
// Otherwise, match via DN rules
|
||||
assert.ok(req.dn);
|
||||
assert.ok(route.dn);
|
||||
|
||||
if (!route.dn.equals(req.dn) && !route.dn.parentOf(req.dn))
|
||||
continue;
|
||||
|
||||
// We should be good to go.
|
||||
req.suffix = route.dn;
|
||||
return {
|
||||
backend: route.backend,
|
||||
handlers: route[op] || [defaultHandler]
|
||||
};
|
||||
}
|
||||
|
||||
// We're here, so nothing matched.
|
||||
|
@ -795,12 +786,12 @@ Server.prototype._getHandlerChain = function(req, res) {
|
|||
};
|
||||
|
||||
|
||||
Server.prototype._mount = function(op, name, argv, notDN) {
|
||||
Server.prototype._mount = function (op, name, argv, notDN) {
|
||||
assert.ok(op);
|
||||
assert.ok(name !== undefined);
|
||||
assert.ok(argv);
|
||||
|
||||
if (typeof(name) !== 'string')
|
||||
if (typeof (name) !== 'string')
|
||||
throw new TypeError('name (string) required');
|
||||
if (!argv.length)
|
||||
throw new Error('at least one handler required');
|
||||
|
@ -808,14 +799,14 @@ Server.prototype._mount = function(op, name, argv, notDN) {
|
|||
var backend = this;
|
||||
var index = 0;
|
||||
|
||||
if (typeof(argv[0]) === 'object' && !Array.isArray(argv[0])) {
|
||||
if (typeof (argv[0]) === 'object' && !Array.isArray(argv[0])) {
|
||||
backend = argv[0];
|
||||
index = 1;
|
||||
}
|
||||
var route = this._getRoute(notDN ? name : dn.parse(name), backend);
|
||||
|
||||
var chain = this._chain.slice();
|
||||
argv.slice(index).forEach(function(a) {
|
||||
argv.slice(index).forEach(function (a) {
|
||||
chain.push(a);
|
||||
});
|
||||
route['0x' + op.toString(16)] = mergeFunctionArgs(chain);
|
||||
|
|
|
@ -10,7 +10,7 @@ var filter = require('./filters/index');
|
|||
|
||||
module.exports = {
|
||||
|
||||
parse: function(urlStr, parseDN) {
|
||||
parse: function (urlStr, parseDN) {
|
||||
var u = url.parse(urlStr);
|
||||
if (!u.protocol || !(u.protocol === 'ldap:' || u.protocol === 'ldaps:'))
|
||||
throw new TypeError(urlStr + ' is an invalid LDAP url (protocol)');
|
||||
|
@ -36,7 +36,7 @@ module.exports = {
|
|||
var tmp = u.search.substr(1).split('?');
|
||||
if (tmp && tmp.length) {
|
||||
if (tmp[0]) {
|
||||
tmp[0].split(',').forEach(function(a) {
|
||||
tmp[0].split(',').forEach(function (a) {
|
||||
u.attributes.push(querystring.unescape(a.trim()));
|
||||
});
|
||||
}
|
||||
|
|
19
package.json
19
package.json
|
@ -3,12 +3,13 @@
|
|||
"contributors": [
|
||||
"Mathieu Lecarme <mathieu@garambrogne.net>>",
|
||||
"Trent Mick <trentm@gmail.com>",
|
||||
"Yunong Xiao <yunong@joyent.com>"
|
||||
"Yunong Xiao <yunong@joyent.com>",
|
||||
"Craig Baker"
|
||||
],
|
||||
"name": "ldapjs",
|
||||
"homepage": "http://ldapjs.org",
|
||||
"description": "LDAP client and server APIs",
|
||||
"version": "0.4.3",
|
||||
"version": "0.5.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/mcavage/node-ldapjs.git"
|
||||
|
@ -19,20 +20,20 @@
|
|||
"lib": "./lib"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"asn1": "0.1.11",
|
||||
"buffertools": "1.0.6",
|
||||
"dtrace-provider": "0.0.3",
|
||||
"nopt": "1.0.10",
|
||||
"sprintf": "0.1.1"
|
||||
"buffertools": "1.0.7",
|
||||
"bunyan": "0.6.3",
|
||||
"dtrace-provider": "0.0.6",
|
||||
"nopt": "1.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tap": "0.1.4",
|
||||
"tap": "0.2",
|
||||
"node-uuid": "1.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "./node_modules/.bin/tap ./tst"
|
||||
"test": "./node_modules/.bin/tap ./test"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,20 +14,20 @@ var Attribute;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
Attribute = require('../lib/index').Attribute;
|
||||
t.ok(Attribute);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new Attribute());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var attr = new Attribute({
|
||||
type: 'cn',
|
||||
vals: ['foo', 'bar']
|
||||
|
@ -43,7 +43,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var attr = new Attribute({
|
||||
type: 'cn',
|
||||
vals: ['foo', 'bar']
|
||||
|
@ -61,7 +61,7 @@ test('toBer', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.startSequence();
|
||||
ber.writeString('cn');
|
|
@ -15,7 +15,7 @@ var Change;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
Attribute = require('../lib/index').Attribute;
|
||||
Change = require('../lib/index').Change;
|
||||
t.ok(Attribute);
|
||||
|
@ -24,13 +24,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new Change());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var change = new Change({
|
||||
operation: 0x00,
|
||||
modification: new Attribute({
|
||||
|
@ -50,16 +50,15 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('GH-31 (multiple attributes per Change)', function(t) {
|
||||
test('GH-31 (multiple attributes per Change)', function (t) {
|
||||
try {
|
||||
var change = new Change({
|
||||
t.notOk(new Change({
|
||||
operation: 'replace',
|
||||
modification: {
|
||||
cn: 'foo',
|
||||
sn: 'bar'
|
||||
}
|
||||
});
|
||||
t.fail('should have thrown');
|
||||
}), 'should have thrown');
|
||||
} catch (e) {
|
||||
t.ok(e);
|
||||
t.end();
|
||||
|
@ -67,7 +66,7 @@ test('GH-31 (multiple attributes per Change)', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var change = new Change({
|
||||
operation: 'Add',
|
||||
modification: new Attribute({
|
||||
|
@ -91,7 +90,7 @@ test('toBer', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.startSequence();
|
||||
ber.writeEnumeration(0x00);
|
|
@ -21,7 +21,7 @@ var server;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('setup', function(t) {
|
||||
test('setup', function (t) {
|
||||
ldap = require('../lib/index');
|
||||
t.ok(ldap);
|
||||
t.ok(ldap.createClient);
|
||||
|
@ -35,7 +35,7 @@ test('setup', function(t) {
|
|||
server = ldap.createServer();
|
||||
t.ok(server);
|
||||
|
||||
server.bind(BIND_DN, function(req, res, next) {
|
||||
server.bind(BIND_DN, function (req, res, next) {
|
||||
if (req.credentials !== BIND_PW)
|
||||
return next(new ldap.InvalidCredentialsError('Invalid password'));
|
||||
|
||||
|
@ -43,39 +43,43 @@ test('setup', function(t) {
|
|||
return next();
|
||||
});
|
||||
|
||||
server.add(SUFFIX, function(req, res, next) {
|
||||
server.add(SUFFIX, function (req, res, next) {
|
||||
res.end();
|
||||
return next();
|
||||
});
|
||||
|
||||
server.compare(SUFFIX, function(req, res, next) {
|
||||
server.compare(SUFFIX, function (req, res, next) {
|
||||
res.end(req.value === 'test');
|
||||
return next();
|
||||
});
|
||||
|
||||
server.del(SUFFIX, function(req, res, next) {
|
||||
server.del(SUFFIX, function (req, res, next) {
|
||||
res.end();
|
||||
return next();
|
||||
});
|
||||
|
||||
// LDAP whoami
|
||||
server.exop('1.3.6.1.4.1.4203.1.11.3', function(req, res, next) {
|
||||
server.exop('1.3.6.1.4.1.4203.1.11.3', function (req, res, next) {
|
||||
res.value = 'u:xxyyz@EXAMPLE.NET';
|
||||
res.end();
|
||||
return next();
|
||||
});
|
||||
|
||||
server.modify(SUFFIX, function(req, res, next) {
|
||||
server.modify(SUFFIX, function (req, res, next) {
|
||||
res.end();
|
||||
return next();
|
||||
});
|
||||
|
||||
server.modifyDN(SUFFIX, function(req, res, next) {
|
||||
server.modifyDN(SUFFIX, function (req, res, next) {
|
||||
res.end();
|
||||
return next();
|
||||
});
|
||||
|
||||
server.search(SUFFIX, function(req, res, next) {
|
||||
server.search('dc=timeout', function (req, res, next) {
|
||||
// Haha client!
|
||||
});
|
||||
|
||||
server.search(SUFFIX, function (req, res, next) {
|
||||
|
||||
if (req.dn.equals('cn=ref,' + SUFFIX)) {
|
||||
res.send(res.createSearchReference('ldap://localhost'));
|
||||
|
@ -105,7 +109,7 @@ test('setup', function(t) {
|
|||
return next();
|
||||
});
|
||||
|
||||
server.search('dc=empty', function(req, res, next) {
|
||||
server.search('dc=empty', function (req, res, next) {
|
||||
res.send({
|
||||
dn: 'dc=empty',
|
||||
attributes: {
|
||||
|
@ -117,27 +121,25 @@ test('setup', function(t) {
|
|||
return next();
|
||||
});
|
||||
|
||||
server.unbind(function(req, res, next) {
|
||||
server.unbind(function (req, res, next) {
|
||||
res.end();
|
||||
return next();
|
||||
});
|
||||
|
||||
server.listen(SOCKET, function() {
|
||||
server.listen(SOCKET, function () {
|
||||
client = ldap.createClient({
|
||||
socketPath: SOCKET,
|
||||
reconnect: false // turn this off for unit testing
|
||||
});
|
||||
t.ok(client);
|
||||
// client.log4js.setLevel('Trace');
|
||||
// server.log4js.setLevel('Trace');
|
||||
t.end();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
test('simple bind success', function(t) {
|
||||
client.bind(BIND_DN, BIND_PW, function(err, res) {
|
||||
test('simple bind success', function (t) {
|
||||
client.bind(BIND_DN, BIND_PW, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -146,8 +148,8 @@ test('simple bind success', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('simple bind failure', function(t) {
|
||||
client.bind(BIND_DN, uuid(), function(err, res) {
|
||||
test('simple bind failure', function (t) {
|
||||
client.bind(BIND_DN, uuid(), function (err, res) {
|
||||
t.ok(err);
|
||||
t.notOk(res);
|
||||
|
||||
|
@ -162,14 +164,14 @@ test('simple bind failure', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('add success', function(t) {
|
||||
test('add success', function (t) {
|
||||
var attrs = [
|
||||
new Attribute({
|
||||
type: 'cn',
|
||||
vals: ['test']
|
||||
})
|
||||
];
|
||||
client.add('cn=add, ' + SUFFIX, attrs, function(err, res) {
|
||||
client.add('cn=add, ' + SUFFIX, attrs, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -178,12 +180,12 @@ test('add success', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('add success with object', function(t) {
|
||||
test('add success with object', function (t) {
|
||||
var entry = {
|
||||
cn: ['unit', 'add'],
|
||||
sn: 'test'
|
||||
};
|
||||
client.add('cn=add, ' + SUFFIX, entry, function(err, res) {
|
||||
client.add('cn=add, ' + SUFFIX, entry, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -192,8 +194,8 @@ test('add success with object', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('compare success', function(t) {
|
||||
client.compare('cn=compare, ' + SUFFIX, 'cn', 'test', function(err,
|
||||
test('compare success', function (t) {
|
||||
client.compare('cn=compare, ' + SUFFIX, 'cn', 'test', function (err,
|
||||
matched,
|
||||
res) {
|
||||
t.ifError(err);
|
||||
|
@ -204,8 +206,8 @@ test('compare success', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('compare false', function(t) {
|
||||
client.compare('cn=compare, ' + SUFFIX, 'cn', 'foo', function(err,
|
||||
test('compare false', function (t) {
|
||||
client.compare('cn=compare, ' + SUFFIX, 'cn', 'foo', function (err,
|
||||
matched,
|
||||
res) {
|
||||
t.ifError(err);
|
||||
|
@ -216,8 +218,8 @@ test('compare false', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('compare bad suffix', function(t) {
|
||||
client.compare('cn=' + uuid(), 'cn', 'foo', function(err,
|
||||
test('compare bad suffix', function (t) {
|
||||
client.compare('cn=' + uuid(), 'cn', 'foo', function (err,
|
||||
matched,
|
||||
res) {
|
||||
t.ok(err);
|
||||
|
@ -229,8 +231,8 @@ test('compare bad suffix', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('delete success', function(t) {
|
||||
client.del('cn=delete, ' + SUFFIX, function(err, res) {
|
||||
test('delete success', function (t) {
|
||||
client.del('cn=delete, ' + SUFFIX, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.end();
|
||||
|
@ -238,8 +240,8 @@ test('delete success', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('exop success', function(t) {
|
||||
client.exop('1.3.6.1.4.1.4203.1.11.3', function(err, value, res) {
|
||||
test('exop success', function (t) {
|
||||
client.exop('1.3.6.1.4.1.4203.1.11.3', function (err, value, res) {
|
||||
t.ifError(err);
|
||||
t.ok(value);
|
||||
t.ok(res);
|
||||
|
@ -249,8 +251,8 @@ test('exop success', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('exop invalid', function(t) {
|
||||
client.exop('1.2.3.4', function(err, res) {
|
||||
test('exop invalid', function (t) {
|
||||
client.exop('1.2.3.4', function (err, res) {
|
||||
t.ok(err);
|
||||
t.ok(err instanceof ldap.ProtocolError);
|
||||
t.notOk(res);
|
||||
|
@ -259,15 +261,15 @@ test('exop invalid', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('bogus exop (GH-17)', function(t) {
|
||||
client.exop('cn=root', function(err, value) {
|
||||
test('bogus exop (GH-17)', function (t) {
|
||||
client.exop('cn=root', function (err, value) {
|
||||
t.ok(err);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('modify success', function(t) {
|
||||
test('modify success', function (t) {
|
||||
var change = new Change({
|
||||
type: 'Replace',
|
||||
modification: new Attribute({
|
||||
|
@ -275,7 +277,7 @@ test('modify success', function(t) {
|
|||
vals: ['test']
|
||||
})
|
||||
});
|
||||
client.modify('cn=modify, ' + SUFFIX, change, function(err, res) {
|
||||
client.modify('cn=modify, ' + SUFFIX, change, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -284,14 +286,14 @@ test('modify success', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('modify change plain object success', function(t) {
|
||||
test('modify change plain object success', function (t) {
|
||||
var change = new Change({
|
||||
type: 'Replace',
|
||||
modification: {
|
||||
cn: 'test'
|
||||
}
|
||||
});
|
||||
client.modify('cn=modify, ' + SUFFIX, change, function(err, res) {
|
||||
client.modify('cn=modify, ' + SUFFIX, change, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -300,7 +302,7 @@ test('modify change plain object success', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('modify array success', function(t) {
|
||||
test('modify array success', function (t) {
|
||||
var changes = [
|
||||
new Change({
|
||||
operation: 'Replace',
|
||||
|
@ -316,7 +318,7 @@ test('modify array success', function(t) {
|
|||
})
|
||||
})
|
||||
];
|
||||
client.modify('cn=modify, ' + SUFFIX, changes, function(err, res) {
|
||||
client.modify('cn=modify, ' + SUFFIX, changes, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -325,7 +327,7 @@ test('modify array success', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('modify change plain object success (GH-31)', function(t) {
|
||||
test('modify change plain object success (GH-31)', function (t) {
|
||||
var change = {
|
||||
type: 'replace',
|
||||
modification: {
|
||||
|
@ -333,7 +335,7 @@ test('modify change plain object success (GH-31)', function(t) {
|
|||
sn: 'bar'
|
||||
}
|
||||
};
|
||||
client.modify('cn=modify, ' + SUFFIX, change, function(err, res) {
|
||||
client.modify('cn=modify, ' + SUFFIX, change, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -342,8 +344,8 @@ test('modify change plain object success (GH-31)', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('modify DN new RDN only', function(t) {
|
||||
client.modifyDN('cn=old, ' + SUFFIX, 'cn=new', function(err, res) {
|
||||
test('modify DN new RDN only', function (t) {
|
||||
client.modifyDN('cn=old, ' + SUFFIX, 'cn=new', function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -352,8 +354,8 @@ test('modify DN new RDN only', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('modify DN new superior', function(t) {
|
||||
client.modifyDN('cn=old, ' + SUFFIX, 'cn=new, dc=foo', function(err, res) {
|
||||
test('modify DN new superior', function (t) {
|
||||
client.modifyDN('cn=old, ' + SUFFIX, 'cn=new, dc=foo', function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -362,12 +364,12 @@ test('modify DN new superior', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('search basic', function(t) {
|
||||
client.search('cn=test, ' + SUFFIX, '(objectclass=*)', function(err, res) {
|
||||
test('search basic', function (t) {
|
||||
client.search('cn=test, ' + SUFFIX, '(objectclass=*)', function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
var gotEntry = 0;
|
||||
res.on('searchEntry', function(entry) {
|
||||
res.on('searchEntry', function (entry) {
|
||||
t.ok(entry);
|
||||
t.ok(entry instanceof ldap.SearchEntry);
|
||||
t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX);
|
||||
|
@ -378,10 +380,10 @@ test('search basic', function(t) {
|
|||
t.ok(entry.object);
|
||||
gotEntry++;
|
||||
});
|
||||
res.on('error', function(err) {
|
||||
res.on('error', function (err) {
|
||||
t.fail(err);
|
||||
});
|
||||
res.on('end', function(res) {
|
||||
res.on('end', function (res) {
|
||||
t.ok(res);
|
||||
t.ok(res instanceof ldap.SearchResponse);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -392,26 +394,26 @@ test('search basic', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('search referral', function(t) {
|
||||
client.search('cn=ref, ' + SUFFIX, '(objectclass=*)', function(err, res) {
|
||||
test('search referral', function (t) {
|
||||
client.search('cn=ref, ' + SUFFIX, '(objectclass=*)', function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
var gotEntry = 0;
|
||||
var gotReferral = false;
|
||||
res.on('searchEntry', function(entry) {
|
||||
res.on('searchEntry', function (entry) {
|
||||
gotEntry++;
|
||||
});
|
||||
res.on('searchReference', function(referral) {
|
||||
res.on('searchReference', function (referral) {
|
||||
gotReferral = true;
|
||||
t.ok(referral);
|
||||
t.ok(referral instanceof ldap.SearchReference);
|
||||
t.ok(referral.uris);
|
||||
t.ok(referral.uris.length);
|
||||
});
|
||||
res.on('error', function(err) {
|
||||
res.on('error', function (err) {
|
||||
t.fail(err);
|
||||
});
|
||||
res.on('end', function(res) {
|
||||
res.on('end', function (res) {
|
||||
t.ok(res);
|
||||
t.ok(res instanceof ldap.SearchResponse);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -423,12 +425,12 @@ test('search referral', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('search empty attribute', function(t) {
|
||||
client.search('dc=empty', '(objectclass=*)', function(err, res) {
|
||||
test('search empty attribute', function (t) {
|
||||
client.search('dc=empty', '(objectclass=*)', function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
var gotEntry = 0;
|
||||
res.on('searchEntry', function(entry) {
|
||||
res.on('searchEntry', function (entry) {
|
||||
var obj = entry.toObject();
|
||||
t.equal('dc=empty', obj.dn);
|
||||
t.ok(obj.member);
|
||||
|
@ -437,10 +439,10 @@ test('search empty attribute', function(t) {
|
|||
t.ok(obj['member;range=0-1'].length);
|
||||
gotEntry++;
|
||||
});
|
||||
res.on('error', function(err) {
|
||||
res.on('error', function (err) {
|
||||
t.fail(err);
|
||||
});
|
||||
res.on('end', function(res) {
|
||||
res.on('end', function (res) {
|
||||
t.ok(res);
|
||||
t.ok(res instanceof ldap.SearchResponse);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -451,14 +453,14 @@ test('search empty attribute', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('GH-21 binary attributes', function(t) {
|
||||
client.search('cn=bin, ' + SUFFIX, '(objectclass=*)', function(err, res) {
|
||||
test('GH-21 binary attributes', function (t) {
|
||||
client.search('cn=bin, ' + SUFFIX, '(objectclass=*)', function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
var gotEntry = 0;
|
||||
var expect = new Buffer('\u00bd + \u00bc = \u00be', 'utf8');
|
||||
var expect2 = new Buffer([0xB5, 0xE7, 0xCA, 0xD3, 0xBB, 0xFA]);
|
||||
res.on('searchEntry', function(entry) {
|
||||
res.on('searchEntry', function (entry) {
|
||||
t.ok(entry);
|
||||
t.ok(entry instanceof ldap.SearchEntry);
|
||||
t.equal(entry.dn.toString(), 'cn=bin, ' + SUFFIX);
|
||||
|
@ -478,10 +480,10 @@ test('GH-21 binary attributes', function(t) {
|
|||
t.ok(entry.object);
|
||||
gotEntry++;
|
||||
});
|
||||
res.on('error', function(err) {
|
||||
res.on('error', function (err) {
|
||||
t.fail(err);
|
||||
});
|
||||
res.on('end', function(res) {
|
||||
res.on('end', function (res) {
|
||||
t.ok(res);
|
||||
t.ok(res instanceof ldap.SearchResponse);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -492,16 +494,16 @@ test('GH-21 binary attributes', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('GH-23 case insensitive attribute filtering', function(t) {
|
||||
test('GH-23 case insensitive attribute filtering', function (t) {
|
||||
var opts = {
|
||||
filter: '(objectclass=*)',
|
||||
attributes: ['Cn']
|
||||
};
|
||||
client.search('cn=test, ' + SUFFIX, opts, function(err, res) {
|
||||
client.search('cn=test, ' + SUFFIX, opts, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
var gotEntry = 0;
|
||||
res.on('searchEntry', function(entry) {
|
||||
res.on('searchEntry', function (entry) {
|
||||
t.ok(entry);
|
||||
t.ok(entry instanceof ldap.SearchEntry);
|
||||
t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX);
|
||||
|
@ -511,10 +513,10 @@ test('GH-23 case insensitive attribute filtering', function(t) {
|
|||
t.ok(entry.object);
|
||||
gotEntry++;
|
||||
});
|
||||
res.on('error', function(err) {
|
||||
res.on('error', function (err) {
|
||||
t.fail(err);
|
||||
});
|
||||
res.on('end', function(res) {
|
||||
res.on('end', function (res) {
|
||||
t.ok(res);
|
||||
t.ok(res instanceof ldap.SearchResponse);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -525,16 +527,16 @@ test('GH-23 case insensitive attribute filtering', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('GH-24 attribute selection of *', function(t) {
|
||||
test('GH-24 attribute selection of *', function (t) {
|
||||
var opts = {
|
||||
filter: '(objectclass=*)',
|
||||
attributes: ['*']
|
||||
};
|
||||
client.search('cn=test, ' + SUFFIX, opts, function(err, res) {
|
||||
client.search('cn=test, ' + SUFFIX, opts, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
var gotEntry = 0;
|
||||
res.on('searchEntry', function(entry) {
|
||||
res.on('searchEntry', function (entry) {
|
||||
t.ok(entry);
|
||||
t.ok(entry instanceof ldap.SearchEntry);
|
||||
t.equal(entry.dn.toString(), 'cn=test, ' + SUFFIX);
|
||||
|
@ -545,10 +547,10 @@ test('GH-24 attribute selection of *', function(t) {
|
|||
t.ok(entry.object);
|
||||
gotEntry++;
|
||||
});
|
||||
res.on('error', function(err) {
|
||||
res.on('error', function (err) {
|
||||
t.fail(err);
|
||||
});
|
||||
res.on('end', function(res) {
|
||||
res.on('end', function (res) {
|
||||
t.ok(res);
|
||||
t.ok(res instanceof ldap.SearchResponse);
|
||||
t.equal(res.status, 0);
|
||||
|
@ -559,25 +561,34 @@ test('GH-24 attribute selection of *', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('abandon (GH-27)', function(t) {
|
||||
client.abandon(401876543, function(err) {
|
||||
test('abandon (GH-27)', function (t) {
|
||||
client.abandon(401876543, function (err) {
|
||||
t.ifError(err);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('unbind (GH-30)', function(t) {
|
||||
client.unbind(function(err) {
|
||||
test('unbind (GH-30)', function (t) {
|
||||
client.unbind(function (err) {
|
||||
t.ifError(err);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('shutdown', function(t) {
|
||||
client.unbind(function(err) {
|
||||
server.on('close', function() {
|
||||
test('search timeout (GH-51)', function (t) {
|
||||
client.timeout = 250;
|
||||
client.search('dc=timeout', 'objectclass=*', function (err, res) {
|
||||
t.ok(err);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('shutdown', function (t) {
|
||||
client.unbind(function (err) {
|
||||
server.on('close', function () {
|
||||
t.end();
|
||||
});
|
||||
server.close();
|
|
@ -15,7 +15,7 @@ var getControl;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
Control = require('../../lib/index').Control;
|
||||
t.ok(Control);
|
||||
getControl = require('../../lib/index').getControl;
|
||||
|
@ -24,13 +24,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new Control());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var c = new Control({
|
||||
type: '2.16.840.1.113730.3.4.2',
|
||||
criticality: true
|
||||
|
@ -42,7 +42,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.startSequence();
|
||||
ber.writeString('2.16.840.1.113730.3.4.2');
|
||||
|
@ -60,7 +60,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse no value', function(t) {
|
||||
test('parse no value', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.startSequence();
|
||||
ber.writeString('2.16.840.1.113730.3.4.2');
|
|
@ -13,7 +13,7 @@ var EntryChangeNotificationControl;
|
|||
///--- Tests
|
||||
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
EntryChangeNotificationControl =
|
||||
require('../../lib').EntryChangeNotificationControl;
|
||||
t.ok(EntryChangeNotificationControl);
|
||||
|
@ -23,13 +23,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new EntryChangeNotificationControl());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var c = new EntryChangeNotificationControl({
|
||||
type: '2.16.840.1.113730.3.4.7',
|
||||
criticality: true,
|
||||
|
@ -62,7 +62,7 @@ test('new with args', function(t) {
|
|||
t.end();
|
||||
});
|
||||
|
||||
test('tober', function(t) {
|
||||
test('tober', function (t) {
|
||||
var psc = new EntryChangeNotificationControl({
|
||||
type: '2.16.840.1.113730.3.4.7',
|
||||
criticality: true,
|
|
@ -13,7 +13,7 @@ var PersistentSearchControl;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
PersistentSearchControl = require('../../lib').PersistentSearchControl;
|
||||
t.ok(PersistentSearchControl);
|
||||
getControl = require('../../lib').getControl;
|
||||
|
@ -22,13 +22,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new PersistentSearchControl());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var c = new PersistentSearchControl({
|
||||
type: '2.16.840.1.113730.3.4.3',
|
||||
criticality: true,
|
||||
|
@ -61,23 +61,13 @@ test('new with args', function(t) {
|
|||
t.end();
|
||||
});
|
||||
|
||||
test('getControl with args', function(t) {
|
||||
test('getControl with args', function (t) {
|
||||
var buf = new Buffer([
|
||||
0x30, 0x26, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30,
|
||||
0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e,
|
||||
0x34, 0x2e, 0x33, 0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01,
|
||||
0xff, 0x01, 0x01, 0xff]);
|
||||
|
||||
var options = {
|
||||
type: '2.16.840.1.113730.3.4.3',
|
||||
criticality: false,
|
||||
value: {
|
||||
changeTypes: 15,
|
||||
changesOnly: true,
|
||||
returnECs: true
|
||||
}
|
||||
};
|
||||
|
||||
var ber = new BerReader(buf);
|
||||
var psc = getControl(ber);
|
||||
t.ok(psc);
|
||||
|
@ -89,7 +79,7 @@ test('getControl with args', function(t) {
|
|||
t.end();
|
||||
});
|
||||
|
||||
test('tober', function(t) {
|
||||
test('tober', function (t) {
|
||||
var psc = new PersistentSearchControl({
|
||||
type: '2.16.840.1.113730.3.4.3',
|
||||
criticality: true,
|
|
@ -12,74 +12,74 @@ var dn;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
dn = require('../lib/index').dn;
|
||||
t.ok(dn);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse basic', function(t) {
|
||||
test('parse basic', function (t) {
|
||||
var DN_STR = 'cn=mark, ou=people, o=joyent';
|
||||
var name = dn.parse(DN_STR);
|
||||
t.ok(name);
|
||||
t.ok(name.rdns);
|
||||
t.ok(Array.isArray(name.rdns));
|
||||
t.equal(3, name.rdns.length);
|
||||
name.rdns.forEach(function(rdn) {
|
||||
t.equal('object', typeof(rdn));
|
||||
name.rdns.forEach(function (rdn) {
|
||||
t.equal('object', typeof (rdn));
|
||||
});
|
||||
t.equal(name.toString(), DN_STR);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse escaped', function(t) {
|
||||
test('parse escaped', function (t) {
|
||||
var DN_STR = 'cn=m\\,ark, ou=people, o=joyent';
|
||||
var name = dn.parse(DN_STR);
|
||||
t.ok(name);
|
||||
t.ok(name.rdns);
|
||||
t.ok(Array.isArray(name.rdns));
|
||||
t.equal(3, name.rdns.length);
|
||||
name.rdns.forEach(function(rdn) {
|
||||
t.equal('object', typeof(rdn));
|
||||
name.rdns.forEach(function (rdn) {
|
||||
t.equal('object', typeof (rdn));
|
||||
});
|
||||
t.equal(name.toString(), DN_STR);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse compound', function(t) {
|
||||
test('parse compound', function (t) {
|
||||
var DN_STR = 'cn=mark+sn=cavage, ou=people, o=joyent';
|
||||
var name = dn.parse(DN_STR);
|
||||
t.ok(name);
|
||||
t.ok(name.rdns);
|
||||
t.ok(Array.isArray(name.rdns));
|
||||
t.equal(3, name.rdns.length);
|
||||
name.rdns.forEach(function(rdn) {
|
||||
t.equal('object', typeof(rdn));
|
||||
name.rdns.forEach(function (rdn) {
|
||||
t.equal('object', typeof (rdn));
|
||||
});
|
||||
t.equal(name.toString(), DN_STR);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('parse quoted', function(t) {
|
||||
test('parse quoted', function (t) {
|
||||
var DN_STR = 'cn="mark+sn=cavage", ou=people, o=joyent';
|
||||
var name = dn.parse(DN_STR);
|
||||
t.ok(name);
|
||||
t.ok(name.rdns);
|
||||
t.ok(Array.isArray(name.rdns));
|
||||
t.equal(3, name.rdns.length);
|
||||
name.rdns.forEach(function(rdn) {
|
||||
t.equal('object', typeof(rdn));
|
||||
name.rdns.forEach(function (rdn) {
|
||||
t.equal('object', typeof (rdn));
|
||||
});
|
||||
t.equal(name.toString(), DN_STR);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('equals', function(t) {
|
||||
test('equals', function (t) {
|
||||
var dn1 = dn.parse('cn=foo, dc=bar');
|
||||
t.ok(dn1.equals('cn=foo, dc=bar'));
|
||||
t.ok(!dn1.equals('cn=foo1, dc=bar'));
|
||||
|
@ -89,7 +89,7 @@ test('equals', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('child of', function(t) {
|
||||
test('child of', function (t) {
|
||||
var dn1 = dn.parse('cn=foo, dc=bar');
|
||||
t.ok(dn1.childOf('dc=bar'));
|
||||
t.ok(!dn1.childOf('dc=moo'));
|
||||
|
@ -101,7 +101,7 @@ test('child of', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parent of', function(t) {
|
||||
test('parent of', function (t) {
|
||||
var dn1 = dn.parse('cn=foo, dc=bar');
|
||||
t.ok(dn1.parentOf('cn=moo, cn=foo, dc=bar'));
|
||||
t.ok(!dn1.parentOf('cn=moo, cn=bar, dc=foo'));
|
||||
|
@ -112,7 +112,7 @@ test('parent of', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('empty DNs GH-16', function(t) {
|
||||
test('empty DNs GH-16', function (t) {
|
||||
var _dn = dn.parse('');
|
||||
var _dn2 = dn.parse('cn=foo');
|
||||
t.notOk(_dn.equals('cn=foo'));
|
||||
|
@ -125,7 +125,7 @@ test('empty DNs GH-16', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('case insensitive attribute names GH-20', function(t) {
|
||||
test('case insensitive attribute names GH-20', function (t) {
|
||||
var dn1 = dn.parse('CN=foo, dc=bar');
|
||||
t.ok(dn1.equals('cn=foo, dc=bar'));
|
||||
t.ok(dn1.equals(dn.parse('cn=foo, DC=bar')));
|
|
@ -14,7 +14,7 @@ var AndFilter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
EqualityFilter = filters.EqualityFilter;
|
||||
|
@ -25,13 +25,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
t.ok(new AndFilter());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new AndFilter();
|
||||
f.addFilter(new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -47,7 +47,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new AndFilter();
|
||||
f.addFilter(new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -63,7 +63,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new AndFilter();
|
||||
f.addFilter(new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -77,5 +77,3 @@ test('match false', function(t) {
|
|||
t.ok(!f.matches({ foo: 'bar', zig: 'zonk' }));
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ var BerWriter = asn1.BerWriter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
ApproximateFilter = filters.ApproximateFilter;
|
||||
|
@ -24,7 +24,7 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
var f = new ApproximateFilter();
|
||||
t.ok(f);
|
||||
t.ok(!f.attribute);
|
||||
|
@ -33,7 +33,7 @@ test('Construct no args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new ApproximateFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -46,7 +46,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new ApproximateFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -57,7 +57,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match multiple', function(t) {
|
||||
test('match multiple', function (t) {
|
||||
var f = new ApproximateFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -68,7 +68,7 @@ test('match multiple', function(t) {
|
|||
t.end();
|
||||
});
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new ApproximateFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -79,7 +79,7 @@ test('match false', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse ok', function(t) {
|
||||
test('parse ok', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeString('bar');
|
||||
|
@ -92,7 +92,7 @@ test('parse ok', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse bad', function(t) {
|
||||
test('parse bad', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeInt(20);
|
|
@ -15,7 +15,7 @@ var BerWriter = asn1.BerWriter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
EqualityFilter = filters.EqualityFilter;
|
||||
|
@ -24,7 +24,7 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
var f = new EqualityFilter();
|
||||
t.ok(f);
|
||||
t.ok(!f.attribute);
|
||||
|
@ -33,7 +33,7 @@ test('Construct no args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -46,7 +46,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -57,7 +57,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match multiple', function(t) {
|
||||
test('match multiple', function (t) {
|
||||
var f = new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -68,7 +68,7 @@ test('match multiple', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -79,7 +79,7 @@ test('match false', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse ok', function(t) {
|
||||
test('parse ok', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeString('bar');
|
||||
|
@ -92,7 +92,7 @@ test('parse ok', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse bad', function(t) {
|
||||
test('parse bad', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeInt(20);
|
|
@ -15,7 +15,7 @@ var filters;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
ExtensibleFilter = filters.ExtensibleFilter;
|
||||
|
@ -24,14 +24,14 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
var f = new ExtensibleFilter();
|
||||
t.ok(f);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new ExtensibleFilter({
|
||||
matchType: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -44,7 +44,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse RFC example 1', function(t) {
|
||||
test('parse RFC example 1', function (t) {
|
||||
var f = filters.parseString('(cn:caseExactMatch:=Fred Flintstone)');
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'cn');
|
||||
|
@ -55,7 +55,7 @@ test('parse RFC example 1', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse RFC example 2', function(t) {
|
||||
test('parse RFC example 2', function (t) {
|
||||
var f = filters.parseString('(cn:=Betty Rubble)');
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'cn');
|
||||
|
@ -66,7 +66,7 @@ test('parse RFC example 2', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse RFC example 3', function(t) {
|
||||
test('parse RFC example 3', function (t) {
|
||||
var f = filters.parseString('(sn:dn:2.4.6.8.10:=Barney Rubble)');
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'sn');
|
||||
|
@ -77,7 +77,7 @@ test('parse RFC example 3', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse RFC example 3', function(t) {
|
||||
test('parse RFC example 3', function (t) {
|
||||
var f = filters.parseString('(o:dn:=Ace Industry)');
|
||||
t.ok(f);
|
||||
t.equal(f.matchType, 'o');
|
||||
|
@ -88,7 +88,7 @@ test('parse RFC example 3', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse RFC example 4', function(t) {
|
||||
test('parse RFC example 4', function (t) {
|
||||
var f = filters.parseString('(:1.2.3:=Wilma Flintstone)');
|
||||
t.ok(f);
|
||||
t.notOk(f.matchType);
|
||||
|
@ -99,7 +99,7 @@ test('parse RFC example 4', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse RFC example 5', function(t) {
|
||||
test('parse RFC example 5', function (t) {
|
||||
var f = filters.parseString('(:DN:2.4.6.8.10:=Dino)');
|
||||
t.ok(f);
|
||||
t.notOk(f.matchType);
|
|
@ -15,7 +15,7 @@ var BerWriter = asn1.BerWriter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
GreaterThanEqualsFilter = filters.GreaterThanEqualsFilter;
|
||||
|
@ -24,7 +24,7 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
var f = new GreaterThanEqualsFilter();
|
||||
t.ok(f);
|
||||
t.ok(!f.attribute);
|
||||
|
@ -33,7 +33,7 @@ test('Construct no args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new GreaterThanEqualsFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -46,7 +46,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new GreaterThanEqualsFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -57,7 +57,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match multiple', function(t) {
|
||||
test('match multiple', function (t) {
|
||||
var f = new GreaterThanEqualsFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -67,7 +67,7 @@ test('match multiple', function(t) {
|
|||
t.end();
|
||||
});
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new GreaterThanEqualsFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -78,7 +78,7 @@ test('match false', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse ok', function(t) {
|
||||
test('parse ok', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeString('bar');
|
||||
|
@ -91,7 +91,7 @@ test('parse ok', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse bad', function(t) {
|
||||
test('parse bad', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeInt(20);
|
|
@ -15,7 +15,7 @@ var BerWriter = asn1.BerWriter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
LessThanEqualsFilter = filters.LessThanEqualsFilter;
|
||||
|
@ -24,7 +24,7 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
var f = new LessThanEqualsFilter();
|
||||
t.ok(f);
|
||||
t.ok(!f.attribute);
|
||||
|
@ -33,7 +33,7 @@ test('Construct no args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new LessThanEqualsFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -46,7 +46,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new LessThanEqualsFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -57,7 +57,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match multiple', function(t) {
|
||||
test('match multiple', function (t) {
|
||||
var f = new LessThanEqualsFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -68,7 +68,7 @@ test('match multiple', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new LessThanEqualsFilter({
|
||||
attribute: 'foo',
|
||||
value: 'bar'
|
||||
|
@ -79,7 +79,7 @@ test('match false', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse ok', function(t) {
|
||||
test('parse ok', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeString('bar');
|
||||
|
@ -92,7 +92,7 @@ test('parse ok', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse bad', function(t) {
|
||||
test('parse bad', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeInt(20);
|
|
@ -14,7 +14,7 @@ var NotFilter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
EqualityFilter = filters.EqualityFilter;
|
||||
|
@ -25,18 +25,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
try {
|
||||
new NotFilter();
|
||||
t.fail('should have thrown');
|
||||
} catch (e) {
|
||||
t.ok(e instanceof TypeError);
|
||||
}
|
||||
test('Construct no args', function (t) {
|
||||
t.ok(new NotFilter());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new NotFilter({
|
||||
filter: new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -49,7 +44,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new NotFilter({
|
||||
filter: new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -62,7 +57,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new NotFilter({
|
||||
filter: new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -73,5 +68,3 @@ test('match false', function(t) {
|
|||
t.ok(!f.matches({ foo: 'bar' }));
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ var OrFilter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
EqualityFilter = filters.EqualityFilter;
|
||||
|
@ -25,13 +25,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
t.ok(new OrFilter());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new OrFilter();
|
||||
f.addFilter(new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -47,7 +47,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new OrFilter();
|
||||
f.addFilter(new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -63,7 +63,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new OrFilter();
|
||||
f.addFilter(new EqualityFilter({
|
||||
attribute: 'foo',
|
||||
|
@ -77,5 +77,3 @@ test('match false', function(t) {
|
|||
t.ok(!f.matches({ foo: 'baz', zig: 'zonk' }));
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var test = require('tap').test;
|
||||
|
||||
var parse = require('../../lib/index').parseFilter;
|
||||
|
||||
|
||||
|
||||
test('GH-48 XML Strings in filter', function (t) {
|
||||
var str = '(&(CentralUIEnrollments=\\<mydoc\\>*)(objectClass=User))';
|
||||
var f = parse(str);
|
||||
t.ok(f);
|
||||
t.ok(f.filters);
|
||||
t.equal(f.filters.length, 2);
|
||||
f.filters.forEach(function (filter) {
|
||||
t.ok(filter.attribute);
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('GH-50 = in filter', function (t) {
|
||||
var str = '(uniquemember=uuid=930896af-bf8c-48d4-885c-6573a94b1853, ' +
|
||||
'ou=users, o=smartdc)';
|
||||
var f = parse(str);
|
||||
t.ok(f);
|
||||
t.equal(f.attribute, 'uniquemember');
|
||||
t.equal(f.value,
|
||||
'uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc');
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('( in filter', function (t) {
|
||||
var str = '(foo=bar\\()';
|
||||
var f = parse(str);
|
||||
t.ok(f);
|
||||
t.equal(f.attribute, 'foo');
|
||||
t.equal(f.value, 'bar(');
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test(') in filter', function (t) {
|
||||
var str = '(foo=bar\\))';
|
||||
var f = parse(str);
|
||||
t.ok(f);
|
||||
t.equal(f.attribute, 'foo');
|
||||
t.equal(f.value, 'bar)');
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('\\ in filter', function (t) {
|
||||
var str = '(foo=bar\\\\)';
|
||||
var f = parse(str);
|
||||
t.ok(f);
|
||||
t.equal(f.attribute, 'foo');
|
||||
t.equal(f.value, 'bar\\');
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('* in equality filter', function (t) {
|
||||
var str = '(foo=bar\\*)';
|
||||
var f = parse(str);
|
||||
t.ok(f);
|
||||
t.equal(f.attribute, 'foo');
|
||||
t.equal(f.value, 'bar*');
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('* substr filter (prefix)', function (t) {
|
||||
var str = '(foo=bar*)';
|
||||
var f = parse(str);
|
||||
t.ok(f);
|
||||
t.equal(f.attribute, 'foo');
|
||||
t.equal(f.initial, 'bar');
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('GH-53 NotFilter', function (t) {
|
||||
var str = '(&(objectClass=person)(!(objectClass=shadowAccount)))';
|
||||
var f = parse(str);
|
||||
t.ok(f);
|
||||
t.equal(f.type, 'and');
|
||||
t.equal(f.filters.length, 2);
|
||||
t.equal(f.filters[0].type, 'equal');
|
||||
t.equal(f.filters[1].type, 'not');
|
||||
t.equal(f.filters[1].filter.type, 'equal');
|
||||
t.equal(f.filters[1].filter.attribute, 'objectClass');
|
||||
t.equal(f.filters[1].filter.value, 'shadowAccount');
|
||||
t.end();
|
||||
});
|
|
@ -15,7 +15,7 @@ var BerWriter = asn1.BerWriter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
PresenceFilter = filters.PresenceFilter;
|
||||
|
@ -24,7 +24,7 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
var f = new PresenceFilter();
|
||||
t.ok(f);
|
||||
t.ok(!f.attribute);
|
||||
|
@ -32,7 +32,7 @@ test('Construct no args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new PresenceFilter({
|
||||
attribute: 'foo'
|
||||
});
|
||||
|
@ -43,7 +43,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new PresenceFilter({
|
||||
attribute: 'foo'
|
||||
});
|
||||
|
@ -53,7 +53,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new PresenceFilter({
|
||||
attribute: 'foo'
|
||||
});
|
||||
|
@ -63,7 +63,7 @@ test('match false', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse ok', function(t) {
|
||||
test('parse ok', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo', 0x87);
|
||||
|
|
@ -15,7 +15,7 @@ var BerWriter = asn1.BerWriter;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
var filters = require('../../lib/index').filters;
|
||||
t.ok(filters);
|
||||
SubstringFilter = filters.SubstringFilter;
|
||||
|
@ -24,7 +24,7 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct no args', function(t) {
|
||||
test('Construct no args', function (t) {
|
||||
var f = new SubstringFilter();
|
||||
t.ok(f);
|
||||
t.ok(!f.attribute);
|
||||
|
@ -33,7 +33,7 @@ test('Construct no args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('Construct args', function(t) {
|
||||
test('Construct args', function (t) {
|
||||
var f = new SubstringFilter({
|
||||
attribute: 'foo',
|
||||
initial: 'bar',
|
||||
|
@ -52,7 +52,7 @@ test('Construct args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match true', function(t) {
|
||||
test('match true', function (t) {
|
||||
var f = new SubstringFilter({
|
||||
attribute: 'foo',
|
||||
initial: 'bar',
|
||||
|
@ -65,7 +65,7 @@ test('match true', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match false', function(t) {
|
||||
test('match false', function (t) {
|
||||
var f = new SubstringFilter({
|
||||
attribute: 'foo',
|
||||
initial: 'bar',
|
||||
|
@ -78,7 +78,7 @@ test('match false', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('match any', function(t) {
|
||||
test('match any', function (t) {
|
||||
var f = new SubstringFilter({
|
||||
attribute: 'foo',
|
||||
initial: 'bar'
|
||||
|
@ -88,7 +88,7 @@ test('match any', function(t) {
|
|||
t.end();
|
||||
});
|
||||
|
||||
test('parse ok', function(t) {
|
||||
test('parse ok', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.startSequence();
|
||||
|
@ -104,7 +104,7 @@ test('parse ok', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse bad', function(t) {
|
||||
test('parse bad', function (t) {
|
||||
var writer = new BerWriter();
|
||||
writer.writeString('foo');
|
||||
writer.writeInt(20);
|
|
@ -9,47 +9,74 @@ var ldap = require('../lib/index');
|
|||
///--- Globals
|
||||
|
||||
var SOCKET = '/tmp/.' + uuid();
|
||||
var SUFFIX = 'dc=' + uuid();
|
||||
|
||||
var client;
|
||||
var server;
|
||||
|
||||
|
||||
|
||||
///--- Helper
|
||||
|
||||
function search(t, options, callback) {
|
||||
client.search(SUFFIX, options, function (err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
var found = false;
|
||||
res.on('searchEntry', function (entry) {
|
||||
t.ok(entry);
|
||||
found = true;
|
||||
});
|
||||
res.on('end', function () {
|
||||
t.ok(found);
|
||||
if (callback)
|
||||
return callback();
|
||||
|
||||
return t.end();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
///--- Tests
|
||||
|
||||
test('setup', function(t) {
|
||||
test('setup', function (t) {
|
||||
server = ldap.createServer();
|
||||
t.ok(server);
|
||||
server.listen(SOCKET, function() {
|
||||
server.listen(SOCKET, function () {
|
||||
client = ldap.createClient({
|
||||
socketPath: SOCKET
|
||||
});
|
||||
t.ok(client);
|
||||
// client.log4js.setLevel('Debug');
|
||||
t.end();
|
||||
});
|
||||
|
||||
server.bind('cn=root', function (req, res, next) {
|
||||
res.end();
|
||||
return next();
|
||||
});
|
||||
server.search(SUFFIX, function (req, res, next) {
|
||||
var entry = {
|
||||
dn: 'cn=foo, ' + SUFFIX,
|
||||
attributes: {
|
||||
objectclass: ['person', 'top'],
|
||||
cn: 'Pogo Stick',
|
||||
sn: 'Stick',
|
||||
givenname: 'ogo',
|
||||
mail: uuid() + '@pogostick.org'
|
||||
}
|
||||
};
|
||||
|
||||
if (req.filter.matches(entry.attributes))
|
||||
res.send(entry);
|
||||
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('Evolution search filter (GH-3)', function(t) {
|
||||
var suffix = 'dc=' + uuid();
|
||||
var entry = {
|
||||
dn: 'cn=foo, ' + suffix,
|
||||
attributes: {
|
||||
objectclass: ['person', 'top'],
|
||||
cn: 'Pogo Stick',
|
||||
sn: 'Stick',
|
||||
givenname: 'ogo',
|
||||
mail: uuid() + '@pogostick.org'
|
||||
}
|
||||
};
|
||||
|
||||
server.search(suffix, function(req, res, next) {
|
||||
console.log(req.filter.toString());
|
||||
if (req.filter.matches(entry.attributes))
|
||||
res.send(entry);
|
||||
res.end();
|
||||
});
|
||||
|
||||
test('Evolution search filter (GH-3)', function (t) {
|
||||
// This is what Evolution sends, when searching for a contact 'ogo'. Wow.
|
||||
var filter =
|
||||
'(|(cn=ogo*)(givenname=ogo*)(sn=ogo*)(mail=ogo*)(member=ogo*)' +
|
||||
|
@ -69,25 +96,43 @@ test('Evolution search filter (GH-3)', function(t) {
|
|||
'(anniversary=ogo*)(birthdate=ogo*)(mailer=ogo*)(fileas=ogo*)' +
|
||||
'(category=ogo*)(calcaluri=ogo*)(calfburl=ogo*)(icscalendar=ogo*))';
|
||||
|
||||
client.search(suffix, filter, function(err, res) {
|
||||
t.ifError(err);
|
||||
t.ok(res);
|
||||
var found = false;
|
||||
res.on('searchEntry', function(entry) {
|
||||
t.ok(entry);
|
||||
found = true;
|
||||
});
|
||||
res.on('end', function() {
|
||||
t.ok(found);
|
||||
t.end();
|
||||
return search(t, filter);
|
||||
});
|
||||
|
||||
|
||||
test('GH-49 Client errors on bad attributes', function (t) {
|
||||
var searchOpts = {
|
||||
filter: 'cn=*ogo*',
|
||||
scope: 'one',
|
||||
attributes: 'dn'
|
||||
};
|
||||
return search(t, searchOpts);
|
||||
});
|
||||
|
||||
|
||||
test('GH-55 Client emits connect multiple times', function (t) {
|
||||
var c = ldap.createClient({
|
||||
socketPath: SOCKET
|
||||
});
|
||||
|
||||
var count = 0;
|
||||
c.on('connect', function (socket) {
|
||||
t.ok(socket);
|
||||
count++;
|
||||
c.bind('cn=root', 'secret', function (err, res) {
|
||||
t.ifError(err);
|
||||
c.unbind(function () {
|
||||
t.equal(count, 1);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('shutdown', function(t) {
|
||||
client.unbind(function() {
|
||||
server.on('close', function() {
|
||||
test('shutdown', function (t) {
|
||||
client.unbind(function () {
|
||||
server.on('close', function () {
|
||||
t.end();
|
||||
});
|
||||
server.close();
|
|
@ -15,7 +15,7 @@ var dn;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
AddRequest = require('../../lib/index').AddRequest;
|
||||
Attribute = require('../../lib/index').Attribute;
|
||||
dn = require('../../lib/index').dn;
|
||||
|
@ -26,13 +26,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new AddRequest());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var req = new AddRequest({
|
||||
entry: dn.parse('cn=foo, o=test'),
|
||||
attributes: [new Attribute({type: 'cn', vals: ['foo']}),
|
||||
|
@ -49,7 +49,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeString('cn=foo,o=test');
|
||||
|
||||
|
@ -83,7 +83,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var req = new AddRequest({
|
||||
messageID: 123,
|
||||
entry: dn.parse('cn=foo, o=test'),
|
||||
|
@ -115,7 +115,7 @@ test('toBer', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toObject', function(t) {
|
||||
test('toObject', function (t) {
|
||||
var req = new AddRequest({
|
||||
entry: dn.parse('cn=foo, o=test'),
|
||||
attributes: [new Attribute({type: 'cn', vals: ['foo', 'bar']}),
|
|
@ -14,20 +14,20 @@ var AddResponse;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
AddResponse = require('../../lib/index').AddResponse;
|
||||
t.ok(AddResponse);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new AddResponse());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var res = new AddResponse({
|
||||
messageID: 123,
|
||||
status: 0
|
||||
|
@ -39,7 +39,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeEnumeration(0);
|
||||
ber.writeString('cn=root');
|
||||
|
@ -54,7 +54,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var res = new AddResponse({
|
||||
messageID: 123,
|
||||
status: 3,
|
|
@ -14,7 +14,7 @@ var dn;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
BindRequest = require('../../lib/index').BindRequest;
|
||||
dn = require('../../lib/index').dn;
|
||||
t.ok(BindRequest);
|
||||
|
@ -23,13 +23,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new BindRequest());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var req = new BindRequest({
|
||||
version: 3,
|
||||
name: dn.parse('cn=root'),
|
||||
|
@ -43,7 +43,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeInt(3);
|
||||
ber.writeString('cn=root');
|
||||
|
@ -60,7 +60,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var req = new BindRequest({
|
||||
messageID: 123,
|
||||
version: 3,
|
|
@ -14,20 +14,20 @@ var BindResponse;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
BindResponse = require('../../lib/index').BindResponse;
|
||||
t.ok(BindResponse);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new BindResponse());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var res = new BindResponse({
|
||||
messageID: 123,
|
||||
status: 0
|
||||
|
@ -39,7 +39,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeEnumeration(0);
|
||||
ber.writeString('cn=root');
|
||||
|
@ -54,7 +54,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var res = new BindResponse({
|
||||
messageID: 123,
|
||||
status: 3,
|
|
@ -14,7 +14,7 @@ var dn;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
CompareRequest = require('../../lib/index').CompareRequest;
|
||||
dn = require('../../lib/index').dn;
|
||||
t.ok(CompareRequest);
|
||||
|
@ -23,13 +23,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new CompareRequest());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var req = new CompareRequest({
|
||||
entry: dn.parse('cn=foo, o=test'),
|
||||
attribute: 'sn',
|
||||
|
@ -43,7 +43,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeString('cn=foo,o=test');
|
||||
|
||||
|
@ -62,7 +62,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var req = new CompareRequest({
|
||||
messageID: 123,
|
||||
entry: dn.parse('cn=foo, o=test'),
|
|
@ -14,20 +14,20 @@ var CompareResponse;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
CompareResponse = require('../../lib/index').CompareResponse;
|
||||
t.ok(CompareResponse);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new CompareResponse());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var res = new CompareResponse({
|
||||
messageID: 123,
|
||||
status: 0
|
||||
|
@ -39,7 +39,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeEnumeration(0);
|
||||
ber.writeString('cn=root');
|
||||
|
@ -54,7 +54,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var res = new CompareResponse({
|
||||
messageID: 123,
|
||||
status: 3,
|
|
@ -1,8 +1,9 @@
|
|||
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
|
||||
|
||||
var test = require('tap').test;
|
||||
|
||||
var asn1 = require('asn1');
|
||||
var Logger = require('bunyan');
|
||||
var test = require('tap').test;
|
||||
|
||||
|
||||
///--- Globals
|
||||
|
@ -15,7 +16,7 @@ var dn;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
DeleteRequest = require('../../lib/index').DeleteRequest;
|
||||
dn = require('../../lib/index').dn;
|
||||
t.ok(DeleteRequest);
|
||||
|
@ -23,13 +24,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new DeleteRequest());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var req = new DeleteRequest({
|
||||
entry: dn.parse('cn=test')
|
||||
});
|
||||
|
@ -39,11 +40,13 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeString('cn=test', 0x4a);
|
||||
|
||||
var req = new DeleteRequest();
|
||||
var req = new DeleteRequest({
|
||||
log: new Logger({name: 'del_request.test.js'})
|
||||
});
|
||||
var reader = new BerReader(ber.buffer);
|
||||
reader.readSequence(0x4a);
|
||||
t.ok(req.parse(reader, reader.length));
|
||||
|
@ -52,7 +55,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var req = new DeleteRequest({
|
||||
messageID: 123,
|
||||
entry: dn.parse('cn=test')
|
|
@ -14,20 +14,20 @@ var DeleteResponse;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
DeleteResponse = require('../../lib/index').DeleteResponse;
|
||||
t.ok(DeleteResponse);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new DeleteResponse());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var res = new DeleteResponse({
|
||||
messageID: 123,
|
||||
status: 0
|
||||
|
@ -39,7 +39,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeEnumeration(0);
|
||||
ber.writeString('cn=root');
|
||||
|
@ -54,7 +54,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var res = new DeleteResponse({
|
||||
messageID: 123,
|
||||
status: 3,
|
|
@ -14,7 +14,7 @@ var dn;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
ExtendedRequest = require('../../lib/index').ExtendedRequest;
|
||||
dn = require('../../lib/index').dn;
|
||||
t.ok(ExtendedRequest);
|
||||
|
@ -23,13 +23,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new ExtendedRequest());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var req = new ExtendedRequest({
|
||||
requestName: '1.2.3.4',
|
||||
requestValue: 'test'
|
||||
|
@ -41,7 +41,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeString('1.2.3.4', 0x80);
|
||||
ber.writeString('test', 0x81);
|
||||
|
@ -55,7 +55,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var req = new ExtendedRequest({
|
||||
messageID: 123,
|
||||
requestName: '1.2.3.4',
|
|
@ -14,20 +14,20 @@ var ExtendedResponse;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
ExtendedResponse = require('../../lib/index').ExtendedResponse;
|
||||
t.ok(ExtendedResponse);
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new ExtendedResponse());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var res = new ExtendedResponse({
|
||||
messageID: 123,
|
||||
status: 0,
|
||||
|
@ -43,7 +43,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeEnumeration(0);
|
||||
ber.writeString('cn=root');
|
||||
|
@ -62,7 +62,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var res = new ExtendedResponse({
|
||||
messageID: 123,
|
||||
status: 3,
|
|
@ -14,7 +14,7 @@ var dn;
|
|||
|
||||
///--- Tests
|
||||
|
||||
test('load library', function(t) {
|
||||
test('load library', function (t) {
|
||||
ModifyDNRequest = require('../../lib/index').ModifyDNRequest;
|
||||
dn = require('../../lib/index').dn;
|
||||
t.ok(ModifyDNRequest);
|
||||
|
@ -23,13 +23,13 @@ test('load library', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('new no args', function(t) {
|
||||
test('new no args', function (t) {
|
||||
t.ok(new ModifyDNRequest());
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('new with args', function(t) {
|
||||
test('new with args', function (t) {
|
||||
var req = new ModifyDNRequest({
|
||||
entry: dn.parse('cn=foo, o=test'),
|
||||
newRdn: dn.parse('cn=foo2'),
|
||||
|
@ -43,7 +43,7 @@ test('new with args', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('parse', function(t) {
|
||||
test('parse', function (t) {
|
||||
var ber = new BerWriter();
|
||||
ber.writeString('cn=foo,o=test');
|
||||
ber.writeString('cn=foo2');
|
||||
|
@ -59,7 +59,7 @@ test('parse', function(t) {
|
|||
});
|
||||
|
||||
|
||||
test('toBer', function(t) {
|
||||
test('toBer', function (t) {
|
||||
var req = new ModifyDNRequest({
|
||||
messageID: 123,
|
||||
entry: dn.parse('cn=foo, o=test'),
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue