@@ -270,9 +270,100 @@ def match entry
270270 end
271271 end
272272
273+ # Converts an LDAP filter-string (in the prefix syntax specified in RFC-2254)
274+ # to a Net::LDAP::Filter.
275+ def self . from_rfc2254 str
276+ FilterParser . new ( str ) . filter
277+ end
273278
274279end # class Net::LDAP::Filter
275280
281+
282+ class FilterParser #:nodoc:
283+
284+ attr_reader :filter
285+
286+ def initialize str
287+ require 'strscan'
288+ @filter = parse ( StringScanner . new ( str ) ) or raise Net ::LDAP ::LdapError . new ( "invalid filter syntax" )
289+ end
290+
291+ def parse scanner
292+ parse_filter_branch ( scanner ) or parse_paren_expression ( scanner )
293+ end
294+
295+ def parse_paren_expression scanner
296+ if scanner . scan /\s *\( \s */
297+ b = if scanner . scan /\s *\& \s */
298+ a = nil
299+ branches = [ ]
300+ while br = parse_paren_expression ( scanner )
301+ branches << br
302+ end
303+ if branches . length >= 2
304+ a = branches . shift
305+ while branches . length > 0
306+ a = a & branches . shift
307+ end
308+ a
309+ end
310+ elsif scanner . scan /\s *\| \s */
311+ # TODO: DRY!
312+ a = nil
313+ branches = [ ]
314+ while br = parse_paren_expression ( scanner )
315+ branches << br
316+ end
317+ if branches . length >= 2
318+ a = branches . shift
319+ while branches . length > 0
320+ a = a | branches . shift
321+ end
322+ a
323+ end
324+ elsif scanner . scan /\s *\! \s */
325+ br = parse_paren_expression ( scanner )
326+ if br
327+ ~ br
328+ end
329+ else
330+ parse_filter_branch ( scanner )
331+ end
332+
333+ if b and scanner . scan ( /\s *\) \s */ )
334+ b
335+ end
336+ end
337+ end
338+
339+ def parse_filter_branch scanner
340+ scanner . scan /\s */
341+ if token = scanner . scan ( /[\w \- _]+/ )
342+ scanner . scan /\s */
343+ if op = scanner . scan ( /\= |\< \= |\< |\> \= |\> |\! \= / )
344+ scanner . scan /\s */
345+ if value = scanner . scan ( /[\w \* ]+/ )
346+ case op
347+ when "="
348+ Filter . eq ( token , value )
349+ when "!="
350+ Filter . ne ( token , value )
351+ when "<"
352+ Filter . lt ( token , value )
353+ when "<="
354+ Filter . le ( token , value )
355+ when ">"
356+ Filter . gt ( token , value )
357+ when ">="
358+ Filter . ge ( token , value )
359+ end
360+ end
361+ end
362+ end
363+ end
364+
365+ end # class Net::LDAP::FilterParser
366+
276367end # class Net::LDAP
277368end # module Net
278369
0 commit comments