Packages

Parse and modify LDAP Data Interchange Format (LDIF)

Current section

Files

Jump to
ldif lib ldif.ex
Raw

lib/ldif.ex

defmodule LDIF do
@moduledoc """
LDIF is a simple Elixir parser for LDAP Data Interchange Format
([LDIF](https://en.wikipedia.org/wiki/LDAP_Data_Interchange_Format)) text files.
It will convert the entries within them to Elixir structs, and can directly apply LDIF change records to normal
LDIF records.
[RFC 2849](https://www.rfc-editor.org/rfc/rfc2849) describes LDIF as:
> ... a file format suitable for describing
> directory information or modifications made to directory information.
> The file format, known as LDIF, for LDAP Data Interchange Format, is
> typically used to import and export directory information between
> LDAP-based directory servers, or to describe a set of changes which
> are to be applied to a directory.
The LDIF format is commonly used for importing records and changes into LDAP directories such as
[OpenLDAP](https://www.openldap.org). Records are typically for contact details, user accounts, groups and
departments but can be for any information.
## Features
* Import normal LDAP directory entries from a string or a file, as a list of structs.
* Import LDIF-formatted changes and apply to them to a list of entries
* Supports including external data in entry attributes. Both file:// and https:// are supported but optional
* Binary data such as images and encoded text should be parsed correctly
* A few utility functions are provided to directly modify entries - you can change DNs, adjust attribute values and
so on.
The top level `LDIF` module could contain all the functions you need but the following other modules may be of use:
* `LDIF.Sigil` provides a sigil for importing LDIF data in documentation and tests
* `LDIF.Entry` has various features for working with LDIF entries
"""
alias LDIF.Import
alias LDIF.Apply
@default_import_opts [
single_value: [],
lang_tags: true,
ext_files: true,
ext_http: false,
reject: [],
redact: [],
normalize_dns: false,
http: [],
one: false
]
@doc """
Decodes an LDIF string to a list of `LDIF.Entry` structs
Options to adjust the output include:
* `:ext_files` - whether to allow external file: URLs to be fetched and embedded. Defaults to `true`
* `:ext_http` - whether to allow external https: URLs to be fetched and embedded. Defaults to `false`
* `:lang_tags` - whether to allow language-tagged attributes. Defaults to `true`
* `:normalize_dns` - normalizes DNs if set to `true`. If given a list will normalize all listed attribute values. Defaults to `false`
* `:redact` - a list of attributes to replace with `********`.
* `:reject` - a list of attributes to remove entirely
* `:single_value` - a list of attributes to convert to a single value (the first one)
"""
@spec decode_entries!(ldif :: binary(), opts :: keyword()) :: list()
def decode_entries!(ldif, opts \\ []) do
decode_entries_as_stream!(ldif, opts)
|> Enum.to_list()
end
@doc """
Decodes an LDIF string to a list of specific Change structs
Options to adjust the output are the same as for `decode_entries!/2`
"""
@spec decode_changes!(ldif :: binary(), opts :: keyword()) :: list()
def decode_changes!(ldif, opts \\ []) do
decode_changes_as_stream!(ldif, opts)
|> Enum.to_list()
end
@doc """
Decodes an LDIF string to a stream of `LDIF.Entry` structs
Options to adjust the output are the same as for `decode_entries!/2`
"""
@spec decode_entries_as_stream!(ldif :: binary(), opts :: keyword()) :: %Stream{} | function()
def decode_entries_as_stream!(ldif, opts \\ []) do
Import.entries(ldif, Keyword.merge(@default_import_opts, opts))
end
@doc """
Decodes an LDIF string to a stream of `LDIF.Entry` structs
Options to adjust the output are the same as for `decode_entries!/2`
"""
@spec decode_changes_as_stream!(ldif :: binary(), opts :: keyword()) :: %Stream{} | function()
def decode_changes_as_stream!(ldif, opts \\ []) do
Import.changes(ldif, Keyword.merge(@default_import_opts, opts))
end
@doc """
Applies the changes specified in a list of change entries to a list of normal entries.
"""
@spec apply_changes(changes :: list(), entries :: list()) :: list()
def apply_changes(changes, entries) do
Apply.apply_changes(changes, entries)
end
end