Source code for univention.ldif
#!/usr/bin/python3
# SPDX-FileCopyrightText: 2004-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only
"""Univention LDIF tool"""
import re
import sys
from argparse import ArgumentParser, FileType
from base64 import b64decode
from collections.abc import Iterable, Iterator
from typing import IO
__all__ = [
"ldif_decode",
"ldif_normalize",
"ldif_unwrap",
]
RE_B64 = re.compile(r'^([a-zA-Z0-9-]+):: (.*)')
[docs]
def ldif_decode(src: IO[str] = sys.stdin, dst: IO[bytes] = sys.stdout.buffer) -> None:
"""Decode bas64 in LDIF."""
try:
for line in src:
dst.write(decode64(line))
except BrokenPipeError:
pass
def decode(stream: Iterable[str]) -> Iterator[bytes]:
for line in stream:
yield decode64(line)
def decode64(line: str) -> bytes:
m = RE_B64.search(line)
if m:
attr, encoded = m.groups()
decoded = b64decode(encoded)
return b"%s: %s\n" % (attr.encode("utf-8"), decoded)
else:
return line.encode("utf-8")
[docs]
def ldif_unwrap(src: IO[str] = sys.stdin, dst: IO[bytes] = sys.stdout.buffer) -> None:
"""Unwrap LDIF."""
try:
for line in unwrap(src):
dst.write(line.encode("utf-8"))
except BrokenPipeError:
pass
def unwrap(stream: Iterable[str]) -> Iterator[str]:
prev = ""
for line in stream:
if line[:1] in (' ', '\t'):
prev = prev.rstrip("\n\r") + line[1:]
else:
if prev:
yield prev
prev = line
if prev:
yield prev
[docs]
def ldif_normalize(src: IO[str] = sys.stdin, dst: IO[bytes] = sys.stdout.buffer) -> None:
"""Unwrap and base64 decode LDIF."""
try:
for line in unwrap(src):
dst.write(decode64(line))
except BrokenPipeError:
pass
def main() -> None:
parser = ArgumentParser(description=__doc__)
parser.add_argument("--src", "-s", type=FileType("r"), default="-", help="Source input")
parser.add_argument("--dst", "-d", type=FileType("w"), default="-", help="Destination output")
parser.set_defaults(func=ldif_normalize)
subparsers = parser.add_subparsers(help="Sub-command help")
parser_decode = subparsers.add_parser("decode", help=ldif_decode.__doc__)
parser_decode.set_defaults(func=ldif_decode)
parser_unwrap = subparsers.add_parser("unwrap", help=ldif_unwrap.__doc__)
parser_unwrap.set_defaults(func=ldif_unwrap)
args = parser.parse_args()
args.func(args.src, args.dst.buffer)
if __name__ == "__main__":
main()