Initial setup for 0.5 (use eng.git layout)
This commit is contained in:
parent
4df59978ce
commit
afeb354eac
|
@ -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
|
node_modules
|
||||||
*.log
|
*.log
|
||||||
*.ldif
|
*.ldif
|
||||||
*.tar*
|
*.tar*
|
||||||
docs/pkg
|
|
||||||
|
|
|
@ -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
|
120
Makefile
120
Makefile
|
@ -1,85 +1,49 @@
|
||||||
|
#
|
||||||
|
# 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"
|
# Tools
|
||||||
endif
|
#
|
||||||
|
NPM := npm
|
||||||
|
TAP := ./node_modules/.bin/tap
|
||||||
|
|
||||||
|
#
|
||||||
|
# Files
|
||||||
|
#
|
||||||
|
DOC_FILES = client.md \
|
||||||
|
dn.md \
|
||||||
|
errors.md \
|
||||||
|
examples.md \
|
||||||
|
filters.md
|
||||||
|
|
||||||
DOCPKGDIR = ./docs/pkg
|
JS_FILES := $(shell find lib test -name '*.js')
|
||||||
HAVE_GJSLINT := $(shell which gjslint >/dev/null && echo yes || echo no)
|
JSL_CONF_NODE = tools/jsl.node.conf
|
||||||
LINT = ./node_modules/.javascriptlint/build/install/jsl --conf ./tools/jsl.conf
|
JSL_FILES_NODE = $(JS_FILES)
|
||||||
NAME=ldapjs
|
JSSTYLE_FILES = $(JS_FILES)
|
||||||
RESTDOWN_VERSION=1.2.13
|
JSSTYLE_FLAGS = -f tools/jsstyle.conf
|
||||||
SRC := $(shell pwd)
|
|
||||||
TAR = tar
|
|
||||||
UNAME := $(shell uname)
|
|
||||||
ifeq ($(UNAME), SunOS)
|
|
||||||
TAR = gtar
|
|
||||||
endif
|
|
||||||
NPM := npm_config_tar=$(TAR) npm
|
|
||||||
|
|
||||||
RESTDOWN = ./node_modules/.restdown/bin/restdown \
|
# Repo-specific targets
|
||||||
-b ./docs/branding \
|
#
|
||||||
-m ${DOCPKGDIR} \
|
.PHONY: all
|
||||||
-D mediaroot=media
|
all:
|
||||||
|
|
||||||
.PHONY: dep lint test doc clean all install
|
|
||||||
|
|
||||||
all:: test doc
|
|
||||||
|
|
||||||
node_modules/.ldapjs.npm.installed:
|
|
||||||
$(NPM) install
|
$(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
|
|
||||||
|
|
||||||
if [[ ! -d node_modules/.javascriptlint ]]; then \
|
.PHONY: test
|
||||||
git clone https://github.com/davepacheco/javascriptlint node_modules/.javascriptlint; \
|
test: $(TAP)
|
||||||
else \
|
$(TAP) test/*.test.js
|
||||||
(cd node_modules/.javascriptlint && git fetch origin); \
|
|
||||||
fi
|
|
||||||
|
|
||||||
@(cd ./node_modules/.restdown && git checkout $(RESTDOWN_VERSION))
|
include ./Makefile.deps
|
||||||
@(cd ./node_modules/.javascriptlint && $(MAKE) install)
|
include ./Makefile.targ
|
||||||
@touch ./node_modules/.ldapjs.npm.installed
|
|
||||||
|
|
||||||
dep: ./node_modules/.ldapjs.npm.installed
|
|
||||||
install: dep
|
|
||||||
|
|
||||||
gjslint:
|
|
||||||
gjslint --nojsdoc -r lib -r tst
|
|
||||||
|
|
||||||
ifeq ($(HAVE_GJSLINT), yes)
|
|
||||||
lint: install gjslint
|
|
||||||
${LINT} --recurse lib/*.js
|
|
||||||
else
|
|
||||||
lint: install
|
|
||||||
@echo "* * *"
|
|
||||||
@echo "* Warning: Cannot lint with gjslint. Install it from:"
|
|
||||||
@echo "* http://code.google.com/closure/utilities/docs/linter_howto.html"
|
|
||||||
@echo "* * *"
|
|
||||||
${LINT} --recurse lib/*.js
|
|
||||||
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
|
|
||||||
$(NPM) test
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@rm -fr ${DOCPKGDIR} *.log *.tar.gz
|
|
||||||
|
|
|
@ -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 @@
|
||||||
|
Subproject commit 5693fd3ce6f31f66f85bfde275ab64e609ea04d0
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit ab8f1fc8d90db8484bbed8a526ff40add5aa1c15
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 14131f6b33bf45a04b4c66e388d0ce1f3e5b55ef
|
|
@ -29,6 +29,7 @@ function Attribute(options) {
|
||||||
var _vals = [];
|
var _vals = [];
|
||||||
|
|
||||||
self._vals.forEach(function (v) {
|
self._vals.forEach(function (v) {
|
||||||
|
/* JSSTYLED */
|
||||||
if (/;binary$/.test(self.type)) {
|
if (/;binary$/.test(self.type)) {
|
||||||
_vals.push(v.toString('base64'));
|
_vals.push(v.toString('base64'));
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,6 +73,7 @@ Attribute.prototype.addValue = function(val) {
|
||||||
this._vals.push(val);
|
this._vals.push(val);
|
||||||
} else {
|
} else {
|
||||||
var encoding = 'utf8';
|
var encoding = 'utf8';
|
||||||
|
/* JSSTYLED */
|
||||||
if (/;binary$/.test(this.type))
|
if (/;binary$/.test(this.type))
|
||||||
encoding = 'base64';
|
encoding = 'base64';
|
||||||
this._vals.push(new Buffer(val + '', encoding));
|
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))
|
if (!(a instanceof Attribute) || !(b instanceof Attribute))
|
||||||
throw new TypeError('can only compare Attributes');
|
throw new TypeError('can only compare Attributes');
|
||||||
|
|
||||||
|
@ -95,6 +98,7 @@ Attribute.compare = function(a, b) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
/* END JSSTYLED */
|
||||||
|
|
||||||
|
|
||||||
Attribute.prototype.parse = function (ber) {
|
Attribute.prototype.parse = function (ber) {
|
||||||
|
@ -142,6 +146,7 @@ Attribute.toBer = function(attr, ber) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* BEGIN JSSTYLED */
|
||||||
Attribute.isAttribute = function (attr) {
|
Attribute.isAttribute = function (attr) {
|
||||||
if (!attr) return false;
|
if (!attr) return false;
|
||||||
if (typeof (attr) !== 'object') return false;
|
if (typeof (attr) !== 'object') return false;
|
||||||
|
@ -155,6 +160,7 @@ Attribute.isAttribute = function(attr) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
/* END JSSTLYED */
|
||||||
|
|
||||||
|
|
||||||
Attribute.prototype.toString = function () {
|
Attribute.prototype.toString = function () {
|
||||||
|
|
|
@ -20,6 +20,8 @@ function Change(options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
this._modification = false;
|
||||||
|
|
||||||
this.__defineGetter__('operation', function () {
|
this.__defineGetter__('operation', function () {
|
||||||
switch (self._operation) {
|
switch (self._operation) {
|
||||||
case 0x00: return 'add';
|
case 0x00: return 'add';
|
||||||
|
@ -50,6 +52,7 @@ function Change(options) {
|
||||||
this.__defineGetter__('modification', function () {
|
this.__defineGetter__('modification', function () {
|
||||||
return self._modification;
|
return self._modification;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.__defineSetter__('modification', function (attr) {
|
this.__defineSetter__('modification', function (attr) {
|
||||||
if (Attribute.isAttribute(attr)) {
|
if (Attribute.isAttribute(attr)) {
|
||||||
self._modification = attr;
|
self._modification = attr;
|
||||||
|
@ -88,8 +91,10 @@ Change.compare = function(a, b) {
|
||||||
if (!(a instanceof Change) || !(b instanceof Change))
|
if (!(a instanceof Change) || !(b instanceof Change))
|
||||||
throw new TypeError('can only compare Changes');
|
throw new TypeError('can only compare Changes');
|
||||||
|
|
||||||
if (a.operation < b.operation) return -1;
|
if (a.operation < b.operation)
|
||||||
if (a.operation > b.operation) return 1;
|
return -1;
|
||||||
|
if (a.operation > b.operation)
|
||||||
|
return 1;
|
||||||
|
|
||||||
return Attribute.compare(a.modification, b.modification);
|
return Attribute.compare(a.modification, b.modification);
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,8 +53,11 @@ var MAX_MSGID = Math.pow(2, 31) - 1;
|
||||||
function xor() {
|
function xor() {
|
||||||
var b = false;
|
var b = false;
|
||||||
for (var i = 0; i < arguments.length; i++) {
|
for (var i = 0; i < arguments.length; i++) {
|
||||||
if (arguments[i] && !b) b = true;
|
if (arguments[i] && !b) {
|
||||||
else if (arguments[i] && b) return false;
|
b = true;
|
||||||
|
} else if (arguments[i] && b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
@ -178,8 +181,11 @@ Client.prototype.connect = function(callback) {
|
||||||
function reconnect() {
|
function reconnect() {
|
||||||
self.connection = null;
|
self.connection = null;
|
||||||
|
|
||||||
if (self.reconnect)
|
if (self.reconnect) {
|
||||||
setTimeout(function() { self.connect(function() {}); }, self.reconnect);
|
setTimeout(function () {
|
||||||
|
self.connect(function () {});
|
||||||
|
}, self.reconnect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.connection.on('close', function (had_err) {
|
self.connection.on('close', function (had_err) {
|
||||||
|
@ -641,14 +647,14 @@ Client.prototype.search = function(base, options, controls, callback) {
|
||||||
throw new TypeError('callback (function) required');
|
throw new TypeError('callback (function) required');
|
||||||
|
|
||||||
if (options.attributes) {
|
if (options.attributes) {
|
||||||
if (Array.isArray(options.attributes)) {
|
if (!Array.isArray(options.attributes)) {
|
||||||
// noop
|
if (typeof (options.attributes) === 'string') {
|
||||||
} else if (typeof(options.attributes) === 'string') {
|
|
||||||
options.attributes = [options.attributes];
|
options.attributes = [options.attributes];
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError('options.attributes must be an Array of Strings');
|
throw new TypeError('options.attributes must be an Array of Strings');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
var req = new SearchRequest({
|
var req = new SearchRequest({
|
||||||
baseObject: typeof (base) === 'string' ? dn.parse(base) : base,
|
baseObject: typeof (base) === 'string' ? dn.parse(base) : base,
|
||||||
scope: options.scope || 'base',
|
scope: options.scope || 'base',
|
||||||
|
|
|
@ -56,6 +56,7 @@ module.exports = {
|
||||||
critical: critical,
|
critical: critical,
|
||||||
value: value ? value.toString('utf8') : null
|
value: value ? value.toString('utf8') : null
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return control;
|
return control;
|
||||||
|
|
|
@ -10,7 +10,8 @@ var SERVER_PROVIDER;
|
||||||
var DTRACE_ID = 0;
|
var DTRACE_ID = 0;
|
||||||
var MAX_INT = 4294967295;
|
var MAX_INT = 4294967295;
|
||||||
|
|
||||||
/* Args:
|
/*
|
||||||
|
* Args:
|
||||||
* server-*-start:
|
* server-*-start:
|
||||||
* 0 -> id
|
* 0 -> id
|
||||||
* 1 -> remoteIP
|
* 1 -> remoteIP
|
||||||
|
@ -99,4 +100,3 @@ module.exports = function() {
|
||||||
|
|
||||||
return SERVER_PROVIDER;
|
return SERVER_PROVIDER;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ Object.keys(CODES).forEach(function(code) {
|
||||||
message || msg,
|
message || msg,
|
||||||
dn || null,
|
dn || null,
|
||||||
caller || module.exports[err]);
|
caller || module.exports[err]);
|
||||||
}
|
};
|
||||||
module.exports[err].constructor = module.exports[err];
|
module.exports[err].constructor = module.exports[err];
|
||||||
util.inherits(module.exports[err], LDAPError);
|
util.inherits(module.exports[err], LDAPError);
|
||||||
|
|
||||||
|
@ -136,6 +136,6 @@ module.exports.getMessage = function(code) {
|
||||||
if (typeof (code) !== 'number')
|
if (typeof (code) !== 'number')
|
||||||
throw new TypeError('code (number) required');
|
throw new TypeError('code (number) required');
|
||||||
|
|
||||||
var errObj = ERRORS[res.status];
|
var errObj = ERRORS[code];
|
||||||
return (errObj && errObj.message ? errObj.message : '');
|
return (errObj && errObj.message ? errObj.message : '');
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,9 +55,10 @@ AndFilter.prototype.matches = function(target) {
|
||||||
|
|
||||||
var matches = this.filters.length ? true : false;
|
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))
|
if (!this.filters[i].matches(target))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,8 +60,16 @@ function matchParens(str, openParenIndex) {
|
||||||
// the filter tree is an intermediary step between the incoming expression and
|
// the filter tree is an intermediary step between the incoming expression and
|
||||||
// the outgoing Filter Class structure.
|
// the outgoing Filter Class structure.
|
||||||
function _buildFilterTree(expr) {
|
function _buildFilterTree(expr) {
|
||||||
|
var c;
|
||||||
|
var child;
|
||||||
|
var clean = false;
|
||||||
|
var endParen;
|
||||||
|
var esc = false;
|
||||||
|
var i = 0;
|
||||||
var tree = {};
|
var tree = {};
|
||||||
var split;
|
var split;
|
||||||
|
var substrNdx = 0;
|
||||||
|
var val = '';
|
||||||
|
|
||||||
if (expr.length === 0)
|
if (expr.length === 0)
|
||||||
return tree;
|
return tree;
|
||||||
|
@ -85,13 +93,10 @@ function _buildFilterTree(expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tree.op != 'expr') {
|
if (tree.op != 'expr') {
|
||||||
var child;
|
|
||||||
var i = 0;
|
|
||||||
tree.children = [];
|
tree.children = [];
|
||||||
|
|
||||||
// logical operators are k-ary, so we go until our expression string runs
|
// logical operators are k-ary, so we go until our expression string runs
|
||||||
// out (at least for this recursion level)
|
// out (at least for this recursion level)
|
||||||
var endParen;
|
|
||||||
while (expr.length !== 0) {
|
while (expr.length !== 0) {
|
||||||
endParen = matchParens(expr);
|
endParen = matchParens(expr);
|
||||||
if (endParen == expr.length - 1) {
|
if (endParen == expr.length - 1) {
|
||||||
|
@ -107,29 +112,23 @@ function _buildFilterTree(expr) {
|
||||||
} else {
|
} else {
|
||||||
//else its some sort of non-logical expression, parse and return as such
|
//else its some sort of non-logical expression, parse and return as such
|
||||||
var operatorStr = '';
|
var operatorStr = '';
|
||||||
var valueOffset = 0;
|
|
||||||
tree.name = '';
|
tree.name = '';
|
||||||
tree.value = '';
|
tree.value = '';
|
||||||
if (expr.indexOf('~=') !== -1) {
|
if (expr.indexOf('~=') !== -1) {
|
||||||
operatorStr = '~=';
|
operatorStr = '~=';
|
||||||
tree.tag = 'approxMatch';
|
tree.tag = 'approxMatch';
|
||||||
valueOffset = 2;
|
|
||||||
} else if (expr.indexOf('>=') !== -1) {
|
} else if (expr.indexOf('>=') !== -1) {
|
||||||
operatorStr = '>=';
|
operatorStr = '>=';
|
||||||
tree.tag = 'greaterOrEqual';
|
tree.tag = 'greaterOrEqual';
|
||||||
valueOffset = 2;
|
|
||||||
} else if (expr.indexOf('<=') !== -1) {
|
} else if (expr.indexOf('<=') !== -1) {
|
||||||
operatorStr = '<=';
|
operatorStr = '<=';
|
||||||
tree.tag = 'lessOrEqual';
|
tree.tag = 'lessOrEqual';
|
||||||
valueOffset = 2;
|
|
||||||
} else if (expr.indexOf(':=') !== -1) {
|
} else if (expr.indexOf(':=') !== -1) {
|
||||||
operatorStr = ':=';
|
operatorStr = ':=';
|
||||||
tree.tag = 'extensibleMatch';
|
tree.tag = 'extensibleMatch';
|
||||||
valueOffset = 2;
|
|
||||||
} else if (expr.indexOf('=') !== -1) {
|
} else if (expr.indexOf('=') !== -1) {
|
||||||
operatorStr = '=';
|
operatorStr = '=';
|
||||||
tree.tag = 'equalityMatch';
|
tree.tag = 'equalityMatch';
|
||||||
valueOffset = 1;
|
|
||||||
} else {
|
} else {
|
||||||
tree.tag = 'present';
|
tree.tag = 'present';
|
||||||
}
|
}
|
||||||
|
@ -138,7 +137,6 @@ function _buildFilterTree(expr) {
|
||||||
tree.name = expr;
|
tree.name = expr;
|
||||||
} else {
|
} else {
|
||||||
// pull out lhs and rhs of equality operator
|
// pull out lhs and rhs of equality operator
|
||||||
var clean = false;
|
|
||||||
var splitAry = expr.split(operatorStr);
|
var splitAry = expr.split(operatorStr);
|
||||||
tree.name = splitAry.shift();
|
tree.name = splitAry.shift();
|
||||||
tree.value = splitAry.join(operatorStr);
|
tree.value = splitAry.join(operatorStr);
|
||||||
|
@ -149,17 +147,14 @@ function _buildFilterTree(expr) {
|
||||||
if (tree.value.length === 0) {
|
if (tree.value.length === 0) {
|
||||||
tree.tag = 'present';
|
tree.tag = 'present';
|
||||||
} else {
|
} else {
|
||||||
var substrNdx = 0;
|
|
||||||
var substr = false;
|
|
||||||
var esc = false;
|
|
||||||
|
|
||||||
// Effectively a hand-rolled .shift() to support \* sequences
|
// Effectively a hand-rolled .shift() to support \* sequences
|
||||||
clean = true;
|
clean = true;
|
||||||
split = [];
|
split = [];
|
||||||
substrNdx = 0;
|
substrNdx = 0;
|
||||||
split[substrNdx] = '';
|
split[substrNdx] = '';
|
||||||
for (var i = 0; i < tree.value.length; i++) {
|
for (i = 0; i < tree.value.length; i++) {
|
||||||
var c = tree.value[i];
|
c = tree.value[i];
|
||||||
if (esc) {
|
if (esc) {
|
||||||
split[substrNdx] += c;
|
split[substrNdx] += c;
|
||||||
esc = false;
|
esc = false;
|
||||||
|
@ -227,10 +222,9 @@ function _buildFilterTree(expr) {
|
||||||
|
|
||||||
// Cleanup any escape sequences
|
// Cleanup any escape sequences
|
||||||
if (!clean) {
|
if (!clean) {
|
||||||
var val = '';
|
|
||||||
var esc = false;
|
for (i = 0; i < tree.value.length; i++) {
|
||||||
for (var i = 0; i < tree.value.length; i++) {
|
c = tree.value[i];
|
||||||
var c = tree.value[i];
|
|
||||||
if (esc) {
|
if (esc) {
|
||||||
val += c;
|
val += c;
|
||||||
esc = false;
|
esc = false;
|
||||||
|
@ -250,7 +244,7 @@ function _buildFilterTree(expr) {
|
||||||
|
|
||||||
function serializeTree(tree, filter) {
|
function serializeTree(tree, filter) {
|
||||||
if (tree === undefined || tree.length === 0)
|
if (tree === undefined || tree.length === 0)
|
||||||
return filter;
|
return;
|
||||||
|
|
||||||
// if the current tree object is not an expression then its a logical
|
// if the current tree object is not an expression then its a logical
|
||||||
// operator (ie an internal node in the tree)
|
// operator (ie an internal node in the tree)
|
||||||
|
@ -266,6 +260,8 @@ function serializeTree(tree, filter) {
|
||||||
case 'not':
|
case 'not':
|
||||||
current = new NotFilter();
|
current = new NotFilter();
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
filter.addFilter(current || filter);
|
filter.addFilter(current || filter);
|
||||||
|
@ -321,7 +317,10 @@ function serializeTree(tree, filter) {
|
||||||
attribute: tree.name
|
attribute: tree.name
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (tmp)
|
||||||
filter.addFilter(tmp);
|
filter.addFilter(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,4 +482,3 @@ module.exports = {
|
||||||
SubstringFilter: SubstringFilter,
|
SubstringFilter: SubstringFilter,
|
||||||
Filter: Filter
|
Filter: Filter
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,10 @@ OrFilter.prototype.matches = function(target) {
|
||||||
if (typeof (target) !== 'object')
|
if (typeof (target) !== 'object')
|
||||||
throw new TypeError('target (object) required');
|
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))
|
if (this.filters[i].matches(target))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,6 @@ var errors = require('./errors');
|
||||||
var filters = require('./filters');
|
var filters = require('./filters');
|
||||||
var logStub = require('./log_stub');
|
var logStub = require('./log_stub');
|
||||||
var messages = require('./messages');
|
var messages = require('./messages');
|
||||||
var schema = require('./schema');
|
|
||||||
var url = require('./url');
|
var url = require('./url');
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,12 +66,7 @@ module.exports = {
|
||||||
|
|
||||||
log4js: logStub,
|
log4js: logStub,
|
||||||
parseURL: url.parse,
|
parseURL: url.parse,
|
||||||
url: url,
|
url: url
|
||||||
|
|
||||||
loadSchema: schema.load,
|
|
||||||
createSchemaAddHandler: schema.createAddHandler,
|
|
||||||
createSchemaModifyHandler: schema.createModifyHandler,
|
|
||||||
createSchemaSearchHandler: schema.createSearchHandler
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ function AbandonRequest(options) {
|
||||||
|
|
||||||
this.abandonID = options.abandonID || 0;
|
this.abandonID = options.abandonID || 0;
|
||||||
|
|
||||||
var self = this;
|
|
||||||
this.__defineGetter__('type', function () { return 'AbandonRequest'; });
|
this.__defineGetter__('type', function () { return 'AbandonRequest'; });
|
||||||
}
|
}
|
||||||
util.inherits(AbandonRequest, LDAPMessage);
|
util.inherits(AbandonRequest, LDAPMessage);
|
||||||
|
@ -77,7 +76,7 @@ AbandonRequest.prototype._toBer = function(ber) {
|
||||||
var i = this.abandonID;
|
var i = this.abandonID;
|
||||||
var sz = 4;
|
var sz = 4;
|
||||||
|
|
||||||
while ((((i & 0xff800000) == 0) || ((i & 0xff800000) == 0xff800000)) &&
|
while ((((i & 0xff800000) === 0) || ((i & 0xff800000) === 0xff800000)) &&
|
||||||
(sz > 1)) {
|
(sz > 1)) {
|
||||||
sz--;
|
sz--;
|
||||||
i <<= 8;
|
i <<= 8;
|
||||||
|
@ -100,4 +99,3 @@ AbandonRequest.prototype._json = function(j) {
|
||||||
|
|
||||||
return j;
|
return j;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -108,9 +108,10 @@ AddRequest.prototype.indexOf = function(attr) {
|
||||||
if (!attr || typeof (attr) !== 'string')
|
if (!attr || typeof (attr) !== 'string')
|
||||||
throw new TypeError('attr (string) required');
|
throw new TypeError('attr (string) required');
|
||||||
|
|
||||||
for (var i = 0; i < this.attributes.length; i++)
|
for (var i = 0; i < this.attributes.length; i++) {
|
||||||
if (this.attributes[i].type === attr)
|
if (this.attributes[i].type === attr)
|
||||||
return i;
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
@ -120,7 +121,7 @@ AddRequest.prototype.attributeNames = function() {
|
||||||
var attrs = [];
|
var attrs = [];
|
||||||
|
|
||||||
for (var i = 0; i < this.attributes.length; i++)
|
for (var i = 0; i < this.attributes.length; i++)
|
||||||
attrs.push[this.attributes[i].type.toLowerCase()];
|
attrs.push(this.attributes[i].type.toLowerCase());
|
||||||
|
|
||||||
return attrs;
|
return attrs;
|
||||||
};
|
};
|
||||||
|
@ -132,9 +133,10 @@ AddRequest.prototype.getAttribute = function(name) {
|
||||||
|
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
|
|
||||||
for (var i = 0; i < this.attributes.length; i++)
|
for (var i = 0; i < this.attributes.length; i++) {
|
||||||
if (this.attributes[i].type === name)
|
if (this.attributes[i].type === name)
|
||||||
return this.attribute[i];
|
return this.attribute[i];
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
@ -142,7 +144,7 @@ AddRequest.prototype.getAttribute = function(name) {
|
||||||
|
|
||||||
AddRequest.prototype.addAttribute = function (attr) {
|
AddRequest.prototype.addAttribute = function (attr) {
|
||||||
if (!(attr instanceof Attribute))
|
if (!(attr instanceof Attribute))
|
||||||
throw new TypeEroror('attribute (Attribute) required');
|
throw new TypeError('attribute (Attribute) required');
|
||||||
|
|
||||||
return this.attributes.push(attr);
|
return this.attributes.push(attr);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,4 +22,3 @@ function BindResponse(options) {
|
||||||
}
|
}
|
||||||
util.inherits(BindResponse, LDAPResult);
|
util.inherits(BindResponse, LDAPResult);
|
||||||
module.exports = BindResponse;
|
module.exports = BindResponse;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ var LDAPMessage = require('./message');
|
||||||
var LDAPResult = require('./result');
|
var LDAPResult = require('./result');
|
||||||
|
|
||||||
var dn = require('../dn');
|
var dn = require('../dn');
|
||||||
|
var Attribute = require('../attribute');
|
||||||
var Change = require('../change');
|
var Change = require('../change');
|
||||||
var Protocol = require('../protocol');
|
var Protocol = require('../protocol');
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,6 @@ Parser.prototype.write = function(data) {
|
||||||
if (!data || !Buffer.isBuffer(data))
|
if (!data || !Buffer.isBuffer(data))
|
||||||
throw new TypeError('data (buffer) required');
|
throw new TypeError('data (buffer) required');
|
||||||
|
|
||||||
var log = this.log;
|
|
||||||
var nextMessage = null;
|
var nextMessage = null;
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -116,7 +115,6 @@ Parser.prototype.write = function(data) {
|
||||||
Parser.prototype.getMessage = function (ber) {
|
Parser.prototype.getMessage = function (ber) {
|
||||||
assert.ok(ber);
|
assert.ok(ber);
|
||||||
|
|
||||||
var log = this.log;
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var messageID = ber.readInt();
|
var messageID = ber.readInt();
|
||||||
|
@ -209,8 +207,7 @@ Parser.prototype.getMessage = function(ber) {
|
||||||
this.emit('error',
|
this.emit('error',
|
||||||
new Error('protocolOp 0x' +
|
new Error('protocolOp 0x' +
|
||||||
(type ? type.toString(16) : '??') +
|
(type ? type.toString(16) : '??') +
|
||||||
' not supported'
|
' not supported'),
|
||||||
),
|
|
||||||
new LDAPResult({
|
new LDAPResult({
|
||||||
messageID: messageID,
|
messageID: messageID,
|
||||||
protocolOp: type || Protocol.LDAP_REP_EXTENSION
|
protocolOp: type || Protocol.LDAP_REP_EXTENSION
|
||||||
|
@ -225,4 +222,3 @@ Parser.prototype.getMessage = function(ber) {
|
||||||
log4js: self.log4js
|
log4js: self.log4js
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,3 @@ SearchEntry.prototype._toBer = function(ber) {
|
||||||
|
|
||||||
return ber;
|
return ber;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,3 @@ SearchReference.prototype._toBer = function(ber) {
|
||||||
|
|
||||||
return ber;
|
return ber;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ SearchResponse.prototype.send = function(entry, nofiltering) {
|
||||||
savedAttrs[a] = entry.attributes[a];
|
savedAttrs[a] = entry.attributes[a];
|
||||||
delete entry.attributes[a];
|
delete entry.attributes[a];
|
||||||
} else if (all) {
|
} else if (all) {
|
||||||
// noop
|
return;
|
||||||
} else if (self.attributes.length && self.attributes.indexOf(_a) === -1) {
|
} else if (self.attributes.length && self.attributes.indexOf(_a) === -1) {
|
||||||
savedAttrs[a] = entry.attributes[a];
|
savedAttrs[a] = entry.attributes[a];
|
||||||
delete entry.attributes[a];
|
delete entry.attributes[a];
|
||||||
|
|
|
@ -48,8 +48,6 @@ module.exports = UnbindRequest;
|
||||||
|
|
||||||
|
|
||||||
UnbindRequest.prototype.newResult = function () {
|
UnbindRequest.prototype.newResult = function () {
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// This one is special, so just hack up the result object
|
// This one is special, so just hack up the result object
|
||||||
function UnbindResponse(options) {
|
function UnbindResponse(options) {
|
||||||
LDAPMessage.call(this, options);
|
LDAPMessage.call(this, options);
|
||||||
|
@ -58,7 +56,7 @@ UnbindRequest.prototype.newResult = function() {
|
||||||
util.inherits(UnbindResponse, LDAPMessage);
|
util.inherits(UnbindResponse, LDAPMessage);
|
||||||
UnbindResponse.prototype.end = function (status) {
|
UnbindResponse.prototype.end = function (status) {
|
||||||
if (this.log.isTraceEnabled())
|
if (this.log.isTraceEnabled())
|
||||||
log.trace('%s: unbinding!', this.connection.ldap.id);
|
this.log.trace('%s: unbinding!', this.connection.ldap.id);
|
||||||
this.connection.end();
|
this.connection.end();
|
||||||
};
|
};
|
||||||
UnbindResponse.prototype._json = function (j) { return 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
|
|
||||||
// }
|
|
|
@ -7,7 +7,6 @@ var tls = require('tls');
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
|
||||||
var asn1 = require('asn1');
|
var asn1 = require('asn1');
|
||||||
var sprintf = require('sprintf').sprintf;
|
|
||||||
|
|
||||||
var dn = require('./dn');
|
var dn = require('./dn');
|
||||||
var dtrace = require('./dtrace');
|
var dtrace = require('./dtrace');
|
||||||
|
@ -37,6 +36,8 @@ var Ber = asn1.Ber;
|
||||||
var BerReader = asn1.BerReader;
|
var BerReader = asn1.BerReader;
|
||||||
var DN = dn.DN;
|
var DN = dn.DN;
|
||||||
|
|
||||||
|
var sprintf = util.format;
|
||||||
|
|
||||||
|
|
||||||
///--- Helpers
|
///--- Helpers
|
||||||
|
|
||||||
|
@ -220,6 +221,8 @@ function fireDTraceProbe(req, res) {
|
||||||
case Protocol.LDAP_REQ_UNBIND:
|
case Protocol.LDAP_REQ_UNBIND:
|
||||||
op = 'unbind';
|
op = 'unbind';
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
res._dtraceOp = op;
|
res._dtraceOp = op;
|
||||||
|
@ -436,7 +439,7 @@ function Server(options) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}; // end newConnection
|
} // end newConnection
|
||||||
|
|
||||||
this.routes = {};
|
this.routes = {};
|
||||||
if ((options.cert || options.certificate) && options.key) {
|
if ((options.cert || options.certificate) && options.key) {
|
||||||
|
@ -715,7 +718,7 @@ Server.prototype._getRoute = function(_dn, backend) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Server.prototype._getHandlerChain = function(req, res) {
|
Server.prototype._getHandlerChain = function _getHandlerChain(req, res) {
|
||||||
assert.ok(req);
|
assert.ok(req);
|
||||||
|
|
||||||
fireDTraceProbe(req, res);
|
fireDTraceProbe(req, res);
|
||||||
|
@ -741,43 +744,34 @@ Server.prototype._getHandlerChain = function(req, res) {
|
||||||
|
|
||||||
// Special cases are abandons, exops and unbinds, handle those first.
|
// Special cases are abandons, exops and unbinds, handle those first.
|
||||||
if (req.protocolOp === Protocol.LDAP_REQ_EXTENSION) {
|
if (req.protocolOp === Protocol.LDAP_REQ_EXTENSION) {
|
||||||
if (r !== req.requestName)
|
if (r === req.requestName) {
|
||||||
continue;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
backend: routes.backend,
|
backend: routes.backend,
|
||||||
handlers: route[op] || [noExOpHandler]
|
handlers: route[op] || [noExOpHandler]
|
||||||
};
|
};
|
||||||
|
}
|
||||||
} else if (req.protocolOp === Protocol.LDAP_REQ_UNBIND) {
|
} else if (req.protocolOp === Protocol.LDAP_REQ_UNBIND) {
|
||||||
function getUnbindChain() {
|
return {
|
||||||
|
backend: routes['unbind'] ? routes['unbind'].backend : self,
|
||||||
|
handlers: function getUnbindChain() {
|
||||||
if (routes['unbind'] && routes['unbind'][op])
|
if (routes['unbind'] && routes['unbind'][op])
|
||||||
return routes['unbind'][op];
|
return routes['unbind'][op];
|
||||||
|
|
||||||
self.log.debug('%s unbind request %j', req.logId, req.json);
|
self.log.debug('%s unbind request %j', req.logId, req.json);
|
||||||
return [defaultNoOpHandler];
|
return [defaultNoOpHandler];
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
backend: routes['unbind'] ? routes['unbind'].backend : self,
|
|
||||||
handlers: getUnbindChain()
|
|
||||||
};
|
};
|
||||||
} else if (req.protocolOp === Protocol.LDAP_REQ_ABANDON) {
|
} else if (req.protocolOp === Protocol.LDAP_REQ_ABANDON) {
|
||||||
return {
|
return {
|
||||||
backend: self,
|
backend: self,
|
||||||
handlers: [defaultNoOpHandler]
|
handlers: [defaultNoOpHandler]
|
||||||
};
|
};
|
||||||
}
|
} else if (route[op]) {
|
||||||
|
|
||||||
if (!route[op])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Otherwise, match via DN rules
|
// Otherwise, match via DN rules
|
||||||
assert.ok(req.dn);
|
assert.ok(req.dn);
|
||||||
assert.ok(route.dn);
|
assert.ok(route.dn);
|
||||||
|
|
||||||
if (!route.dn.equals(req.dn) && !route.dn.parentOf(req.dn))
|
if (route.dn.equals(req.dn) || route.dn.parentOf(req.dn)) {
|
||||||
continue;
|
|
||||||
|
|
||||||
// We should be good to go.
|
// We should be good to go.
|
||||||
req.suffix = route.dn;
|
req.suffix = route.dn;
|
||||||
return {
|
return {
|
||||||
|
@ -785,6 +779,8 @@ Server.prototype._getHandlerChain = function(req, res) {
|
||||||
handlers: route[op] || [defaultHandler]
|
handlers: route[op] || [defaultHandler]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We're here, so nothing matched.
|
// We're here, so nothing matched.
|
||||||
return {
|
return {
|
||||||
|
|
14
package.json
14
package.json
|
@ -9,7 +9,7 @@
|
||||||
"name": "ldapjs",
|
"name": "ldapjs",
|
||||||
"homepage": "http://ldapjs.org",
|
"homepage": "http://ldapjs.org",
|
||||||
"description": "LDAP client and server APIs",
|
"description": "LDAP client and server APIs",
|
||||||
"version": "0.4.8",
|
"version": "0.5.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git://github.com/mcavage/node-ldapjs.git"
|
"url": "git://github.com/mcavage/node-ldapjs.git"
|
||||||
|
@ -20,17 +20,17 @@
|
||||||
"lib": "./lib"
|
"lib": "./lib"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.4"
|
"node": ">=0.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asn1": "0.1.11",
|
"asn1": "0.1.11",
|
||||||
"buffertools": "1.0.6",
|
"buffertools": "1.0.7",
|
||||||
"dtrace-provider": "0.0.3",
|
"bunyan": "0.6.3",
|
||||||
"nopt": "1.0.10",
|
"dtrace-provider": "0.0.6",
|
||||||
"sprintf": "0.1.1"
|
"nopt": "1.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tap": "0.1.4",
|
"tap": "0.2",
|
||||||
"node-uuid": "1.3.3"
|
"node-uuid": "1.3.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -52,14 +52,13 @@ 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 {
|
try {
|
||||||
new Change({
|
t.notOk(new Change({
|
||||||
operation: 'replace',
|
operation: 'replace',
|
||||||
modification: {
|
modification: {
|
||||||
cn: 'foo',
|
cn: 'foo',
|
||||||
sn: 'bar'
|
sn: 'bar'
|
||||||
}
|
}
|
||||||
});
|
}), 'should have thrown');
|
||||||
t.fail('should have thrown');
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
t.ok(e);
|
t.ok(e);
|
||||||
t.end();
|
t.end();
|
|
@ -68,16 +68,6 @@ test('getControl with args', function(t) {
|
||||||
0x34, 0x2e, 0x33, 0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01,
|
0x34, 0x2e, 0x33, 0x04, 0x0b, 0x30, 0x09, 0x02, 0x01, 0x0f, 0x01, 0x01,
|
||||||
0xff, 0x01, 0x01, 0xff]);
|
0xff, 0x01, 0x01, 0xff]);
|
||||||
|
|
||||||
var 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 ber = new BerReader(buf);
|
||||||
var psc = getControl(ber);
|
var psc = getControl(ber);
|
||||||
t.ok(psc);
|
t.ok(psc);
|
|
@ -77,5 +77,3 @@ test('match false', function(t) {
|
||||||
t.ok(!f.matches({ foo: 'bar', zig: 'zonk' }));
|
t.ok(!f.matches({ foo: 'bar', zig: 'zonk' }));
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -108,4 +108,3 @@ test('parse RFC example 5', function(t) {
|
||||||
t.ok(f.dnAttributes);
|
t.ok(f.dnAttributes);
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,5 +68,3 @@ test('match false', function(t) {
|
||||||
t.ok(!f.matches({ foo: 'bar' }));
|
t.ok(!f.matches({ foo: 'bar' }));
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -77,5 +77,3 @@ test('match false', function(t) {
|
||||||
t.ok(!f.matches({ foo: 'baz', zig: 'zonk' }));
|
t.ok(!f.matches({ foo: 'baz', zig: 'zonk' }));
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ function search(t, options, callback) {
|
||||||
if (callback)
|
if (callback)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
t.end();
|
return t.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ var test = require('tap').test;
|
||||||
///--- Globals
|
///--- Globals
|
||||||
|
|
||||||
var url;
|
var url;
|
||||||
|
var parseURL;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#
|
#
|
||||||
# Configuration File for JavaScript Lint 0.3.0
|
# Configuration File for JavaScript Lint
|
||||||
# Developed by Matthias Miller (http://www.JavaScriptLint.com)
|
|
||||||
#
|
#
|
||||||
# This configuration file can be used to lint a collection of scripts, or to enable
|
# This configuration file can be used to lint a collection of scripts, or to enable
|
||||||
# or disable warnings for scripts that are linted via the command line.
|
# or disable warnings for scripts that are linted via the command line.
|
||||||
|
@ -10,59 +9,74 @@
|
||||||
# Enable or disable warnings based on requirements.
|
# Enable or disable warnings based on requirements.
|
||||||
# Use "+WarningName" to display or "-WarningName" to suppress.
|
# Use "+WarningName" to display or "-WarningName" to suppress.
|
||||||
#
|
#
|
||||||
+no_return_value # function {0} does not always return a value
|
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent
|
||||||
+duplicate_formal # duplicate formal argument {0}
|
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
|
||||||
+equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
|
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
|
||||||
+var_hides_arg # variable {0} hides argument
|
+anon_no_return_value # anonymous function does not always return value
|
||||||
+redeclared_var # redeclaration of {0} {1}
|
+assign_to_function_call # assignment to a function call
|
||||||
+anon_no_return_value # anonymous function does not always return a value
|
-block_without_braces # block statement without curly braces
|
||||||
+missing_semicolon # missing semicolon
|
|
||||||
+meaningless_block # meaningless block; curly braces have no impact
|
|
||||||
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
|
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
|
||||||
-unreachable_code # unreachable code
|
+comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
|
||||||
|
+default_not_at_end # the default case is not at the end of the switch statement
|
||||||
|
+dup_option_explicit # duplicate "option explicit" control comment
|
||||||
|
+duplicate_case_in_switch # duplicate case in switch statement
|
||||||
|
+duplicate_formal # duplicate formal argument {name}
|
||||||
|
+empty_statement # empty statement or extra semicolon
|
||||||
|
+identifier_hides_another # identifer {name} hides an identifier in a parent scope
|
||||||
|
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
|
||||||
|
+incorrect_version # Expected /*jsl:content-type*/ control comment. The script was parsed with the wrong version.
|
||||||
|
+invalid_fallthru # unexpected "fallthru" control comment
|
||||||
|
+invalid_pass # unexpected "pass" control comment
|
||||||
|
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
|
||||||
|
+leading_decimal_point # leading decimal point may indicate a number or an object member
|
||||||
|
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
|
||||||
|
+meaningless_block # meaningless block; curly braces have no impact
|
||||||
|
+mismatch_ctrl_comments # mismatched control comment; "ignore" and "end" control comments must have a one-to-one correspondence
|
||||||
|
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
|
||||||
+missing_break # missing break statement
|
+missing_break # missing break statement
|
||||||
+missing_break_for_last_case # missing break statement for last case in switch
|
+missing_break_for_last_case # missing break statement for last case in switch
|
||||||
+comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
|
+missing_default_case # missing default case in switch statement
|
||||||
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
|
+missing_option_explicit # the "option explicit" control comment is missing
|
||||||
+useless_void # use of the void type may be unnecessary (void is always undefined)
|
+missing_semicolon # missing semicolon
|
||||||
-useless_quotes # quotation marks are unnecessary
|
+missing_semicolon_for_lambda # missing semicolon for lambda assignment
|
||||||
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
|
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
|
||||||
+use_of_label # use of label
|
|
||||||
-block_without_braces # block statement without curly braces
|
|
||||||
+leading_decimal_point # leading decimal point may indicate a number or an object member
|
|
||||||
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
|
|
||||||
-octal_number # leading zeros make an octal number
|
|
||||||
+nested_comment # nested comment
|
+nested_comment # nested comment
|
||||||
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
|
+no_return_value # function {name} does not always return a value
|
||||||
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
|
+octal_number # leading zeros make an octal number
|
||||||
+empty_statement # empty statement or extra semicolon
|
|
||||||
-missing_option_explicit # the "option explicit" control comment is missing
|
|
||||||
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
|
|
||||||
+dup_option_explicit # duplicate "option explicit" control comment
|
|
||||||
+useless_assign # useless assignment
|
|
||||||
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
|
|
||||||
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
|
|
||||||
-missing_default_case # missing default case in switch statement
|
|
||||||
+duplicate_case_in_switch # duplicate case in switch statements
|
|
||||||
+default_not_at_end # the default case is not at the end of the switch statement
|
|
||||||
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
|
|
||||||
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
|
|
||||||
+useless_comparison # useless comparison; comparing identical expressions
|
|
||||||
+with_statement # with statement hides undeclared variables; use temporary variable instead
|
|
||||||
+trailing_comma_in_array # extra comma is not recommended in array initializers
|
|
||||||
+assign_to_function_call # assignment to a function call
|
|
||||||
+parseint_missing_radix # parseInt missing radix parameter
|
+parseint_missing_radix # parseInt missing radix parameter
|
||||||
+unreferenced_argument # argument declared but never referenced: {name}
|
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
|
||||||
+unreferenced_function # function declared but not referenced
|
+redeclared_var # redeclaration of {name}
|
||||||
|
+trailing_comma_in_array # extra comma is not recommended in array initializers
|
||||||
|
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
|
||||||
|
+undeclared_identifier # undeclared identifier: {name}
|
||||||
|
+unreachable_code # unreachable code
|
||||||
|
-unreferenced_argument # argument declared but never referenced: {name}
|
||||||
|
-unreferenced_function # function is declared but never referenced: {name}
|
||||||
|
+unreferenced_variable # variable is declared but never referenced: {name}
|
||||||
|
+unsupported_version # JavaScript {version} is not supported
|
||||||
|
+use_of_label # use of label
|
||||||
|
+useless_assign # useless assignment
|
||||||
|
+useless_comparison # useless comparison; comparing identical expressions
|
||||||
|
-useless_quotes # the quotation marks are unnecessary
|
||||||
|
+useless_void # use of the void type may be unnecessary (void is always undefined)
|
||||||
|
+var_hides_arg # variable {name} hides argument
|
||||||
|
+want_assign_or_call # expected an assignment or function call
|
||||||
|
+with_statement # with statement hides undeclared variables; use temporary variable instead
|
||||||
-identifier_hides_another
|
-identifier_hides_another
|
||||||
-empty_statement
|
|
||||||
|
|
||||||
### Output format
|
### Output format
|
||||||
# Customize the format of the error message.
|
# Customize the format of the error message.
|
||||||
# __FILE__ indicates current file path
|
# __FILE__ indicates current file path
|
||||||
# __FILENAME__ indicates current file name
|
# __FILENAME__ indicates current file name
|
||||||
# __LINE__ indicates current line
|
# __LINE__ indicates current line
|
||||||
# __ERROR__ indicates error message
|
# __COL__ indicates current column
|
||||||
|
# __ERROR__ indicates error message (__ERROR_PREFIX__: __ERROR_MSG__)
|
||||||
|
# __ERROR_NAME__ indicates error name (used in configuration file)
|
||||||
|
# __ERROR_PREFIX__ indicates error prefix
|
||||||
|
# __ERROR_MSG__ indicates error message
|
||||||
|
#
|
||||||
|
# For machine-friendly output, the output format can be prefixed with
|
||||||
|
# "encode:". If specified, all items will be encoded with C-slashes.
|
||||||
#
|
#
|
||||||
# Visual Studio syntax (default):
|
# Visual Studio syntax (default):
|
||||||
+output-format __FILE__(__LINE__): __ERROR__
|
+output-format __FILE__(__LINE__): __ERROR__
|
||||||
|
@ -77,33 +91,13 @@
|
||||||
+context
|
+context
|
||||||
|
|
||||||
|
|
||||||
### Semicolons
|
|
||||||
# By default, assignments of an anonymous function to a variable or
|
|
||||||
# property (such as a function prototype) must be followed by a semicolon.
|
|
||||||
#
|
|
||||||
#+lambda_assign_requires_semicolon # deprecated setting
|
|
||||||
|
|
||||||
|
|
||||||
### Control Comments
|
### Control Comments
|
||||||
# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
|
# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
|
||||||
# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
|
# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
|
||||||
# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
|
# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
|
||||||
# although legacy control comments are enabled by default for backward compatibility.
|
# although legacy control comments are enabled by default for backward compatibility.
|
||||||
#
|
#
|
||||||
+legacy_control_comments
|
-legacy_control_comments
|
||||||
|
|
||||||
|
|
||||||
### JScript Function Extensions
|
|
||||||
# JScript allows member functions to be defined like this:
|
|
||||||
# function MyObj() { /*constructor*/ }
|
|
||||||
# function MyObj.prototype.go() { /*member function*/ }
|
|
||||||
#
|
|
||||||
# It also allows events to be attached like this:
|
|
||||||
# function window::onload() { /*init page*/ }
|
|
||||||
#
|
|
||||||
# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
|
|
||||||
#
|
|
||||||
#-jscript_function_extensions # deprecated setting
|
|
||||||
|
|
||||||
|
|
||||||
### Defining identifiers
|
### Defining identifiers
|
||||||
|
@ -115,21 +109,25 @@
|
||||||
# (Use this in conjunction with the "undeclared identifier" warning.)
|
# (Use this in conjunction with the "undeclared identifier" warning.)
|
||||||
#
|
#
|
||||||
# Common uses for webpages might be:
|
# Common uses for webpages might be:
|
||||||
|
+define __dirname
|
||||||
|
+define clearInterval
|
||||||
|
+define clearTimeout
|
||||||
|
+define console
|
||||||
|
+define exports
|
||||||
+define global
|
+define global
|
||||||
|
+define module
|
||||||
+define process
|
+define process
|
||||||
+define require
|
+define require
|
||||||
+define exports
|
|
||||||
+define setTimeout
|
|
||||||
+define clearTimeout
|
|
||||||
+define setInterval
|
+define setInterval
|
||||||
+define clearInterval
|
+define setTimeout
|
||||||
+define JSON
|
|
||||||
+define console
|
|
||||||
+define __dirname
|
|
||||||
+define __filename
|
|
||||||
+define Buffer
|
+define Buffer
|
||||||
+define module
|
+define JSON
|
||||||
|
+define Math
|
||||||
|
|
||||||
|
### JavaScript Version
|
||||||
|
# To change the default JavaScript version:
|
||||||
|
#+default-type text/javascript;version=1.5
|
||||||
|
#+default-type text/javascript;e4x=1
|
||||||
|
|
||||||
### Files
|
### Files
|
||||||
# Specify which files to lint
|
# Specify which files to lint
|
||||||
|
@ -137,4 +135,4 @@
|
||||||
# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
|
# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
|
||||||
# or "+process Folder\Path\*.htm".
|
# or "+process Folder\Path\*.htm".
|
||||||
#
|
#
|
||||||
#+process jsl-test.js
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
indent=2
|
||||||
|
doxygen
|
||||||
|
unparenthesized-return=0
|
||||||
|
blank-after-start-comment=0
|
Loading…
Reference in New Issue