diff --git a/ldapserver/dn.py b/ldapserver/dn.py index b6ce3bfc823977b53f19ba7a4d5fb6e625b49240..f291face5d1e1352d9200d26e172dc0c1a5c4b40 100644 --- a/ldapserver/dn.py +++ b/ldapserver/dn.py @@ -55,22 +55,16 @@ class DN(tuple): :raises ValueError: if expr is invalid :returns: Parsed DN :rtype: DN''' - escaped = False rdns = [] - token = '' - for char in expr: - if escaped: - escaped = False - token += char - elif char == ',': - rdns.append(RDN.from_str(schema, token)) - token = '' - else: - if char == '\\': - escaped = True - token += char - if token: - rdns.append(RDN.from_str(schema, token)) + while expr: + # relativeDistinguishedName may contain escape sequences including "\,". + # Split off first token expr at "," while ignoring "\,". + match = re.match(r'^(([^,\\]|\\.)+)(,|$)', expr) + if not match: + raise ValueError(f'Unrecognized token {expr!r}') + expr = expr[match.end():] + rdn_expr, _, _ = match.groups() + rdns.append(RDN.from_str(schema, rdn_expr)) return cls(schema, *rdns) def __str__(self): @@ -269,22 +263,16 @@ class RDN(tuple): :raises ValueError: if expr is invalid :returns: Parsed RDN :rtype: RDN''' - escaped = False assertions = [] - token = '' - for char in expr: - if escaped: - escaped = False - token += char - elif char == '+': - assertions.append(RDNAssertion.from_str(schema, token)) - token = '' - else: - if char == '\\': - escaped = True - token += char - if token: - assertions.append(RDNAssertion.from_str(schema, token)) + while expr: + # attributeTypeAndValue may contain escape sequences including "\+". + # Split off first token expr at "+" while ignoring "\+". + match = re.match(r'^(([^+\\]|\\.)+)(\+|$)', expr) + if not match: + raise ValueError(f'Unrecognized token {expr!r}') + expr = expr[match.end():] + assertion_expr, _, _ = match.groups() + assertions.append(RDNAssertion.from_str(schema, assertion_expr)) return cls(schema, *assertions) def __str__(self):