123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- // Copyright 2014 Mark Cavage, Inc. All rights reserved.
- // Copyright 2014 Patrick Mooney. All rights reserved.
-
- var assert = require('assert-plus');
-
-
- ///--- API
-
- /**
- * RFC 2254 Escaping of filter strings
- *
- * Raw Escaped
- * (o=Parens (R Us)) (o=Parens \28R Us\29)
- * (cn=star*) (cn=star\2A)
- * (filename=C:\MyFile) (filename=C:\5cMyFile)
- *
- * Use substr_filter to avoid having * ecsaped.
- *
- * @author [Austin King](https://github.com/ozten)
- */
- function _escape(inp) {
- if (typeof (inp) === 'string') {
- var esc = '';
- for (var i = 0; i < inp.length; i++) {
- switch (inp[i]) {
- case '*':
- esc += '\\2a';
- break;
- case '(':
- esc += '\\28';
- break;
- case ')':
- esc += '\\29';
- break;
- case '\\':
- esc += '\\5c';
- break;
- case '\0':
- esc += '\\00';
- break;
- default:
- esc += inp[i];
- break;
- }
- }
- return esc;
-
- } else {
- return inp;
- }
- }
-
-
- /**
- * Check value or array with test function.
- *
- * @param {Function} rule test function.
- * @param value value or array of values.
- * @param {Boolean} allMatch require all array values to match. default: false
- */
- function testValues(rule, value, allMatch) {
- if (Array.isArray(value)) {
- var i;
- if (allMatch) {
- // Do all entries match rule?
- for (i = 0; i < value.length; i++) {
- if (!rule(value[i])) {
- return false;
- }
- }
- return true;
- } else {
- // Do any entries match rule?
- for (i = 0; i < value.length; i++) {
- if (rule(value[i])) {
- return true;
- }
- }
- return false;
- }
- } else {
- return rule(value);
- }
- }
-
-
- /**
- * Fetch value for named object attribute.
- *
- * @param {Object} obj object to fetch value from
- * @param {String} attr name of attribute to fetch
- * @param {Boolean} strictCase attribute name is case-sensitive. default: false
- */
- function getAttrValue(obj, attr, strictCase) {
- assert.object(obj);
- assert.string(attr);
- // Check for exact case match first
- if (obj.hasOwnProperty(attr)) {
- return obj[attr];
- } else if (strictCase) {
- return undefined;
- }
-
- // Perform case-insensitive enumeration after that
- var lower = attr.toLowerCase();
- var result;
- Object.getOwnPropertyNames(obj).some(function (name) {
- if (name.toLowerCase() === lower) {
- result = obj[name];
- return true;
- }
- return false;
- });
- return result;
- }
-
-
- /**
- * Filter base class
- */
- function Filter() {
- }
-
-
- /**
- * Depth-first filter traversal
- */
- Filter.prototype.forEach = function forEach(cb) {
- if (this.filter) {
- // not
- this.filter.forEach(cb);
- } else if (this.filters) {
- // and/or
- this.filters.forEach(function (item) {
- item.forEach(cb);
- });
- }
- cb(this);
- };
-
- /**
- * Depth-first map traversal.
- */
- Filter.prototype.map = function map(cb) {
- var child;
- if (this.filter) {
- child = this.filter.map(cb);
- if (child === null) {
- // empty NOT not allowed
- return null;
- } else {
- this.filter = child;
- }
- } else if (this.filters) {
- child = this.filters.map(function (item) {
- return item.map(cb);
- }).filter(function (item) {
- return (item !== null);
- });
- if (child.length === 0) {
- // empty and/or not allowed
- return null;
- } else {
- this.filters = child;
- }
- }
- return cb(this);
- };
-
-
- ///--- Exports
-
- module.exports = {
- escape: _escape,
- testValues: testValues,
- getAttrValue: getAttrValue,
- Filter: Filter
- };
|