123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- 'use strict'
- const readAttributePair = require('./read-attribute-pair')
- /**
- * @typedef {object} ParsedPojoRdn
- * @property {string} name Either the name of an RDN attribute, or the
- * equivalent numeric OID.
- * @property {string | import('@ldapjs/asn1').BerReader} value The attribute
- * value as a plain string, or a `BerReader` if the string value was an encoded
- * hex string.
- */
- /**
- * Parse a string into a set of plain JavaScript object representations of
- * RDNs.
- *
- * @example A plain string with multiple RDNs and multiple attribute assertions.
- * const input = 'cn=foo+sn=bar,dc=example,dc=com
- * const result = parseString(input)
- * // [
- * // { cn: 'foo', sn: 'bar' },
- * // { dc: 'example' }
- * // { dc: 'com' }
- * // ]
- *
- * @param {string} input The RDN string to parse.
- *
- * @returns {ParsedPojoRdn[]}
- *
- * @throws When there is some problem parsing the RDN string.
- */
- module.exports = function parseString (input) {
- if (typeof input !== 'string') {
- throw Error('input must be a string')
- }
- if (input.length === 0) {
- // Short circuit because the input is an empty DN (i.e. "root DSE").
- return []
- }
- const searchBuffer = Buffer.from(input, 'utf8')
- const length = searchBuffer.byteLength
- const rdns = []
- let pos = 0
- let rdn = {}
- readRdnLoop:
- while (pos <= length) {
- if (pos === length) {
- const char = searchBuffer[pos - 1]
- /* istanbul ignore else */
- if (char === 0x2b || char === 0x2c || char === 0x3b) {
- throw Error('rdn string ends abruptly with character: ' + String.fromCharCode(char))
- }
- }
- // Find the start of significant characters by skipping over any leading
- // whitespace.
- while (pos < length && searchBuffer[pos] === 0x20) {
- pos += 1
- }
- const readAttrPairResult = readAttributePair({ searchBuffer, startPos: pos })
- pos = readAttrPairResult.endPos
- rdn = { ...rdn, ...readAttrPairResult.pair }
- if (pos >= length) {
- // We've reached the end of the string. So push the current RDN and stop.
- rdns.push(rdn)
- break
- }
- // Next, we need to determine if the next set of significant characters
- // denotes another attribute pair for the current RDN, or is the indication
- // of another RDN.
- while (pos < length) {
- const char = searchBuffer[pos]
- // We don't need to skip whitespace before the separator because the
- // attribute pair function has already advanced us past any such
- // whitespace.
- if (char === 0x2b) { // +
- // We need to continue adding attribute pairs to the current RDN.
- pos += 1
- continue readRdnLoop
- }
- /* istanbul ignore else */
- if (char === 0x2c || char === 0x3b) { // , or ;
- // The current RDN has been fully parsed, so push it to the list,
- // reset the collector, and start parsing the next RDN.
- rdns.push(rdn)
- rdn = {}
- pos += 1
- continue readRdnLoop
- }
- }
- }
- return rdns
- }
|