Skip to content

Commit 7de0147

Browse files
author
blackhedd
committed
Added Net::LDAP::Filter.from_rfc2254
1 parent 8b7b74a commit 7de0147

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

lib/net/ldap/filter.rb

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

274279
end # 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+
276367
end # class Net::LDAP
277368
end # module Net
278369

tests/testfilter.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ def teardown
1919
end
2020

2121
def test_rfc_2254
22+
p Net::LDAP::Filter.from_rfc2254( " ( uid=george* ) " )
23+
p Net::LDAP::Filter.from_rfc2254( "uid!=george*" )
24+
p Net::LDAP::Filter.from_rfc2254( "uid<george*" )
25+
p Net::LDAP::Filter.from_rfc2254( "uid <= george*" )
26+
p Net::LDAP::Filter.from_rfc2254( "uid>george*" )
27+
p Net::LDAP::Filter.from_rfc2254( "uid>=george*" )
28+
p Net::LDAP::Filter.from_rfc2254( "uid!=george*" )
29+
30+
p Net::LDAP::Filter.from_rfc2254( "(& (uid!=george* ) (mail=*))" )
31+
p Net::LDAP::Filter.from_rfc2254( "(| (uid!=george* ) (mail=*))" )
32+
p Net::LDAP::Filter.from_rfc2254( "(! (mail=*))" )
2233
end
2334

2435

0 commit comments

Comments
 (0)