import re
import base64


def ldif_to_entries(ldif_lines):
    """Convert a LDIF file to a dict of dn => attributes.

    Args:
        ldif_lines: ASCII-encoded LDIF string

    Returns:
        dict(dn => dict(attribute => list(values))), where:
        - `dn` is a string;
        - `attribute` is a string;
        - `value` is bytes.

    Note: the object's DN is not included in the attributes.
    """
    entries = {}
    for entry in ldif_lines.decode('ascii').split('\n\n'):
        if not entry.strip():
            continue
        if entry.startswith('version:'):
            if re.match('^version: +1$', entry.strip()):
                continue
            else:
                raise ValueError("Invalid LDIF file - missing 'version: 1' header")

        attributes = {}
        for line in entry.split('\n'):
            if not line.strip():
                continue
            m = re.match(r'(\w+)(:?): (.*)', line.strip())
            if m is None:
                raise ValueError("Invalid line in ldif output: %r" % line)

            field, is_extended, value = m.groups()
            if is_extended:
                value = base64.b64decode(value.encode('ascii'))
            else:
                value = value.encode('ascii')
            attributes.setdefault(field, []).append(value)
        dns = attributes.pop('dn', [b''])
        assert len(dns) == 1
        entries[dns[0].decode('utf-8')] = attributes
    return entries