package org.keycloak.federation.ldap.idm.model;

import java.util.Deque;
import java.util.LinkedList;

/**
 * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
 */
public class LDAPDn {

    private final Deque<Entry> entries = new LinkedList<>();

    public static LDAPDn fromString(String dnString) {
        LDAPDn dn = new LDAPDn();

        String[] rdns = dnString.split(",");
        for (String entryStr : rdns) {
            String[] rdn = entryStr.split("=");
            dn.addLast(rdn[0].trim(), rdn[1].trim());
        }

        return dn;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();

        boolean first = true;
        for (Entry rdn : entries) {
            if (first) {
                first = false;
            } else {
                builder.append(",");
            }
            builder.append(rdn.attrName).append("=").append(rdn.attrValue);
        }

        return builder.toString();
    }

    /**
     * @return string like "uid=joe" from the DN like "uid=joe,dc=something,dc=org"
     */
    public String getFirstRdn() {
        Entry firstEntry = entries.getFirst();
        return firstEntry.attrName + "=" + firstEntry.attrValue;
    }

    /**
     * @return string attribute name like "uid" from the DN like "uid=joe,dc=something,dc=org"
     */
    public String getFirstRdnAttrName() {
        Entry firstEntry = entries.getFirst();
        return firstEntry.attrName;
    }

    /**
     *
     * @return string like "dc=something,dc=org" from the DN like "uid=joe,dc=something,dc=org"
     */
    public String getParentDn() {
        return new LinkedList<>(entries).remove().toString();
    }

    public void addFirst(String rdnName, String rdnValue) {
        entries.addFirst(new Entry(rdnName, rdnValue));
    }

    public void addLast(String rdnName, String rdnValue) {
        entries.addLast(new Entry(rdnName, rdnValue));
    }


    private static class Entry {
        private final String attrName;
        private final String attrValue;

        private Entry(String attrName, String attrValue) {
            this.attrName = attrName;
            this.attrValue = attrValue;
        }
    }
}

@@ -94,16 +94,80 @@
 kedList;
+%0Aimport java.util.regex.Matcher;%0Aimport java.util.regex.Pattern;
 %0A%0A/**%0A *
@@ -315,24 +315,116 @@
 dList%3C%3E();%0A%0A
+    private static final Pattern dnRegex = Pattern.compile(%22%5B%5E,%5C%5C%5C%5C%5D*(?:%5C%5C%5C%5C.%5B%5E,%5C%5C%5C%5C%5D*)%22);%0A%0A
     public s
@@ -513,53 +513,64 @@
     
-String%5B%5D rdns = dnString.split(%22,%22
+Matcher dnMatches = dnRegex.matcher(dnString
 );%0A
+%0A
         
 for 
@@ -569,35 +569,31 @@
     
-for (String entryStr : rdns
+while (dnMatches.find()
 ) %7B%0A
@@ -623,16 +623,26 @@
 n = 
-entryStr
+dnMatches.group(1)
 .spl

Fix LDAP RDN resolution based on unescaped comma split