1
2
3 from ldaptor.protocols import pureldap
4
5 """
6
7 RFC2254:
8
9 filter = "(" filtercomp ")"
10 filtercomp = and / or / not / item
11 and = "&" filterlist
12 or = "|" filterlist
13 not = "!" filter
14 filterlist = 1*filter
15 item = simple / present / substring / extensible
16 simple = attr filtertype value
17 filtertype = equal / approx / greater / less
18 equal = "="
19 approx = "~="
20 greater = ">="
21 less = "<="
22 extensible = attr [":dn"] [":" matchingrule] ":=" value
23 / [":dn"] ":" matchingrule ":=" value
24 present = attr "=*"
25 substring = attr "=" [initial] any [final]
26 initial = value
27 any = "*" *(value "*")
28 final = value
29 attr = AttributeDescription from Section 4.1.5 of [1]
30 matchingrule = MatchingRuleId from Section 4.1.9 of [1]
31 value = AttributeValue from Section 4.1.6 of [1]
32 """
33
36 Exception.__init__(self)
37 self.msg=msg
38 self.loc=loc
39 self.text=text
40
42 return "Invalid LDAP filter: %s at point %d in %r" \
43 % (self.msg, self.loc, self.text)
44
46 raise NotImplementedError
47
48 from pyparsing import Word, Literal, Optional, ZeroOrMore, Suppress, \
49 Group, Forward, OneOrMore, ParseException, \
50 CharsNotIn, Combine, StringStart, \
51 StringEnd, delimitedList
52
53 import copy, string
54
55 filter_ = Forward()
56 attr = Word(string.ascii_letters,
57 string.ascii_letters + string.digits + ';-',)
58 attr.leaveWhitespace()
59 attr.setName('attr')
60 hexdigits = Word(string.hexdigits, exact=2)
61 hexdigits.setName('hexdigits')
62 escaped = Suppress(Literal('\\'))+hexdigits
63 escaped.setName('escaped')
65 text=t[0]
66 return chr(int(text, 16))
67 escaped.setParseAction(_p_escaped)
68 value = Combine(OneOrMore(CharsNotIn('*()\\\0') | escaped))
69 value.setName('value')
70 equal = Literal("=")
71 equal.setParseAction(lambda s,l,t: pureldap.LDAPFilter_equalityMatch)
72 approx = Literal("~=")
73 approx.setParseAction(lambda s,l,t: pureldap.LDAPFilter_approxMatch)
74 greater = Literal(">=")
75 greater.setParseAction(lambda s,l,t: pureldap.LDAPFilter_greaterOrEqual)
76 less = Literal("<=")
77 less.setParseAction(lambda s,l,t: pureldap.LDAPFilter_lessOrEqual)
78 filtertype = equal | approx | greater | less
79 filtertype.setName('filtertype')
80 simple = attr + filtertype + value
81 simple.leaveWhitespace()
82 simple.setName('simple')
87 simple.setParseAction(_p_simple)
88 present = attr + "=*"
89 present.setParseAction(lambda s,l,t: pureldap.LDAPFilter_present(t[0]))
90 initial = copy.copy(value)
91 initial.setParseAction(lambda s,l,t: pureldap.LDAPFilter_substrings_initial(t[0]))
92 initial.setName('initial')
93 any_value = value + Suppress(Literal("*"))
94 any_value.setParseAction(lambda s,l,t: pureldap.LDAPFilter_substrings_any(t[0]))
95 any = Suppress(Literal("*")) + ZeroOrMore(any_value)
96 any.setName('any')
97 final = copy.copy(value)
98 final.setName('final')
99 final.setParseAction(lambda s,l,t: pureldap.LDAPFilter_substrings_final(t[0]))
100 substring = attr + Suppress(Literal("=")) + Group(Optional(initial) + any + Optional(final))
101 substring.setName('substring')
107 substring.setParseAction(_p_substring)
108
109 keystring = Word(string.ascii_letters,
110 string.ascii_letters + string.digits + ';-')
111 keystring.setName('keystring')
112 numericoid = delimitedList(Word(string.digits), delim='.', combine=True)
113 numericoid.setName('numericoid')
114 oid = numericoid | keystring
115 oid.setName('oid')
116 matchingrule = copy.copy(oid)
117 matchingrule.setName('matchingrule')
118
119 extensible_dn = Optional(":dn")
122 extensible_dn.setParseAction(_p_extensible_dn)
123
124 matchingrule_or_none = Optional(Suppress(":") + matchingrule)
126 if not t:
127 return [None]
128 else:
129 return t[0]
130 matchingrule_or_none.setParseAction(_p_matchingrule_or_none)
131
132 extensible_attr = attr + extensible_dn + matchingrule_or_none + Suppress(":=") + value
133 extensible_attr.setName('extensible_attr')
136 extensible_attr.setParseAction(_p_extensible_attr)
137
138
139 extensible_noattr = extensible_dn + Suppress(":") + matchingrule + Suppress(":=") + value
140 extensible_noattr.setName('extensible_noattr')
142 return [None]+list(t)
143 extensible_noattr.setParseAction(_p_extensible_noattr)
144
145 extensible = extensible_attr | extensible_noattr
146 extensible.setName('extensible')
154 extensible.setParseAction(_p_extensible)
155 item = simple ^ present ^ substring ^ extensible
156 item.setName('item')
157 item.leaveWhitespace()
158 not_ = Suppress(Literal('!')) + filter_
159 not_.setParseAction(lambda s,l,t: pureldap.LDAPFilter_not(t[0]))
160 not_.setName('not')
161 filterlist = OneOrMore(filter_)
162 or_ = Suppress(Literal('|')) + filterlist
163 or_.setParseAction(lambda s,l,t: pureldap.LDAPFilter_or(t))
164 or_.setName('or')
165 and_ = Suppress(Literal('&')) + filterlist
166 and_.setParseAction(lambda s,l,t: pureldap.LDAPFilter_and(t))
167 and_.setName('and')
168 filtercomp = and_ | or_ | not_ | item
169 filtercomp.setName('filtercomp')
170 filter_ << (Suppress(Literal('(').leaveWhitespace())
171 + filtercomp
172 + Suppress(Literal(')').leaveWhitespace()))
173 filter_.setName('filter')
174 filtercomp.leaveWhitespace()
175 filter_.leaveWhitespace()
176
177 toplevel = (StringStart().leaveWhitespace()
178 + filter_
179 + StringEnd().leaveWhitespace())
180 toplevel.leaveWhitespace()
181 toplevel.setName('toplevel')
182
184 try:
185 x=toplevel.parseString(s)
186 except ParseException, e:
187 raise InvalidLDAPFilter, (e.msg,
188 e.loc,
189 e.line)
190 assert len(x)==1
191 return x[0]
192
193
194 maybeSubString_value = Combine(OneOrMore(CharsNotIn('*\\\0') | escaped))
195
196 maybeSubString_simple = copy.copy(maybeSubString_value)
202 maybeSubString_simple.setParseAction(_p_maybeSubString_simple)
203
204 maybeSubString_present = Literal("*")
208 maybeSubString_present.setParseAction(_p_maybeSubString_present)
209
210 maybeSubString_substring = Optional(initial) + any + Optional(final)
216 maybeSubString_substring.setParseAction(_p_maybeSubString_substring)
217
218 maybeSubString = (maybeSubString_simple
219 ^ maybeSubString_present
220 ^ maybeSubString_substring
221 )
222
224 try:
225 x=maybeSubString.parseString(s)
226 except ParseException, e:
227 raise InvalidLDAPFilter, (e.msg,
228 e.loc,
229 e.line)
230 assert len(x)==1
231 fn = x[0]
232 return fn(attrType)
233
234 if __name__=='__main__':
235 import sys
236 for filt in sys.argv[1:]:
237 print repr(parseFilter(filt))
238 print
239