lib/dn.js
function parse(name) {
  if (typeof (name) !== 'string')
    throw new TypeError('name (string) required');

  var cur = 0;
  var len = name.length;

  function parseRdn() {
    var rdn = new RDN();
    var order = 0;
    rdn.spLead = trim();
    while (cur < len) {
      var opts = {
        order: order
      };
      var attr = parseAttrType();
      trim();
      if (cur >= len || name[cur++] !== '=')
        throw invalidDN(name);

      trim();
      // Parameters about RDN value are set in 'opts' by parseAttrValue
      var value = parseAttrValue(opts);
      rdn.set(attr, value, opts);
      rdn.spTrail = trim();
      if (cur >= len || name[cur] !== '+')
        break;
      ++cur;
      ++order;
    }
    return rdn;
  }


  function trim() {
    var count = 0;
    while ((cur < len) && isWhitespace(name[cur])) {
      ++cur;
      count++;
    }
    return count;
  }

  function parseAttrType() {
    var beg = cur;
    while (cur < len) {
      var c = name[cur];
      if (isAlphaNumeric(c) ||
          c == '.' ||
          c == '-' ||
          c == ' ') {
        ++cur;
      } else {
        break;
      }
    }
    // Back out any trailing spaces.
    while ((cur > beg) && (name[cur - 1] == ' '))
      --cur;

    if (beg == cur)
      throw invalidDN(name);

    return name.slice(beg, cur);
  }

  function parseAttrValue(opts) {
    if (cur < len && name[cur] == '#') {
      opts.binary = true;
      return parseBinaryAttrValue();
    } else if (cur < len && name[cur] == '"') {
      opts.quoted = true;
      return parseQuotedAttrValue();
    } else {
      return parseStringAttrValue();
    }
  }

  function parseBinaryAttrValue() {
    var beg = cur++;
    while (cur < len && isAlphaNumeric(name[cur]))
      ++cur;

    return name.slice(beg, cur);
  }

  function parseQuotedAttrValue() {
    var str = '';
    ++cur; // Consume the first quote

    while ((cur < len) && name[cur] != '"') {
      if (name[cur] === '\\')
        cur++;
      str += name[cur++];
    }
    if (cur++ >= len) // no closing quote
      throw invalidDN(name);

    return str;
  }

  function parseStringAttrValue() {
    var beg = cur;
    var str = '';
    var esc = -1;

    while ((cur < len) && !atTerminator()) {
      if (name[cur] === '\\') {
        // Consume the backslash and mark its place just in case it's escaping
        // whitespace which needs to be preserved.
        esc = cur++;
      }
      if (cur === len) // backslash followed by nothing
        throw invalidDN(name);
      str += name[cur++];
    }

    // Trim off (unescaped) trailing whitespace and rewind cursor to the end of
    // the AttrValue to record whitespace length.
    for (; cur > beg; cur--) {
      if (!isWhitespace(name[cur - 1]) || (esc === (cur - 1)))
        break;
    }
    return str.slice(0, cur - beg);
  }

  function atTerminator() {
    return (cur < len &&
            (name[cur] === ',' ||
             name[cur] === ';' ||
             name[cur] === '+'));
  }

  var rdns = [];

  // Short-circuit for empty DNs
  if (len === 0)
    return new DN(rdns);

  rdns.push(parseRdn());
  while (cur < len) {
    if (name[cur] === ',' || name[cur] === ';') {
      ++cur;
      rdns.push(parseRdn());
    } else {
      throw invalidDN(name);
    }
  }

  return new DN(rdns);
}
function parse(name) {
  if (typeof (name) !== 'string')
    throw new TypeError('name (string) required');

  var cur = 0;
  var len = name.length;

  function parseRdn() {
    var rdn = new RDN();
    var order = 0;
    rdn.spLead = trim();
    while (cur < len) {
      var opts = {
        order: order
      };
      var attr = parseAttrType();
      trim();
      if (cur >= len || name[cur++] !== '=')
        throw invalidDN(name);

      trim();
      // Parameters about RDN value are set in 'opts' by parseAttrValue
      var value = parseAttrValue(opts);
      rdn.set(attr, value, opts);
      rdn.spTrail = trim();
      if (cur >= len || name[cur] !== '+')
        break;
      ++cur;
      ++order;
    }
    return rdn;
  }


  function trim() {
    var count = 0;
    while ((cur < len) && isWhitespace(name[cur])) {
      ++cur;
      count++;
    }
    return count;
  }

  function parseAttrType() {
    var beg = cur;
    while (cur < len) {
      var c = name[cur];
      if (isAlphaNumeric(c) ||
          c == '.' ||
          c == '-' ||
          c == ' ') {
        ++cur;
      } else {
        break;
      }
    }
    // Back out any trailing spaces.
    while ((cur > beg) && (name[cur - 1] == ' '))
      --cur;

    if (beg == cur)
      throw invalidDN(name);

    return name.slice(beg, cur);
  }

  function parseAttrValue(opts) {
    if (cur < len && name[cur] == '#') {
      opts.binary = true;
      return parseBinaryAttrValue();
    } else if (cur < len && name[cur] == '"') {
      opts.quoted = true;
      return parseQuotedAttrValue();
    } else {
      return parseStringAttrValue();
    }
  }

  function parseBinaryAttrValue() {
    var beg = cur++;
    while (cur < len && isAlphaNumeric(name[cur]))
      ++cur;

    return name.slice(beg, cur);
  }

  function parseQuotedAttrValue() {
    var str = '';
    ++cur; // Consume the first quote

    while ((cur < len) && name[cur] != '"') {
      if (name[cur] === '\\')
        cur++;
      str += name[cur++];
    }
    if (cur++ >= len) // no closing quote
      throw invalidDN(name);

    return str;
  }

  function parseStringAttrValue() {
    var beg = cur;
    var str = '';
    var esc = -1;

    while ((cur < len) && !atTerminator()) {
      if (name[cur] === '\\') {
        // Consume the backslash and mark its place just in case it's escaping
        // whitespace which needs to be preserved.
        esc = cur++;
      }
      if (cur === len) // backslash followed by nothing
        throw invalidDN(name);
      str += name[cur++];
    }

    // Trim off (unescaped) trailing whitespace and rewind cursor to the end of
    // the AttrValue to record whitespace length.
    for (; cur > beg; cur--) {
      if (!isWhitespace(name[cur - 1]) || (esc === (cur - 1)))
        break;
    }
    return str.slice(0, cur - beg);
  }

  function atTerminator() {
    return (cur < len &&
            (name[cur] === ',' ||
             name[cur] === ';' ||
             name[cur] === '+'));
  }

  var rdns = [];

  // Short-circuit for empty DNs
  if (len === 0)
    return new DN(rdns);

  rdns.push(parseRdn());
  while (cur < len) {
    if (name[cur] === ',' || name[cur] === ';') {
      ++cur;
      rdns.push(parseRdn());
    } else {
      throw invalidDN(name);
    }
  }

  return new DN(rdns);
}
function parse ( name ) { if ( typeof ( name ) !== 'string' ) throw new TypeError ( 'name (string) required' ) ; var cur = 0 ; var len = name . length ; function parseRdn ( ) { var rdn = new RDN ( ) ; var order = 0 ; rdn . spLead = trim ( ) ; while ( cur < len ) { var opts = { order : order } ; var attr = parseAttrType ( ) ; trim ( ) ; if ( cur >= len || name [ cur ++ ] !== '=' ) throw invalidDN ( name ) ; trim ( ) ; // Parameters about RDN value are set in 'opts' by parseAttrValue var value = parseAttrValue ( opts ) ; rdn . set ( attr , value , opts ) ; rdn . spTrail = trim ( ) ; if ( cur >= len || name [ cur ] !== '+' ) break ; ++ cur ; ++ order ; } return rdn ; } function trim ( ) { var count = 0 ; while ( ( cur < len ) && isWhitespace ( name [ cur ] ) ) { ++ cur ; count ++ ; } return count ; } function parseAttrType ( ) { var beg = cur ; while ( cur < len ) { var c = name [ cur ] ; if ( isAlphaNumeric ( c ) || c == '.' || c == '-' || c == ' ' ) { ++ cur ; } else { break ; } } // Back out any trailing spaces. while ( ( cur > beg ) && ( name [ cur - 1 ] == ' ' ) ) -- cur ; if ( beg == cur ) throw invalidDN ( name ) ; return name . slice ( beg , cur ) ; } function parseAttrValue ( opts ) { if ( cur < len && name [ cur ] == '#' ) { opts . binary = true ; return parseBinaryAttrValue ( ) ; } else if ( cur < len && name [ cur ] == '"' ) { opts . quoted = true ; return parseQuotedAttrValue ( ) ; } else { return parseStringAttrValue ( ) ; } } function parseBinaryAttrValue ( ) { var beg = cur ++ ; while ( cur < len && isAlphaNumeric ( name [ cur ] ) ) ++ cur ; return name . slice ( beg , cur ) ; } function parseQuotedAttrValue ( ) { var str = '' ; ++ cur ; // Consume the first quote while ( ( cur < len ) && name [ cur ] != '"' ) { if ( name [ cur ] === '\\' ) cur ++ ; str += name [ cur ++ ] ; } if ( cur ++ >= len ) // no closing quote throw invalidDN ( name ) ; return str ; } function parseStringAttrValue ( ) { var beg = cur ; var str = '' ; var esc = - 1 ; while ( ( cur < len ) && ! atTerminator ( ) ) { if ( name [ cur ] === '\\' ) { // Consume the backslash and mark its place just in case it's escaping // whitespace which needs to be preserved. esc = cur ++ ; } if ( cur === len ) // backslash followed by nothing throw invalidDN ( name ) ; str += name [ cur ++ ] ; } // Trim off (unescaped) trailing whitespace and rewind cursor to the end of // the AttrValue to record whitespace length. for ( ; cur > beg ; cur -- ) { if ( ! isWhitespace ( name [ cur - 1 ] ) || ( esc === ( cur - 1 ) ) ) break ; } return str . slice ( 0 , cur - beg ) ; } function atTerminator ( ) { return ( cur < len && ( name [ cur ] === ',' || name [ cur ] === ';' || name [ cur ] === '+' ) ) ; } var rdns = [ ] ; // Short-circuit for empty DNs if ( len === 0 ) return new DN ( rdns ) ; rdns . push ( parseRdn ( ) ) ; while ( cur < len ) { if ( name [ cur ] === ',' || name [ cur ] === ';' ) { ++ cur ; rdns . push ( parseRdn ( ) ) ; } else { throw invalidDN ( name ) ; } } return new DN ( rdns ) ; }
Thank you OpenJDK!
Thank you OpenJDK!