1"""
2 pygments.lexers.ldap
3 ~~~~~~~~~~~~~~~~~~~~
4
5 Pygments lexers for LDAP.
6
7 :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9"""
10
11import re
12
13
14from pygments.lexer import RegexLexer, bygroups, default
15from pygments.token import Operator, Comment, Keyword, Literal, Name, String, \
16 Number, Punctuation, Whitespace, Escape
17
18__all__ = ['LdifLexer', 'LdaprcLexer']
19
20
21class LdifLexer(RegexLexer):
22
23 """
24 Lexer for LDIF
25 """
26
27 name = 'LDIF'
28 aliases = ['ldif']
29 filenames = ['*.ldif']
30 mimetypes = ["text/x-ldif"]
31 url = "https://datatracker.ietf.org/doc/html/rfc2849"
32 version_added = '2.17'
33
34 tokens = {
35 'root': [
36 (r'\s*\n', Whitespace),
37 (r'(-)(\n)', bygroups(Punctuation, Whitespace)),
38 (r'(#.*)(\n)', bygroups(Comment.Single, Whitespace)),
39 (r'(version)(:)([ \t]*)(.*)([ \t]*\n)', bygroups(Keyword,
40 Punctuation, Whitespace, Number.Integer, Whitespace)),
41 (r'(control)(:)([ \t]*)([\.0-9]+)([ \t]+)((?:true|false)?)([ \t]*)',
42 bygroups(Keyword, Punctuation, Whitespace, Name.Other, Whitespace, Keyword, Whitespace), "after-control"),
43 (r'(deleteoldrdn)(:)([ \n]*)([0-1]+)([ \t]*\n)',
44 bygroups(Keyword, Punctuation, Whitespace, Number, Whitespace)),
45 (r'(add|delete|replace)(::?)(\s*)(.*)([ \t]*\n)', bygroups(
46 Keyword, Punctuation, Whitespace, Name.Attribute, Whitespace)),
47 (r'(changetype)(:)([ \t]*)([a-z]*)([ \t]*\n)',
48 bygroups(Keyword, Punctuation, Whitespace, Keyword, Whitespace)),
49 (r'(dn|newrdn)(::)', bygroups(Keyword, Punctuation), "base64-dn"),
50 (r'(dn|newrdn)(:)', bygroups(Keyword, Punctuation), "dn"),
51 (r'(objectclass)(:)([ \t]*)([^ \t\n]*)([ \t]*\n)', bygroups(
52 Keyword, Punctuation, Whitespace, Name.Class, Whitespace)),
53 (r'([a-zA-Z]*|[0-9][0-9\.]*[0-9])(;)',
54 bygroups(Name.Attribute, Punctuation), "property"),
55 (r'([a-zA-Z]*|[0-9][0-9\.]*[0-9])(:<)',
56 bygroups(Name.Attribute, Punctuation), "url"),
57 (r'([a-zA-Z]*|[0-9][0-9\.]*[0-9])(::?)',
58 bygroups(Name.Attribute, Punctuation), "value"),
59 ],
60 "after-control": [
61 (r":<", Punctuation, ("#pop", "url")),
62 (r"::?", Punctuation, ("#pop", "value")),
63 default("#pop"),
64 ],
65 'property': [
66 (r'([-a-zA-Z0-9]*)(;)', bygroups(Name.Property, Punctuation)),
67 (r'([-a-zA-Z0-9]*)(:<)',
68 bygroups(Name.Property, Punctuation), ("#pop", "url")),
69 (r'([-a-zA-Z0-9]*)(::?)',
70 bygroups(Name.Property, Punctuation), ("#pop", "value")),
71 ],
72 'value': [
73 (r'(\s*)([^\n]+\S)(\n )',
74 bygroups(Whitespace, String, Whitespace)),
75 (r'(\s*)([^\n]+\S)(\n)',
76 bygroups(Whitespace, String, Whitespace), "#pop"),
77 ],
78 'url': [
79 (r'([ \t]*)(\S*)([ \t]*\n )',
80 bygroups(Whitespace, Comment.PreprocFile, Whitespace)),
81 (r'([ \t]*)(\S*)([ \t]*\n)', bygroups(Whitespace,
82 Comment.PreprocFile, Whitespace), "#pop"),
83 ],
84 "dn": [
85 (r'([ \t]*)([-a-zA-Z0-9\.]+)(=)', bygroups(Whitespace,
86 Name.Attribute, Operator), ("#pop", "dn-value")),
87 ],
88 "dn-value": [
89 (r'\\[^\n]', Escape),
90 (r',', Punctuation, ("#pop", "dn")),
91 (r'\+', Operator, ("#pop", "dn")),
92 (r'[^,\+\n]+', String),
93 (r'\n ', Whitespace),
94 (r'\n', Whitespace, "#pop"),
95 ],
96 "base64-dn": [
97 (r'([ \t]*)([^ \t\n][^ \t\n]*[^\n])([ \t]*\n )',
98 bygroups(Whitespace, Name, Whitespace)),
99 (r'([ \t]*)([^ \t\n][^ \t\n]*[^\n])([ \t]*\n)',
100 bygroups(Whitespace, Name, Whitespace), "#pop"),
101 ]
102 }
103
104
105class LdaprcLexer(RegexLexer):
106 """
107 Lexer for OpenLDAP configuration files.
108 """
109
110 name = 'LDAP configuration file'
111 aliases = ['ldapconf', 'ldaprc']
112 filenames = ['.ldaprc', 'ldaprc', 'ldap.conf']
113 mimetypes = ["text/x-ldapconf"]
114 url = 'https://www.openldap.org/software//man.cgi?query=ldap.conf&sektion=5&apropos=0&manpath=OpenLDAP+2.4-Release'
115 version_added = '2.17'
116
117 _sasl_keywords = r'SASL_(?:MECH|REALM|AUTHCID|AUTHZID|CBINDING)'
118 _tls_keywords = r'TLS_(?:CACERT|CACERTDIR|CERT|ECNAME|KEY|CIPHER_SUITE|PROTOCOL_MIN|RANDFILE|CRLFILE)'
119 _literal_keywords = rf'(?:URI|SOCKET_BIND_ADDRESSES|{_sasl_keywords}|{_tls_keywords})'
120 _boolean_keywords = r'GSSAPI_(?:ALLOW_REMOTE_PRINCIPAL|ENCRYPT|SIGN)|REFERRALS|SASL_NOCANON'
121 _integer_keywords = r'KEEPALIVE_(?:IDLE|PROBES|INTERVAL)|NETWORK_TIMEOUT|PORT|SIZELIMIT|TIMELIMIT|TIMEOUT'
122 _secprops = r'none|noanonymous|noplain|noactive|nodict|forwardsec|passcred|(?:minssf|maxssf|maxbufsize)=\d+'
123
124 flags = re.IGNORECASE | re.MULTILINE
125
126 tokens = {
127 'root': [
128 (r'#.*', Comment.Single),
129 (r'\s+', Whitespace),
130 (rf'({_boolean_keywords})(\s+)(on|true|yes|off|false|no)$',
131 bygroups(Keyword, Whitespace, Keyword.Constant)),
132 (rf'({_integer_keywords})(\s+)(\d+)',
133 bygroups(Keyword, Whitespace, Number.Integer)),
134 (r'(VERSION)(\s+)(2|3)', bygroups(Keyword, Whitespace, Number.Integer)),
135 # Constants
136 (r'(DEREF)(\s+)(never|searching|finding|always)',
137 bygroups(Keyword, Whitespace, Keyword.Constant)),
138 (rf'(SASL_SECPROPS)(\s+)((?:{_secprops})(?:,{_secprops})*)',
139 bygroups(Keyword, Whitespace, Keyword.Constant)),
140 (r'(SASL_CBINDING)(\s+)(none|tls-unique|tls-endpoint)',
141 bygroups(Keyword, Whitespace, Keyword.Constant)),
142 (r'(TLS_REQ(?:CERT|SAN))(\s+)(allow|demand|hard|never|try)',
143 bygroups(Keyword, Whitespace, Keyword.Constant)),
144 (r'(TLS_CRLCHECK)(\s+)(none|peer|all)',
145 bygroups(Keyword, Whitespace, Keyword.Constant)),
146 # Literals
147 (r'(BASE|BINDDN)(\s+)(\S+)$',
148 bygroups(Keyword, Whitespace, Literal)),
149 # Accepts hostname with or without port.
150 (r'(HOST)(\s+)([a-z0-9]+)((?::(\d+))?)',
151 bygroups(Keyword, Whitespace, Literal, Number.Integer)),
152 (rf'({_literal_keywords})(\s+)(\S+)$',
153 bygroups(Keyword, Whitespace, Literal)),
154 ],
155 }