ldap-filters
Advanced tools
Comparing version 1.2.0 to 2.0.0
var Filter = require('./index'); | ||
var input = '(&(givenName=jenny)(sn=jensen)(|(c=us)(st=ontario)))'; | ||
var fs = require('fs'); | ||
input = fs.readFileSync('filter_test.txt','utf8'); | ||
var input = ' (& (givenName=jenny)\n(sn=jensen) \n(|(c=us)\n (st=ontario)) ) '; | ||
//var fs = require('fs'); | ||
//input = fs.readFileSync('filter_test.txt','utf8'); | ||
var parsed = Filter.parse(input); | ||
parsed = Filter.parse(parsed.toString(true)); | ||
//parsed = Filter.parse(parsed.toString(true)); | ||
parsed = Filter.parse(input); | ||
console.log(parsed); | ||
/* | ||
console.log(JSON.stringify(parsed,null,2)); | ||
console.log(parsed + ''); | ||
console.log(parsed.toString(true)); | ||
*/ |
@@ -105,5 +105,10 @@ var soundex = require('soundex'); | ||
var pattern = filter.replace(/\*/g,'.*'); | ||
pattern = pattern.replace(/\\([0-9a-fA-F]{2,2})/g,function(m,$1){ | ||
var s = String.fromCharCode(parseInt($1,16)); | ||
if (['(',')','\\','*'].indexOf(s)>=0) s = '\\x'+$1.toUpperCase(); | ||
return s; | ||
}); | ||
var regex = new RegExp('^'+pattern+'$','i'); | ||
return match.some(function(cv){ | ||
return Filter.escape(cv).match(regex); | ||
return cv.match(regex); | ||
}); | ||
@@ -219,2 +224,5 @@ }; | ||
}, | ||
raw: function(value) { | ||
return new Filter(this.name,'=',value); | ||
}, | ||
equalTo: function(value) { | ||
@@ -221,0 +229,0 @@ return new Filter(this.name,'=',this.escape(value)); |
1985
lib/parser.js
@@ -1,722 +0,1477 @@ | ||
/* parser generated by jison 0.4.15 */ | ||
/* | ||
Returns a Parser object of the following structure: | ||
module.exports = (function() { | ||
"use strict"; | ||
Parser: { | ||
yy: {} | ||
/* | ||
* Generated by PEG.js 0.9.0. | ||
* | ||
* http://pegjs.org/ | ||
*/ | ||
function peg$subclass(child, parent) { | ||
function ctor() { this.constructor = child; } | ||
ctor.prototype = parent.prototype; | ||
child.prototype = new ctor(); | ||
} | ||
Parser.prototype: { | ||
yy: {}, | ||
trace: function(), | ||
symbols_: {associative list: name ==> number}, | ||
terminals_: {associative list: number ==> name}, | ||
productions_: [...], | ||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), | ||
table: [...], | ||
defaultActions: {...}, | ||
parseError: function(str, hash), | ||
parse: function(input), | ||
function peg$SyntaxError(message, expected, found, location) { | ||
this.message = message; | ||
this.expected = expected; | ||
this.found = found; | ||
this.location = location; | ||
this.name = "SyntaxError"; | ||
lexer: { | ||
EOF: 1, | ||
parseError: function(str, hash), | ||
setInput: function(input), | ||
input: function(), | ||
unput: function(str), | ||
more: function(), | ||
less: function(n), | ||
pastInput: function(), | ||
upcomingInput: function(), | ||
showPosition: function(), | ||
test_match: function(regex_match_array, rule_index), | ||
next: function(), | ||
lex: function(), | ||
begin: function(condition), | ||
popState: function(), | ||
_currentRules: function(), | ||
topState: function(), | ||
pushState: function(condition), | ||
options: { | ||
ranges: boolean (optional: true ==> token location info will include a .range[] member) | ||
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) | ||
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) | ||
}, | ||
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), | ||
rules: [...], | ||
conditions: {associative list: name ==> set}, | ||
if (typeof Error.captureStackTrace === "function") { | ||
Error.captureStackTrace(this, peg$SyntaxError); | ||
} | ||
} | ||
peg$subclass(peg$SyntaxError, Error); | ||
token location info (@$, _$, etc.): { | ||
first_line: n, | ||
last_line: n, | ||
first_column: n, | ||
last_column: n, | ||
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) | ||
} | ||
function peg$parse(input) { | ||
var options = arguments.length > 1 ? arguments[1] : {}, | ||
parser = this, | ||
peg$FAILED = {}, | ||
the parseError function receives a 'hash' object with these members for lexer and parser errors: { | ||
text: (matched text) | ||
token: (the produced terminal token, if any) | ||
line: (yylineno) | ||
} | ||
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { | ||
loc: (yylloc) | ||
expected: (string describing the set of expected tokens) | ||
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) | ||
} | ||
*/ | ||
var parser = (function(){ | ||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,3],$V1=[1,28],$V2=[1,30],$V3=[7,26]; | ||
var parser = {trace: function trace() { }, | ||
yy: {}, | ||
symbols_: {"error":2,"done":3,"filter":4,"LEFT_PAREN":5,"filter_comp":6,"RIGHT_PAREN":7,"and":8,"or":9,"not":10,"operation":11,"AND":12,"filter_list":13,"OR":14,"NOT":15,"some_op":16,"present":17,"ATTR_STR":18,"filter_type":19,"value_str":20,"filter_type_ambiguous":21,"APPROX":22,"GREATER_EQ":23,"LESS_EQ":24,"EQUAL":25,"VALUE_STR":26,"$accept":0,"$end":1}, | ||
terminals_: {2:"error",5:"LEFT_PAREN",7:"RIGHT_PAREN",12:"AND",14:"OR",15:"NOT",17:"present",18:"ATTR_STR",22:"APPROX",23:"GREATER_EQ",24:"LESS_EQ",25:"EQUAL",26:"VALUE_STR"}, | ||
productions_: [0,[3,1],[4,3],[6,1],[6,1],[6,1],[6,1],[8,2],[9,2],[10,2],[13,1],[13,2],[11,1],[11,1],[16,3],[16,3],[19,1],[19,1],[19,1],[21,1],[20,1],[20,2]], | ||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { | ||
/* this == yyval */ | ||
peg$startRuleFunctions = { start: peg$parsestart }, | ||
peg$startRuleFunction = peg$parsestart, | ||
var $0 = $$.length - 1; | ||
switch (yystate) { | ||
case 1: | ||
peg$c0 = function(filter) { return filter; }, | ||
peg$c1 = "(", | ||
peg$c2 = { type: "literal", value: "(", description: "\"(\"" }, | ||
peg$c3 = ")", | ||
peg$c4 = { type: "literal", value: ")", description: "\")\"" }, | ||
peg$c5 = "&", | ||
peg$c6 = { type: "literal", value: "&", description: "\"&\"" }, | ||
peg$c7 = function(filters) { return Filter.AND(filters); }, | ||
peg$c8 = "|", | ||
peg$c9 = { type: "literal", value: "|", description: "\"|\"" }, | ||
peg$c10 = function(filters) { return Filter.OR(filters); }, | ||
peg$c11 = "!", | ||
peg$c12 = { type: "literal", value: "!", description: "\"!\"" }, | ||
peg$c13 = function(filter) { return Filter.NOT(filter); }, | ||
peg$c14 = function(attr, comp, value) { return new Filter(attr.attribute,comp,value); }, | ||
peg$c15 = "=", | ||
peg$c16 = { type: "literal", value: "=", description: "\"=\"" }, | ||
peg$c17 = "~=", | ||
peg$c18 = { type: "literal", value: "~=", description: "\"~=\"" }, | ||
peg$c19 = ">=", | ||
peg$c20 = { type: "literal", value: ">=", description: "\">=\"" }, | ||
peg$c21 = "<=", | ||
peg$c22 = { type: "literal", value: "<=", description: "\"<=\"" }, | ||
peg$c23 = "=*", | ||
peg$c24 = { type: "literal", value: "=*", description: "\"=*\"" }, | ||
peg$c25 = function(attr) { return Filter.attribute(attr.attribute).present(); }, | ||
peg$c26 = function(attr, value) { | ||
return new Filter(attr.attribute,'=',value); | ||
}, | ||
peg$c27 = "*", | ||
peg$c28 = { type: "literal", value: "*", description: "\"*\"" }, | ||
peg$c29 = { type: "other", description: "attribute description" }, | ||
peg$c30 = ";", | ||
peg$c31 = { type: "literal", value: ";", description: "\";\"" }, | ||
peg$c32 = function(attr, opts) { | ||
if (opts) { | ||
opts.shift(); | ||
opts = opts.shift(); | ||
opts = opts.split(';'); | ||
} | ||
attr.options = opts || []; | ||
return attr; | ||
}, | ||
peg$c33 = { type: "other", description: "attribute Type" }, | ||
peg$c34 = function(oid) { | ||
return { | ||
type: 'oid', | ||
attribute: oid | ||
}; | ||
}, | ||
peg$c35 = function(name) { | ||
return { | ||
type: 'attribute', | ||
attribute: name | ||
}; | ||
}, | ||
peg$c36 = { type: "other", description: "attribute type chars" }, | ||
peg$c37 = "-", | ||
peg$c38 = { type: "literal", value: "-", description: "\"-\"" }, | ||
peg$c39 = { type: "other", description: "OID" }, | ||
peg$c40 = ".", | ||
peg$c41 = { type: "literal", value: ".", description: "\".\"" }, | ||
peg$c42 = { type: "other", description: "attribute options" }, | ||
peg$c43 = { type: "other", description: "attribute option" }, | ||
peg$c44 = /^[^)]/, | ||
peg$c45 = { type: "class", value: "[^\\x29]", description: "[^\\x29]" }, | ||
peg$c46 = "\\", | ||
peg$c47 = { type: "literal", value: "\\", description: "\"\\\\\"" }, | ||
peg$c48 = function(char) { return String.fromCharCode(char); }, | ||
peg$c49 = function(value) { return parseInt(value,16); }, | ||
peg$c50 = /^[a-fA-F0-9]/, | ||
peg$c51 = { type: "class", value: "[a-fA-F0-9]", description: "[a-fA-F0-9]" }, | ||
peg$c52 = { type: "other", description: "WHITESPACE" }, | ||
peg$c53 = { type: "other", description: "SPACE" }, | ||
peg$c54 = /^[ ]/, | ||
peg$c55 = { type: "class", value: "[\\x20]", description: "[\\x20]" }, | ||
peg$c56 = { type: "other", description: "TAB" }, | ||
peg$c57 = /^[\t]/, | ||
peg$c58 = { type: "class", value: "[\\x09]", description: "[\\x09]" }, | ||
peg$c59 = { type: "other", description: "DIGIT" }, | ||
peg$c60 = /^[0-9]/, | ||
peg$c61 = { type: "class", value: "[0-9]", description: "[0-9]" }, | ||
peg$c62 = { type: "other", description: "ALPHA" }, | ||
peg$c63 = /^[a-zA-Z]/, | ||
peg$c64 = { type: "class", value: "[a-zA-Z]", description: "[a-zA-Z]" }, | ||
peg$c65 = { type: "other", description: "NEWLINE" }, | ||
peg$c66 = "\r\n", | ||
peg$c67 = { type: "literal", value: "\r\n", description: "\"\\r\\n\"" }, | ||
peg$c68 = "\n", | ||
peg$c69 = { type: "literal", value: "\n", description: "\"\\n\"" }, | ||
return $$[$0]; | ||
break; | ||
case 2: | ||
peg$currPos = 0, | ||
peg$savedPos = 0, | ||
peg$posDetailsCache = [{ line: 1, column: 1, seenCR: false }], | ||
peg$maxFailPos = 0, | ||
peg$maxFailExpected = [], | ||
peg$silentFails = 0, | ||
this.$ = $$[$0-1]; | ||
break; | ||
case 3: case 4: case 5: case 6: | ||
this.$ = $$[$0]; | ||
break; | ||
case 7: | ||
this.$ = Filter.AND($$[$0]); | ||
break; | ||
case 8: | ||
peg$result; | ||
this.$ = Filter.OR($$[$0]); | ||
break; | ||
case 9: | ||
if ("startRule" in options) { | ||
if (!(options.startRule in peg$startRuleFunctions)) { | ||
throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); | ||
} | ||
this.$ = Filter.NOT($$[$0]); | ||
break; | ||
case 10: | ||
peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; | ||
} | ||
this.$ = [ $$[$0] ]; | ||
break; | ||
case 11: | ||
function text() { | ||
return input.substring(peg$savedPos, peg$currPos); | ||
} | ||
$$[$0].unshift($$[$0-1]); | ||
this.$ = $$[$0]; | ||
break; | ||
case 12: case 13: case 20: | ||
function location() { | ||
return peg$computeLocation(peg$savedPos, peg$currPos); | ||
} | ||
this.$ = $$[$0]; | ||
break; | ||
case 14: case 15: | ||
function expected(description) { | ||
throw peg$buildException( | ||
null, | ||
[{ type: "other", description: description }], | ||
input.substring(peg$savedPos, peg$currPos), | ||
peg$computeLocation(peg$savedPos, peg$currPos) | ||
); | ||
} | ||
this.$ = new Filter($$[$0-2],$$[$0-1],$$[$0]); | ||
break; | ||
case 16: | ||
function error(message) { | ||
throw peg$buildException( | ||
message, | ||
null, | ||
input.substring(peg$savedPos, peg$currPos), | ||
peg$computeLocation(peg$savedPos, peg$currPos) | ||
); | ||
} | ||
this.$ = '~='; | ||
break; | ||
case 17: | ||
function peg$computePosDetails(pos) { | ||
var details = peg$posDetailsCache[pos], | ||
p, ch; | ||
this.$ = '>='; | ||
break; | ||
case 18: | ||
if (details) { | ||
return details; | ||
} else { | ||
p = pos - 1; | ||
while (!peg$posDetailsCache[p]) { | ||
p--; | ||
} | ||
this.$ = '<='; | ||
break; | ||
case 19: | ||
details = peg$posDetailsCache[p]; | ||
details = { | ||
line: details.line, | ||
column: details.column, | ||
seenCR: details.seenCR | ||
}; | ||
this.$ = '='; | ||
break; | ||
case 21: | ||
while (p < pos) { | ||
ch = input.charAt(p); | ||
if (ch === "\n") { | ||
if (!details.seenCR) { details.line++; } | ||
details.column = 1; | ||
details.seenCR = false; | ||
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { | ||
details.line++; | ||
details.column = 1; | ||
details.seenCR = true; | ||
} else { | ||
details.column++; | ||
details.seenCR = false; | ||
} | ||
this.$ = $$[$0-1] + $$[$0]; | ||
break; | ||
} | ||
}, | ||
table: [{3:1,4:2,5:$V0},{1:[3]},{1:[2,1]},{6:4,8:5,9:6,10:7,11:8,12:[1,9],14:[1,10],15:[1,11],16:12,17:[1,13],18:[1,14]},{7:[1,15]},{7:[2,3]},{7:[2,4]},{7:[2,5]},{7:[2,6]},{4:17,5:$V0,13:16},{4:17,5:$V0,13:18},{4:19,5:$V0},{7:[2,12]},{7:[2,13]},{19:20,21:21,22:[1,22],23:[1,23],24:[1,24],25:[1,25]},o([1,5,7],[2,2]),{7:[2,7]},{4:17,5:$V0,7:[2,10],13:26},{7:[2,8]},{7:[2,9]},{20:27,26:$V1},{20:29,26:$V1},{26:[2,16]},{26:[2,17]},{26:[2,18]},{26:[2,19]},{7:[2,11]},{7:[2,14],26:$V2},o($V3,[2,20]),{7:[2,15],26:$V2},o($V3,[2,21])], | ||
defaultActions: {2:[2,1],5:[2,3],6:[2,4],7:[2,5],8:[2,6],12:[2,12],13:[2,13],16:[2,7],18:[2,8],19:[2,9],22:[2,16],23:[2,17],24:[2,18],25:[2,19],26:[2,11]}, | ||
parseError: function parseError(str, hash) { | ||
if (hash.recoverable) { | ||
this.trace(str); | ||
} else { | ||
throw new Error(str); | ||
p++; | ||
} | ||
peg$posDetailsCache[pos] = details; | ||
return details; | ||
} | ||
} | ||
}, | ||
parse: function parse(input) { | ||
var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; | ||
var args = lstack.slice.call(arguments, 1); | ||
var lexer = Object.create(this.lexer); | ||
var sharedState = { yy: {} }; | ||
for (var k in this.yy) { | ||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) { | ||
sharedState.yy[k] = this.yy[k]; | ||
function peg$computeLocation(startPos, endPos) { | ||
var startPosDetails = peg$computePosDetails(startPos), | ||
endPosDetails = peg$computePosDetails(endPos); | ||
return { | ||
start: { | ||
offset: startPos, | ||
line: startPosDetails.line, | ||
column: startPosDetails.column | ||
}, | ||
end: { | ||
offset: endPos, | ||
line: endPosDetails.line, | ||
column: endPosDetails.column | ||
} | ||
}; | ||
} | ||
lexer.setInput(input, sharedState.yy); | ||
sharedState.yy.lexer = lexer; | ||
sharedState.yy.parser = this; | ||
if (typeof lexer.yylloc == 'undefined') { | ||
lexer.yylloc = {}; | ||
function peg$fail(expected) { | ||
if (peg$currPos < peg$maxFailPos) { return; } | ||
if (peg$currPos > peg$maxFailPos) { | ||
peg$maxFailPos = peg$currPos; | ||
peg$maxFailExpected = []; | ||
} | ||
peg$maxFailExpected.push(expected); | ||
} | ||
var yyloc = lexer.yylloc; | ||
lstack.push(yyloc); | ||
var ranges = lexer.options && lexer.options.ranges; | ||
if (typeof sharedState.yy.parseError === 'function') { | ||
this.parseError = sharedState.yy.parseError; | ||
} else { | ||
this.parseError = Object.getPrototypeOf(this).parseError; | ||
function peg$buildException(message, expected, found, location) { | ||
function cleanupExpected(expected) { | ||
var i = 1; | ||
expected.sort(function(a, b) { | ||
if (a.description < b.description) { | ||
return -1; | ||
} else if (a.description > b.description) { | ||
return 1; | ||
} else { | ||
return 0; | ||
} | ||
}); | ||
while (i < expected.length) { | ||
if (expected[i - 1] === expected[i]) { | ||
expected.splice(i, 1); | ||
} else { | ||
i++; | ||
} | ||
} | ||
} | ||
function buildMessage(expected, found) { | ||
function stringEscape(s) { | ||
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } | ||
return s | ||
.replace(/\\/g, '\\\\') | ||
.replace(/"/g, '\\"') | ||
.replace(/\x08/g, '\\b') | ||
.replace(/\t/g, '\\t') | ||
.replace(/\n/g, '\\n') | ||
.replace(/\f/g, '\\f') | ||
.replace(/\r/g, '\\r') | ||
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) | ||
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) | ||
.replace(/[\u0100-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) | ||
.replace(/[\u1000-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); | ||
} | ||
var expectedDescs = new Array(expected.length), | ||
expectedDesc, foundDesc, i; | ||
for (i = 0; i < expected.length; i++) { | ||
expectedDescs[i] = expected[i].description; | ||
} | ||
expectedDesc = expected.length > 1 | ||
? expectedDescs.slice(0, -1).join(", ") | ||
+ " or " | ||
+ expectedDescs[expected.length - 1] | ||
: expectedDescs[0]; | ||
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; | ||
return "Expected " + expectedDesc + " but " + foundDesc + " found."; | ||
} | ||
if (expected !== null) { | ||
cleanupExpected(expected); | ||
} | ||
return new peg$SyntaxError( | ||
message !== null ? message : buildMessage(expected, found), | ||
expected, | ||
found, | ||
location | ||
); | ||
} | ||
function popStack(n) { | ||
stack.length = stack.length - 2 * n; | ||
vstack.length = vstack.length - n; | ||
lstack.length = lstack.length - n; | ||
function peg$parsestart() { | ||
var s0, s1; | ||
s0 = peg$currPos; | ||
s1 = peg$parsefilter(); | ||
if (s1 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c0(s1); | ||
} | ||
s0 = s1; | ||
return s0; | ||
} | ||
_token_stack: | ||
function lex() { | ||
var token; | ||
token = lexer.lex() || EOF; | ||
if (typeof token !== 'number') { | ||
token = self.symbols_[token] || token; | ||
} | ||
return token; | ||
} | ||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; | ||
while (true) { | ||
state = stack[stack.length - 1]; | ||
if (this.defaultActions[state]) { | ||
action = this.defaultActions[state]; | ||
function peg$parsefilter() { | ||
var s0, s1, s2, s3, s4, s5, s6; | ||
s0 = peg$currPos; | ||
s1 = []; | ||
s2 = peg$parseFILL(); | ||
while (s2 !== peg$FAILED) { | ||
s1.push(s2); | ||
s2 = peg$parseFILL(); | ||
} | ||
if (s1 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 40) { | ||
s2 = peg$c1; | ||
peg$currPos++; | ||
} else { | ||
if (symbol === null || typeof symbol == 'undefined') { | ||
symbol = lex(); | ||
} | ||
action = table[state] && table[state][symbol]; | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c2); } | ||
} | ||
if (typeof action === 'undefined' || !action.length || !action[0]) { | ||
var errStr = ''; | ||
expected = []; | ||
for (p in table[state]) { | ||
if (this.terminals_[p] && p > TERROR) { | ||
expected.push('\'' + this.terminals_[p] + '\''); | ||
} | ||
} | ||
if (lexer.showPosition) { | ||
errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; | ||
} else { | ||
errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); | ||
} | ||
this.parseError(errStr, { | ||
text: lexer.match, | ||
token: this.terminals_[symbol] || symbol, | ||
line: lexer.yylineno, | ||
loc: yyloc, | ||
expected: expected | ||
}); | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parsefiltercomp(); | ||
if (s3 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 41) { | ||
s4 = peg$c3; | ||
peg$currPos++; | ||
} else { | ||
s4 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c4); } | ||
} | ||
if (action[0] instanceof Array && action.length > 1) { | ||
throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); | ||
} | ||
switch (action[0]) { | ||
case 1: | ||
stack.push(symbol); | ||
vstack.push(lexer.yytext); | ||
lstack.push(lexer.yylloc); | ||
stack.push(action[1]); | ||
symbol = null; | ||
if (!preErrorSymbol) { | ||
yyleng = lexer.yyleng; | ||
yytext = lexer.yytext; | ||
yylineno = lexer.yylineno; | ||
yyloc = lexer.yylloc; | ||
if (recovering > 0) { | ||
recovering--; | ||
} | ||
if (s4 !== peg$FAILED) { | ||
s5 = []; | ||
s6 = peg$parseFILL(); | ||
while (s6 !== peg$FAILED) { | ||
s5.push(s6); | ||
s6 = peg$parseFILL(); | ||
} | ||
if (s5 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c0(s3); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
symbol = preErrorSymbol; | ||
preErrorSymbol = null; | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
break; | ||
case 2: | ||
len = this.productions_[action[1]][1]; | ||
yyval.$ = vstack[vstack.length - len]; | ||
yyval._$ = { | ||
first_line: lstack[lstack.length - (len || 1)].first_line, | ||
last_line: lstack[lstack.length - 1].last_line, | ||
first_column: lstack[lstack.length - (len || 1)].first_column, | ||
last_column: lstack[lstack.length - 1].last_column | ||
}; | ||
if (ranges) { | ||
yyval._$.range = [ | ||
lstack[lstack.length - (len || 1)].range[0], | ||
lstack[lstack.length - 1].range[1] | ||
]; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
return s0; | ||
} | ||
function peg$parsefiltercomp() { | ||
var s0; | ||
s0 = peg$parseand(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parseor(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parsenot(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parseitem(); | ||
} | ||
} | ||
} | ||
return s0; | ||
} | ||
function peg$parseand() { | ||
var s0, s1, s2, s3, s4, s5; | ||
s0 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 38) { | ||
s1 = peg$c5; | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c6); } | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s2 = []; | ||
s3 = peg$parseFILL(); | ||
while (s3 !== peg$FAILED) { | ||
s2.push(s3); | ||
s3 = peg$parseFILL(); | ||
} | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parsefilterlist(); | ||
if (s3 !== peg$FAILED) { | ||
s4 = []; | ||
s5 = peg$parseFILL(); | ||
while (s5 !== peg$FAILED) { | ||
s4.push(s5); | ||
s5 = peg$parseFILL(); | ||
} | ||
r = this.performAction.apply(yyval, [ | ||
yytext, | ||
yyleng, | ||
yylineno, | ||
sharedState.yy, | ||
action[1], | ||
vstack, | ||
lstack | ||
].concat(args)); | ||
if (typeof r !== 'undefined') { | ||
return r; | ||
if (s4 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c7(s3); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
if (len) { | ||
stack = stack.slice(0, -1 * len * 2); | ||
vstack = vstack.slice(0, -1 * len); | ||
lstack = lstack.slice(0, -1 * len); | ||
} | ||
stack.push(this.productions_[action[1]][0]); | ||
vstack.push(yyval.$); | ||
lstack.push(yyval._$); | ||
newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; | ||
stack.push(newState); | ||
break; | ||
case 3: | ||
return true; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
return s0; | ||
} | ||
return true; | ||
}}; | ||
var Filter = require('./filter'); | ||
/* generated by jison-lex 0.3.4 */ | ||
var lexer = (function(){ | ||
var lexer = ({ | ||
function peg$parseor() { | ||
var s0, s1, s2, s3, s4, s5; | ||
EOF:1, | ||
parseError:function parseError(str, hash) { | ||
if (this.yy.parser) { | ||
this.yy.parser.parseError(str, hash); | ||
s0 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 124) { | ||
s1 = peg$c8; | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c9); } | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s2 = []; | ||
s3 = peg$parseFILL(); | ||
while (s3 !== peg$FAILED) { | ||
s2.push(s3); | ||
s3 = peg$parseFILL(); | ||
} | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parsefilterlist(); | ||
if (s3 !== peg$FAILED) { | ||
s4 = []; | ||
s5 = peg$parseFILL(); | ||
while (s5 !== peg$FAILED) { | ||
s4.push(s5); | ||
s5 = peg$parseFILL(); | ||
} | ||
if (s4 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c10(s3); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
throw new Error(str); | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
}, | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
// resets the lexer, sets new input | ||
setInput:function (input, yy) { | ||
this.yy = yy || this.yy || {}; | ||
this._input = input; | ||
this._more = this._backtrack = this.done = false; | ||
this.yylineno = this.yyleng = 0; | ||
this.yytext = this.matched = this.match = ''; | ||
this.conditionStack = ['INITIAL']; | ||
this.yylloc = { | ||
first_line: 1, | ||
first_column: 0, | ||
last_line: 1, | ||
last_column: 0 | ||
}; | ||
if (this.options.ranges) { | ||
this.yylloc.range = [0,0]; | ||
return s0; | ||
} | ||
function peg$parsenot() { | ||
var s0, s1, s2, s3, s4, s5; | ||
s0 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 33) { | ||
s1 = peg$c11; | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c12); } | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s2 = []; | ||
s3 = peg$parseFILL(); | ||
while (s3 !== peg$FAILED) { | ||
s2.push(s3); | ||
s3 = peg$parseFILL(); | ||
} | ||
this.offset = 0; | ||
return this; | ||
}, | ||
// consumes and returns one char from the input | ||
input:function () { | ||
var ch = this._input[0]; | ||
this.yytext += ch; | ||
this.yyleng++; | ||
this.offset++; | ||
this.match += ch; | ||
this.matched += ch; | ||
var lines = ch.match(/(?:\r\n?|\n).*/g); | ||
if (lines) { | ||
this.yylineno++; | ||
this.yylloc.last_line++; | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parsefilter(); | ||
if (s3 !== peg$FAILED) { | ||
s4 = []; | ||
s5 = peg$parseFILL(); | ||
while (s5 !== peg$FAILED) { | ||
s4.push(s5); | ||
s5 = peg$parseFILL(); | ||
} | ||
if (s4 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c13(s3); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
this.yylloc.last_column++; | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
if (this.options.ranges) { | ||
this.yylloc.range[1]++; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
return s0; | ||
} | ||
function peg$parsefilterlist() { | ||
var s0, s1; | ||
s0 = []; | ||
s1 = peg$parsefilter(); | ||
if (s1 !== peg$FAILED) { | ||
while (s1 !== peg$FAILED) { | ||
s0.push(s1); | ||
s1 = peg$parsefilter(); | ||
} | ||
} else { | ||
s0 = peg$FAILED; | ||
} | ||
this._input = this._input.slice(1); | ||
return ch; | ||
}, | ||
return s0; | ||
} | ||
// unshifts one char (or a string) into the input | ||
unput:function (ch) { | ||
var len = ch.length; | ||
var lines = ch.split(/(?:\r\n?|\n)/g); | ||
function peg$parseitem() { | ||
var s0; | ||
this._input = ch + this._input; | ||
this.yytext = this.yytext.substr(0, this.yytext.length - len); | ||
//this.yyleng -= len; | ||
this.offset -= len; | ||
var oldLines = this.match.split(/(?:\r\n?|\n)/g); | ||
this.match = this.match.substr(0, this.match.length - 1); | ||
this.matched = this.matched.substr(0, this.matched.length - 1); | ||
s0 = peg$parsesubstring(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parsesimple(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parsepresent(); | ||
} | ||
} | ||
if (lines.length - 1) { | ||
this.yylineno -= lines.length - 1; | ||
return s0; | ||
} | ||
function peg$parsesimple() { | ||
var s0, s1, s2, s3; | ||
s0 = peg$currPos; | ||
s1 = peg$parseAttributeDescription(); | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$parsefiltertype(); | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$parsevalue(); | ||
if (s3 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c14(s1, s2, s3); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
var r = this.yylloc.range; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
this.yylloc = { | ||
first_line: this.yylloc.first_line, | ||
last_line: this.yylineno + 1, | ||
first_column: this.yylloc.first_column, | ||
last_column: lines ? | ||
(lines.length === oldLines.length ? this.yylloc.first_column : 0) | ||
+ oldLines[oldLines.length - lines.length].length - lines[0].length : | ||
this.yylloc.first_column - len | ||
}; | ||
return s0; | ||
} | ||
if (this.options.ranges) { | ||
this.yylloc.range = [r[0], r[0] + this.yyleng - len]; | ||
function peg$parsefiltertype() { | ||
var s0; | ||
s0 = peg$parseequal(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parseapprox(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parsegreater(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parseless(); | ||
} | ||
} | ||
this.yyleng = this.yytext.length; | ||
return this; | ||
}, | ||
} | ||
// When called from action, caches matched text and appends it on next action | ||
more:function () { | ||
this._more = true; | ||
return this; | ||
}, | ||
return s0; | ||
} | ||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. | ||
reject:function () { | ||
if (this.options.backtrack_lexer) { | ||
this._backtrack = true; | ||
function peg$parseequal() { | ||
var s0; | ||
if (input.charCodeAt(peg$currPos) === 61) { | ||
s0 = peg$c15; | ||
peg$currPos++; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c16); } | ||
} | ||
return s0; | ||
} | ||
function peg$parseapprox() { | ||
var s0; | ||
if (input.substr(peg$currPos, 2) === peg$c17) { | ||
s0 = peg$c17; | ||
peg$currPos += 2; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c18); } | ||
} | ||
return s0; | ||
} | ||
function peg$parsegreater() { | ||
var s0; | ||
if (input.substr(peg$currPos, 2) === peg$c19) { | ||
s0 = peg$c19; | ||
peg$currPos += 2; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c20); } | ||
} | ||
return s0; | ||
} | ||
function peg$parseless() { | ||
var s0; | ||
if (input.substr(peg$currPos, 2) === peg$c21) { | ||
s0 = peg$c21; | ||
peg$currPos += 2; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c22); } | ||
} | ||
return s0; | ||
} | ||
function peg$parsepresent() { | ||
var s0, s1, s2; | ||
s0 = peg$currPos; | ||
s1 = peg$parseAttributeDescription(); | ||
if (s1 !== peg$FAILED) { | ||
if (input.substr(peg$currPos, 2) === peg$c23) { | ||
s2 = peg$c23; | ||
peg$currPos += 2; | ||
} else { | ||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { | ||
text: "", | ||
token: null, | ||
line: this.yylineno | ||
}); | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c24); } | ||
} | ||
return this; | ||
}, | ||
if (s2 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c25(s1); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
// retain first n characters of the match | ||
less:function (n) { | ||
this.unput(this.match.slice(n)); | ||
}, | ||
return s0; | ||
} | ||
// displays already matched input, i.e. for error messages | ||
pastInput:function () { | ||
var past = this.matched.substr(0, this.matched.length - this.match.length); | ||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); | ||
}, | ||
function peg$parsesubstring() { | ||
var s0, s1, s2, s3, s4, s5, s6, s7; | ||
// displays upcoming input, i.e. for error messages | ||
upcomingInput:function () { | ||
var next = this.match; | ||
if (next.length < 20) { | ||
next += this._input.substr(0, 20-next.length); | ||
s0 = peg$currPos; | ||
s1 = peg$parseAttributeDescription(); | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$parseequal(); | ||
if (s2 !== peg$FAILED) { | ||
s3 = peg$currPos; | ||
s4 = peg$currPos; | ||
s5 = peg$parsevalue(); | ||
if (s5 === peg$FAILED) { | ||
s5 = null; | ||
} | ||
if (s5 !== peg$FAILED) { | ||
s6 = peg$parseany(); | ||
if (s6 !== peg$FAILED) { | ||
s7 = peg$parsevalue(); | ||
if (s7 === peg$FAILED) { | ||
s7 = null; | ||
} | ||
if (s7 !== peg$FAILED) { | ||
s5 = [s5, s6, s7]; | ||
s4 = s5; | ||
} else { | ||
peg$currPos = s4; | ||
s4 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s4; | ||
s4 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s4; | ||
s4 = peg$FAILED; | ||
} | ||
if (s4 !== peg$FAILED) { | ||
s3 = input.substring(s3, peg$currPos); | ||
} else { | ||
s3 = s4; | ||
} | ||
if (s3 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c26(s1, s3); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); | ||
}, | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
// displays the character position where the lexing error occurred, i.e. for error messages | ||
showPosition:function () { | ||
var pre = this.pastInput(); | ||
var c = new Array(pre.length + 1).join("-"); | ||
return pre + this.upcomingInput() + "\n" + c + "^"; | ||
}, | ||
return s0; | ||
} | ||
// test the lexed token: return FALSE when not a match, otherwise return token | ||
test_match:function (match, indexed_rule) { | ||
var token, | ||
lines, | ||
backup; | ||
function peg$parseany() { | ||
var s0, s1, s2, s3, s4, s5; | ||
if (this.options.backtrack_lexer) { | ||
// save context | ||
backup = { | ||
yylineno: this.yylineno, | ||
yylloc: { | ||
first_line: this.yylloc.first_line, | ||
last_line: this.last_line, | ||
first_column: this.yylloc.first_column, | ||
last_column: this.yylloc.last_column | ||
}, | ||
yytext: this.yytext, | ||
match: this.match, | ||
matches: this.matches, | ||
matched: this.matched, | ||
yyleng: this.yyleng, | ||
offset: this.offset, | ||
_more: this._more, | ||
_input: this._input, | ||
yy: this.yy, | ||
conditionStack: this.conditionStack.slice(0), | ||
done: this.done | ||
}; | ||
if (this.options.ranges) { | ||
backup.yylloc.range = this.yylloc.range.slice(0); | ||
s0 = peg$currPos; | ||
s1 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 42) { | ||
s2 = peg$c27; | ||
peg$currPos++; | ||
} else { | ||
s2 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c28); } | ||
} | ||
if (s2 !== peg$FAILED) { | ||
s1 = input.substring(s1, peg$currPos); | ||
} else { | ||
s1 = s2; | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s2 = []; | ||
s3 = peg$currPos; | ||
s4 = peg$parsevalue(); | ||
if (s4 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 42) { | ||
s5 = peg$c27; | ||
peg$currPos++; | ||
} else { | ||
s5 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c28); } | ||
} | ||
if (s5 !== peg$FAILED) { | ||
s4 = [s4, s5]; | ||
s3 = s4; | ||
} else { | ||
peg$currPos = s3; | ||
s3 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s3; | ||
s3 = peg$FAILED; | ||
} | ||
while (s3 !== peg$FAILED) { | ||
s2.push(s3); | ||
s3 = peg$currPos; | ||
s4 = peg$parsevalue(); | ||
if (s4 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 42) { | ||
s5 = peg$c27; | ||
peg$currPos++; | ||
} else { | ||
s5 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c28); } | ||
} | ||
if (s5 !== peg$FAILED) { | ||
s4 = [s4, s5]; | ||
s3 = s4; | ||
} else { | ||
peg$currPos = s3; | ||
s3 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s3; | ||
s3 = peg$FAILED; | ||
} | ||
} | ||
if (s2 !== peg$FAILED) { | ||
s1 = [s1, s2]; | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
lines = match[0].match(/(?:\r\n?|\n).*/g); | ||
if (lines) { | ||
this.yylineno += lines.length; | ||
return s0; | ||
} | ||
function peg$parsevalue() { | ||
var s0, s1, s2; | ||
s0 = peg$currPos; | ||
s1 = []; | ||
s2 = peg$parseAttributeValue(); | ||
if (s2 !== peg$FAILED) { | ||
while (s2 !== peg$FAILED) { | ||
s1.push(s2); | ||
s2 = peg$parseAttributeValue(); | ||
} | ||
this.yylloc = { | ||
first_line: this.yylloc.last_line, | ||
last_line: this.yylineno + 1, | ||
first_column: this.yylloc.last_column, | ||
last_column: lines ? | ||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : | ||
this.yylloc.last_column + match[0].length | ||
}; | ||
this.yytext += match[0]; | ||
this.match += match[0]; | ||
this.matches = match; | ||
this.yyleng = this.yytext.length; | ||
if (this.options.ranges) { | ||
this.yylloc.range = [this.offset, this.offset += this.yyleng]; | ||
} else { | ||
s1 = peg$FAILED; | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s0 = input.substring(s0, peg$currPos); | ||
} else { | ||
s0 = s1; | ||
} | ||
return s0; | ||
} | ||
function peg$parseAttributeDescription() { | ||
var s0, s1, s2, s3, s4; | ||
peg$silentFails++; | ||
s0 = peg$currPos; | ||
s1 = peg$parseAttributeType(); | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 59) { | ||
s3 = peg$c30; | ||
peg$currPos++; | ||
} else { | ||
s3 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c31); } | ||
} | ||
this._more = false; | ||
this._backtrack = false; | ||
this._input = this._input.slice(match[0].length); | ||
this.matched += match[0]; | ||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); | ||
if (this.done && this._input) { | ||
this.done = false; | ||
if (s3 !== peg$FAILED) { | ||
s4 = peg$parseoptions(); | ||
if (s4 !== peg$FAILED) { | ||
s3 = [s3, s4]; | ||
s2 = s3; | ||
} else { | ||
peg$currPos = s2; | ||
s2 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s2; | ||
s2 = peg$FAILED; | ||
} | ||
if (token) { | ||
return token; | ||
} else if (this._backtrack) { | ||
// recover context | ||
for (var k in backup) { | ||
this[k] = backup[k]; | ||
} | ||
return false; // rule action called reject() implying the next rule should be tested instead. | ||
if (s2 === peg$FAILED) { | ||
s2 = null; | ||
} | ||
return false; | ||
}, | ||
if (s2 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c32(s1, s2); | ||
s0 = s1; | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c29); } | ||
} | ||
// return next match in input | ||
next:function () { | ||
if (this.done) { | ||
return this.EOF; | ||
return s0; | ||
} | ||
function peg$parseAttributeType() { | ||
var s0, s1, s2, s3, s4, s5; | ||
peg$silentFails++; | ||
s0 = peg$currPos; | ||
s1 = peg$parseLDAP_OID(); | ||
if (s1 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c34(s1); | ||
} | ||
s0 = s1; | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$currPos; | ||
s1 = peg$currPos; | ||
s2 = peg$currPos; | ||
s3 = peg$parseALPHA(); | ||
if (s3 !== peg$FAILED) { | ||
s4 = []; | ||
s5 = peg$parseAttrTypeChars(); | ||
while (s5 !== peg$FAILED) { | ||
s4.push(s5); | ||
s5 = peg$parseAttrTypeChars(); | ||
} | ||
if (s4 !== peg$FAILED) { | ||
s3 = [s3, s4]; | ||
s2 = s3; | ||
} else { | ||
peg$currPos = s2; | ||
s2 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s2; | ||
s2 = peg$FAILED; | ||
} | ||
if (!this._input) { | ||
this.done = true; | ||
if (s2 !== peg$FAILED) { | ||
s1 = input.substring(s1, peg$currPos); | ||
} else { | ||
s1 = s2; | ||
} | ||
if (s1 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c35(s1); | ||
} | ||
s0 = s1; | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c33); } | ||
} | ||
var token, | ||
match, | ||
tempMatch, | ||
index; | ||
if (!this._more) { | ||
this.yytext = ''; | ||
this.match = ''; | ||
return s0; | ||
} | ||
function peg$parseAttrTypeChars() { | ||
var s0, s1; | ||
peg$silentFails++; | ||
s0 = peg$parseALPHA(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parseDIGIT(); | ||
if (s0 === peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 45) { | ||
s0 = peg$c37; | ||
peg$currPos++; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c38); } | ||
} | ||
} | ||
var rules = this._currentRules(); | ||
for (var i = 0; i < rules.length; i++) { | ||
tempMatch = this._input.match(this.rules[rules[i]]); | ||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { | ||
match = tempMatch; | ||
index = i; | ||
if (this.options.backtrack_lexer) { | ||
token = this.test_match(tempMatch, rules[i]); | ||
if (token !== false) { | ||
return token; | ||
} else if (this._backtrack) { | ||
match = false; | ||
continue; // rule action called reject() implying a rule MISmatch. | ||
} else { | ||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) | ||
return false; | ||
} | ||
} else if (!this.options.flex) { | ||
break; | ||
} | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c36); } | ||
} | ||
return s0; | ||
} | ||
function peg$parseLDAP_OID() { | ||
var s0, s1, s2, s3, s4, s5, s6, s7; | ||
peg$silentFails++; | ||
s0 = peg$currPos; | ||
s1 = peg$currPos; | ||
s2 = []; | ||
s3 = peg$parseDIGIT(); | ||
if (s3 !== peg$FAILED) { | ||
while (s3 !== peg$FAILED) { | ||
s2.push(s3); | ||
s3 = peg$parseDIGIT(); | ||
} | ||
} else { | ||
s2 = peg$FAILED; | ||
} | ||
if (s2 !== peg$FAILED) { | ||
s3 = []; | ||
s4 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 46) { | ||
s5 = peg$c40; | ||
peg$currPos++; | ||
} else { | ||
s5 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c41); } | ||
} | ||
if (s5 !== peg$FAILED) { | ||
s6 = []; | ||
s7 = peg$parseDIGIT(); | ||
if (s7 !== peg$FAILED) { | ||
while (s7 !== peg$FAILED) { | ||
s6.push(s7); | ||
s7 = peg$parseDIGIT(); | ||
} | ||
} else { | ||
s6 = peg$FAILED; | ||
} | ||
if (s6 !== peg$FAILED) { | ||
s5 = [s5, s6]; | ||
s4 = s5; | ||
} else { | ||
peg$currPos = s4; | ||
s4 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s4; | ||
s4 = peg$FAILED; | ||
} | ||
if (match) { | ||
token = this.test_match(match, rules[index]); | ||
if (token !== false) { | ||
return token; | ||
while (s4 !== peg$FAILED) { | ||
s3.push(s4); | ||
s4 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 46) { | ||
s5 = peg$c40; | ||
peg$currPos++; | ||
} else { | ||
s5 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c41); } | ||
} | ||
if (s5 !== peg$FAILED) { | ||
s6 = []; | ||
s7 = peg$parseDIGIT(); | ||
if (s7 !== peg$FAILED) { | ||
while (s7 !== peg$FAILED) { | ||
s6.push(s7); | ||
s7 = peg$parseDIGIT(); | ||
} | ||
} else { | ||
s6 = peg$FAILED; | ||
} | ||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) | ||
return false; | ||
if (s6 !== peg$FAILED) { | ||
s5 = [s5, s6]; | ||
s4 = s5; | ||
} else { | ||
peg$currPos = s4; | ||
s4 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s4; | ||
s4 = peg$FAILED; | ||
} | ||
} | ||
if (this._input === "") { | ||
return this.EOF; | ||
if (s3 !== peg$FAILED) { | ||
s2 = [s2, s3]; | ||
s1 = s2; | ||
} else { | ||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { | ||
text: "", | ||
token: null, | ||
line: this.yylineno | ||
}); | ||
peg$currPos = s1; | ||
s1 = peg$FAILED; | ||
} | ||
}, | ||
} else { | ||
peg$currPos = s1; | ||
s1 = peg$FAILED; | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s0 = input.substring(s0, peg$currPos); | ||
} else { | ||
s0 = s1; | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c39); } | ||
} | ||
// return next match that has a token | ||
lex:function lex() { | ||
var r = this.next(); | ||
if (r) { | ||
return r; | ||
return s0; | ||
} | ||
function peg$parseoptions() { | ||
var s0, s1, s2, s3, s4; | ||
peg$silentFails++; | ||
s0 = peg$currPos; | ||
s1 = peg$currPos; | ||
s2 = peg$parseoption(); | ||
if (s2 !== peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 59) { | ||
s3 = peg$c30; | ||
peg$currPos++; | ||
} else { | ||
return this.lex(); | ||
s3 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c31); } | ||
} | ||
}, | ||
if (s3 !== peg$FAILED) { | ||
s4 = peg$parseoptions(); | ||
if (s4 !== peg$FAILED) { | ||
s2 = [s2, s3, s4]; | ||
s1 = s2; | ||
} else { | ||
peg$currPos = s1; | ||
s1 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s1; | ||
s1 = peg$FAILED; | ||
} | ||
} else { | ||
peg$currPos = s1; | ||
s1 = peg$FAILED; | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s0 = input.substring(s0, peg$currPos); | ||
} else { | ||
s0 = s1; | ||
} | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$currPos; | ||
s1 = peg$parseoption(); | ||
if (s1 !== peg$FAILED) { | ||
s0 = input.substring(s0, peg$currPos); | ||
} else { | ||
s0 = s1; | ||
} | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c42); } | ||
} | ||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) | ||
begin:function begin(condition) { | ||
this.conditionStack.push(condition); | ||
}, | ||
return s0; | ||
} | ||
// pop the previously active lexer condition state off the condition stack | ||
popState:function popState() { | ||
var n = this.conditionStack.length - 1; | ||
if (n > 0) { | ||
return this.conditionStack.pop(); | ||
function peg$parseoption() { | ||
var s0, s1; | ||
peg$silentFails++; | ||
s0 = []; | ||
s1 = peg$parseAttrTypeChars(); | ||
if (s1 !== peg$FAILED) { | ||
while (s1 !== peg$FAILED) { | ||
s0.push(s1); | ||
s1 = peg$parseAttrTypeChars(); | ||
} | ||
} else { | ||
s0 = peg$FAILED; | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c43); } | ||
} | ||
return s0; | ||
} | ||
function peg$parseAttributeValue() { | ||
var s0; | ||
s0 = peg$parseEscapedCharacter(); | ||
if (s0 === peg$FAILED) { | ||
if (peg$c44.test(input.charAt(peg$currPos))) { | ||
s0 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
return this.conditionStack[0]; | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c45); } | ||
} | ||
}, | ||
} | ||
// produce the lexer rule set which is active for the currently active lexer condition state | ||
_currentRules:function _currentRules() { | ||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { | ||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; | ||
return s0; | ||
} | ||
function peg$parseEscapedCharacter() { | ||
var s0, s1, s2; | ||
s0 = peg$currPos; | ||
if (input.charCodeAt(peg$currPos) === 92) { | ||
s1 = peg$c46; | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c47); } | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s2 = peg$parseASCII_VALUE(); | ||
if (s2 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c48(s2); | ||
s0 = s1; | ||
} else { | ||
return this.conditions["INITIAL"].rules; | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
}, | ||
} else { | ||
peg$currPos = s0; | ||
s0 = peg$FAILED; | ||
} | ||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available | ||
topState:function topState(n) { | ||
n = this.conditionStack.length - 1 - Math.abs(n || 0); | ||
if (n >= 0) { | ||
return this.conditionStack[n]; | ||
return s0; | ||
} | ||
function peg$parseASCII_VALUE() { | ||
var s0, s1, s2, s3, s4; | ||
s0 = peg$currPos; | ||
s1 = peg$currPos; | ||
s2 = peg$currPos; | ||
s3 = peg$parseHEX_CHAR(); | ||
if (s3 !== peg$FAILED) { | ||
s4 = peg$parseHEX_CHAR(); | ||
if (s4 !== peg$FAILED) { | ||
s3 = [s3, s4]; | ||
s2 = s3; | ||
} else { | ||
return "INITIAL"; | ||
peg$currPos = s2; | ||
s2 = peg$FAILED; | ||
} | ||
}, | ||
} else { | ||
peg$currPos = s2; | ||
s2 = peg$FAILED; | ||
} | ||
if (s2 !== peg$FAILED) { | ||
s1 = input.substring(s1, peg$currPos); | ||
} else { | ||
s1 = s2; | ||
} | ||
if (s1 !== peg$FAILED) { | ||
peg$savedPos = s0; | ||
s1 = peg$c49(s1); | ||
} | ||
s0 = s1; | ||
// alias for begin(condition) | ||
pushState:function pushState(condition) { | ||
this.begin(condition); | ||
}, | ||
return s0; | ||
} | ||
// return the number of states currently on the stack | ||
stateStackSize:function stateStackSize() { | ||
return this.conditionStack.length; | ||
}, | ||
options: {}, | ||
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { | ||
function peg$parseHEX_CHAR() { | ||
var s0; | ||
if (peg$c50.test(input.charAt(peg$currPos))) { | ||
s0 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c51); } | ||
} | ||
var YYSTATE=YY_START; | ||
switch($avoiding_name_collisions) { | ||
case 0:/**/ | ||
break; | ||
case 1: | ||
var upcoming = this.upcomingInput(); | ||
switch (upcoming[1]) { | ||
case '&': | ||
case '|': | ||
case '!': | ||
break; | ||
return s0; | ||
} | ||
default: | ||
this.begin("ATTR"); | ||
break; | ||
function peg$parseFILL() { | ||
var s0, s1; | ||
peg$silentFails++; | ||
s0 = peg$parseSPACE(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parseTAB(); | ||
if (s0 === peg$FAILED) { | ||
s0 = peg$parseSEP(); | ||
} | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c52); } | ||
} | ||
return s0; | ||
} | ||
return "LEFT_PAREN"; | ||
break; | ||
case 2:return "RIGHT_PAREN"; | ||
break; | ||
case 3:return "AND"; | ||
break; | ||
case 4:return "OR"; | ||
break; | ||
case 5:return "NOT"; | ||
break; | ||
case 6:this.begin("VALUE"); return "APPROX"; | ||
break; | ||
case 7:this.begin("VALUE"); return "GREATER_EQ"; | ||
break; | ||
case 8:this.begin("VALUE"); return "LESS_EQ"; | ||
break; | ||
case 9:this.begin("VALUE"); return "EQUAL"; | ||
break; | ||
case 10:return "STAR"; | ||
break; | ||
case 11:return "VALUE_STR"; | ||
break; | ||
case 12:return "VALUE_STR"; | ||
break; | ||
case 13:return "VALUE_STR"; | ||
break; | ||
case 14:return "VALUE_STR"; | ||
break; | ||
case 15:return "VALUE_STR"; | ||
break; | ||
case 16:this.popState(); return "RIGHT_PAREN"; | ||
break; | ||
case 17:this.popState(); return "ATTR_STR"; | ||
break; | ||
} | ||
}, | ||
rules: [/^(?:\s+)/,/^(?:\()/,/^(?:\))/,/^(?:&)/,/^(?:\|)/,/^(?:!)/,/^(?:~=)/,/^(?:>=)/,/^(?:<=)/,/^(?:=)/,/^(?:\*)/,/^(?:[^\\()]+)/,/^(?:\\\()/,/^(?:\\\))/,/^(?:\\\\)/,/^(?:\\\*)/,/^(?:\))/,/^(?:[^=><~()]+)/], | ||
conditions: {"VALUE":{"rules":[11,12,13,14,15,16],"inclusive":true},"ATTR":{"rules":[17],"inclusive":true},"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10],"inclusive":true}} | ||
}); | ||
return lexer; | ||
})(); | ||
parser.lexer = lexer; | ||
function Parser () { | ||
this.yy = {}; | ||
} | ||
Parser.prototype = parser;parser.Parser = Parser; | ||
return new Parser; | ||
})(); | ||
function peg$parseSPACE() { | ||
var s0, s1; | ||
if (typeof require !== 'undefined' && typeof exports !== 'undefined') { | ||
exports.parser = parser; | ||
exports.Parser = parser.Parser; | ||
exports.parse = function () { return parser.parse.apply(parser, arguments); }; | ||
exports.main = function commonjsMain(args) { | ||
if (!args[1]) { | ||
console.log('Usage: '+args[0]+' FILE'); | ||
process.exit(1); | ||
peg$silentFails++; | ||
if (peg$c54.test(input.charAt(peg$currPos))) { | ||
s0 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c55); } | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c53); } | ||
} | ||
return s0; | ||
} | ||
var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8"); | ||
return exports.parser.parse(source); | ||
}; | ||
if (typeof module !== 'undefined' && require.main === module) { | ||
exports.main(process.argv.slice(1)); | ||
} | ||
} | ||
function peg$parseTAB() { | ||
var s0, s1; | ||
peg$silentFails++; | ||
if (peg$c57.test(input.charAt(peg$currPos))) { | ||
s0 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c58); } | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c56); } | ||
} | ||
return s0; | ||
} | ||
function peg$parseDIGIT() { | ||
var s0, s1; | ||
peg$silentFails++; | ||
s0 = peg$currPos; | ||
if (peg$c60.test(input.charAt(peg$currPos))) { | ||
s1 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c61); } | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s0 = input.substring(s0, peg$currPos); | ||
} else { | ||
s0 = s1; | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c59); } | ||
} | ||
return s0; | ||
} | ||
function peg$parseALPHA() { | ||
var s0, s1; | ||
peg$silentFails++; | ||
s0 = peg$currPos; | ||
if (peg$c63.test(input.charAt(peg$currPos))) { | ||
s1 = input.charAt(peg$currPos); | ||
peg$currPos++; | ||
} else { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c64); } | ||
} | ||
if (s1 !== peg$FAILED) { | ||
s0 = input.substring(s0, peg$currPos); | ||
} else { | ||
s0 = s1; | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c62); } | ||
} | ||
return s0; | ||
} | ||
function peg$parseSEP() { | ||
var s0, s1; | ||
peg$silentFails++; | ||
if (input.substr(peg$currPos, 2) === peg$c66) { | ||
s0 = peg$c66; | ||
peg$currPos += 2; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c67); } | ||
} | ||
if (s0 === peg$FAILED) { | ||
if (input.charCodeAt(peg$currPos) === 10) { | ||
s0 = peg$c68; | ||
peg$currPos++; | ||
} else { | ||
s0 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c69); } | ||
} | ||
} | ||
peg$silentFails--; | ||
if (s0 === peg$FAILED) { | ||
s1 = peg$FAILED; | ||
if (peg$silentFails === 0) { peg$fail(peg$c65); } | ||
} | ||
return s0; | ||
} | ||
var fs = require('fs'); | ||
var Filter = require('./filter'); | ||
function base64_decode(val){ | ||
return (new Buffer(val,'base64')).toString(); | ||
} | ||
var _pluck = function(list,attr){ | ||
return list.map(function(cv){ | ||
return cv[attr]; | ||
}); | ||
}; | ||
peg$result = peg$startRuleFunction(); | ||
if (peg$result !== peg$FAILED && peg$currPos === input.length) { | ||
return peg$result; | ||
} else { | ||
if (peg$result !== peg$FAILED && peg$currPos < input.length) { | ||
peg$fail({ type: "end", description: "end of input" }); | ||
} | ||
throw peg$buildException( | ||
null, | ||
peg$maxFailExpected, | ||
peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, | ||
peg$maxFailPos < input.length | ||
? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) | ||
: peg$computeLocation(peg$maxFailPos, peg$maxFailPos) | ||
); | ||
} | ||
} | ||
return { | ||
SyntaxError: peg$SyntaxError, | ||
parse: peg$parse | ||
}; | ||
})(); |
{ | ||
"name": "ldap-filters", | ||
"version": "1.2.0", | ||
"version": "2.0.0", | ||
"description": "Library for generating, parsing, and evaluating LDAP filters", | ||
@@ -11,7 +11,8 @@ "main": "index.js", | ||
"chai": "*", | ||
"mocha": "*" | ||
"mocha": "*", | ||
"pegjs": "^0.9.0" | ||
}, | ||
"scripts": { | ||
"test": "mocha --timeout 5000 test/*js", | ||
"build": "jison lib/parser.jison -o lib/parser.js" | ||
"build": "node_modules/.bin/pegjs lib/parser.pegjs lib/parser.js" | ||
}, | ||
@@ -18,0 +19,0 @@ "repository": { |
@@ -48,3 +48,17 @@ node-ldap-filters | ||
* **.lte(value)** - tests if value is less than or equal `(attr<=value)` | ||
* **.raw(value)** - add an raw (escaped) attribute value `(attr=value)` | ||
**Added in 2.x** The `.raw` method is useful for building filters that | ||
have complex substring matches not suitable for `.startsWith()`, | ||
`.endsWith()`, or `.contains()` — however, you will need to escape | ||
any values that require escaping. This can be done using | ||
`Filter.escape()` like so: | ||
```javascript | ||
var match_value = '*' + Filter.escape('James (Jimmy)') + '*'; | ||
var filter = Filter.attribute('cn').raw(match_value); | ||
match_value == '*James \\28Jimmy\\29*' // true | ||
``` | ||
#### Aggregate methods | ||
@@ -130,3 +144,3 @@ | ||
There are three ways to run the tests: | ||
Tests can be run from npm or manually with mocha: | ||
@@ -143,21 +157,23 @@ ```bash | ||
The parser is built with **jison**. To re-build the parser, | ||
you must have jison installed globally. | ||
The parser is built with **pegjs**. To re-build the parser, | ||
you'll need the pegjs dev dependency installed. | ||
```bash | ||
# Install jison globally (need sudo?) | ||
npm install -g jison | ||
# Build parser with npm | ||
npm run build | ||
# Build manually with jison | ||
jison lib/parser.jison -o lib/parser.js | ||
# Build manually with pegjs | ||
# requires pegjs command to be availble (npm i -g pegjs) | ||
pegjs lib/parser.pegjs lib/parser.js | ||
``` | ||
## Credits | ||
## History | ||
The jison parser source was originally written by | ||
**Version 1.x and lower** used jison parser source originally written by | ||
[tantaman](https://github.com/tantaman/) found in the | ||
[DATS-DAP](https://github.com/tantaman/DATS-DAP) repository. | ||
**Version 2.x and above** are using an updated original pegjs-based parser. | ||
This version offers better RFC-compliance and improved matching for | ||
complicated substring matches and escaped characters, as well as addressing | ||
some bugs found in the previous jison parser. |
@@ -193,3 +193,21 @@ var should = require('chai').should(); | ||
it('matches substrings with multiple *\'s',function(done){ | ||
var filter = Filter.attribute('cn').raw('*jen* jo*e*'); | ||
expect(filter.match({ cn: 'Jenny Jones' })).to.be.true; | ||
done(); | ||
}); | ||
it('match embedded escape characters',function(done){ | ||
var filter = Filter.attribute('cn').raw('jenny\\2a \\28jones\\29 \\5c'); | ||
expect(filter.match({ cn: 'Jenny* (Jones) \\' })).to.be.true; | ||
done(); | ||
}); | ||
it('matches embedded escape characters with substring',function(done){ | ||
var filter = Filter.attribute('cn').raw('*jenny\\2a j*s*'); | ||
expect(filter.match({ cn: 'Jenny* Jones' })).to.be.true; | ||
done(); | ||
}); | ||
}); | ||
@@ -20,2 +20,9 @@ var should = require('chai').should(); | ||
it('parses a funny character value',function(done){ | ||
var filter = '(orgUnit=%)'; | ||
var parsed = Filter.parse(filter); | ||
parsed.toString().should.be.equal(filter); | ||
done(); | ||
}); | ||
it('parse more complex filter',function(done){ | ||
@@ -59,3 +66,15 @@ var filter = '(&(sn=smith)(gn=john)(!(age=5)))'; | ||
it('fails on incorrect format past first correct filter parse',function(done){ | ||
var filter = '(&(sn=smith))\n(uuid=3) f'; | ||
assert.throws(function(){Filter.parse(filter);}, Error); | ||
done(); | ||
}); | ||
it('allows whitespace',function(done){ | ||
var filter = ' (& (sn=smith) \n ) '; | ||
Filter.parse(filter).toString().should.be.equal('(&(sn=smith))'); | ||
done(); | ||
}); | ||
}); | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
71350
19
1955
177
1
3
1