From 7de0147b21e206bac1493ebb4abdf381052ff989 Mon Sep 17 00:00:00 2001 From: blackhedd Date: Mon, 15 May 2006 20:03:56 +0000 Subject: [PATCH] Added Net::LDAP::Filter.from_rfc2254 --- lib/net/ldap/filter.rb | 91 ++++++++++++++++++++++++++++++++++++++++++ tests/testfilter.rb | 11 +++++ 2 files changed, 102 insertions(+) diff --git a/lib/net/ldap/filter.rb b/lib/net/ldap/filter.rb index 84e8c7b..25bf549 100644 --- a/lib/net/ldap/filter.rb +++ b/lib/net/ldap/filter.rb @@ -270,9 +270,100 @@ class Filter end end + # Converts an LDAP filter-string (in the prefix syntax specified in RFC-2254) + # to a Net::LDAP::Filter. + def self.from_rfc2254 str + FilterParser.new(str).filter + end end # class Net::LDAP::Filter + +class FilterParser #:nodoc: + + attr_reader :filter + + def initialize str + require 'strscan' + @filter = parse( StringScanner.new( str )) or raise Net::LDAP::LdapError.new( "invalid filter syntax" ) + end + + def parse scanner + parse_filter_branch(scanner) or parse_paren_expression(scanner) + end + + def parse_paren_expression scanner + if scanner.scan /\s*\(\s*/ + b = if scanner.scan /\s*\&\s*/ + a = nil + branches = [] + while br = parse_paren_expression(scanner) + branches << br + end + if branches.length >= 2 + a = branches.shift + while branches.length > 0 + a = a & branches.shift + end + a + end + elsif scanner.scan /\s*\|\s*/ + # TODO: DRY! + a = nil + branches = [] + while br = parse_paren_expression(scanner) + branches << br + end + if branches.length >= 2 + a = branches.shift + while branches.length > 0 + a = a | branches.shift + end + a + end + elsif scanner.scan /\s*\!\s*/ + br = parse_paren_expression(scanner) + if br + ~ br + end + else + parse_filter_branch( scanner ) + end + + if b and scanner.scan( /\s*\)\s*/ ) + b + end + end + end + + def parse_filter_branch scanner + scanner.scan /\s*/ + if token = scanner.scan( /[\w\-_]+/ ) + scanner.scan /\s*/ + if op = scanner.scan( /\=|\<\=|\<|\>\=|\>|\!\=/ ) + scanner.scan /\s*/ + if value = scanner.scan( /[\w\*]+/ ) + case op + when "=" + Filter.eq( token, value ) + when "!=" + Filter.ne( token, value ) + when "<" + Filter.lt( token, value ) + when "<=" + Filter.le( token, value ) + when ">" + Filter.gt( token, value ) + when ">=" + Filter.ge( token, value ) + end + end + end + end + end + +end # class Net::LDAP::FilterParser + end # class Net::LDAP end # module Net diff --git a/tests/testfilter.rb b/tests/testfilter.rb index f1ca616..4339f26 100644 --- a/tests/testfilter.rb +++ b/tests/testfilter.rb @@ -19,6 +19,17 @@ class TestFilter < Test::Unit::TestCase end def test_rfc_2254 + p Net::LDAP::Filter.from_rfc2254( " ( uid=george* ) " ) + p Net::LDAP::Filter.from_rfc2254( "uid!=george*" ) + p Net::LDAP::Filter.from_rfc2254( "uidgeorge*" ) + p Net::LDAP::Filter.from_rfc2254( "uid>=george*" ) + p Net::LDAP::Filter.from_rfc2254( "uid!=george*" ) + + p Net::LDAP::Filter.from_rfc2254( "(& (uid!=george* ) (mail=*))" ) + p Net::LDAP::Filter.from_rfc2254( "(| (uid!=george* ) (mail=*))" ) + p Net::LDAP::Filter.from_rfc2254( "(! (mail=*))" ) end