class Net::LDAP::Filter::FilterParser
:nodoc:
object hierarchies.
Parses RFC 2254-style string representations of LDAP filters into Filter
#
def initialize(str)
def initialize(str) require 'strscan' # Don't load strscan until we need it. @filter = parse(StringScanner.new(str)) raise Net::LDAP::FilterSyntaxInvalidError, "Invalid filter syntax." unless @filter end
def merge_branches(op, scanner)
merges them into a single Filter tree by calling the provided
This method calls #parse_branches to generate the branch list and then
into a branch array for filter merging using the parent operation.
test1 and test2. Each of these is parsed separately and then pushed
That is, the expression (&(test1)(test2) has two branches:
Join ("&") and intersect ("|") operations are presented in branches.
#
def merge_branches(op, scanner) filter = nil branches = parse_branches(scanner) if branches.size >= 1 filter = branches.shift while not branches.empty? filter = filter.__send__(op, branches.shift) end end filter end
def parse(ldap_filter_string)
#
def parse(ldap_filter_string) new(ldap_filter_string).filter end
def parse(scanner)
tries to parse a standalone expression first. If that fails, it tries
Parse the string contained in the StringScanner provided. Parsing
#
def parse(scanner) parse_filter_branch(scanner) or parse_paren_expression(scanner) end
def parse_branches(scanner)
This method parses the branch text out into an array of filter
into a branch array for filter merging using the parent operation.
test1 and test2. Each of these is parsed separately and then pushed
That is, the expression (&(test1)(test2) has two branches:
Join ("&") and intersect ("|") operations are presented in branches.
#
def parse_branches(scanner) branches = [] while branch = parse_paren_expression(scanner) branches << branch end branches end
def parse_filter_branch(scanner)
#
def parse_filter_branch(scanner) scanner.scan(/\s*/) if token = scanner.scan(/[-\w:.;]*[\w]/) scanner.scan(/\s*/) if op = scanner.scan(/<=|>=|!=|:=|=/) scanner.scan(/\s*/) if value = scanner.scan(/(?:[-\[\]{}\w*.+\/:@=,#\$%&!'^~\s\xC3\x80-\xCA\xAF]|[^\x00-\x7F]|\\[a-fA-F\d]{2})+/u) # 20100313 AZ: Assumes that "(uid=george*)" is the same as # "(uid=george* )". The standard doesn't specify, but I can find # no examples that suggest otherwise. value.strip! case op when "=" Net::LDAP::Filter.eq(token, value) when "!=" Net::LDAP::Filter.ne(token, value) when "<=" Net::LDAP::Filter.le(token, value) when ">=" Net::LDAP::Filter.ge(token, value) when ":=" Net::LDAP::Filter.ex(token, value) end end end end end
def parse_paren_expression(scanner)
def parse_paren_expression(scanner) if scanner.scan(/\s*\(\s*/) expr = if scanner.scan(/\s*\&\s*/) merge_branches(:&, scanner) elsif scanner.scan(/\s*\|\s*/) merge_branches(:|, scanner) elsif scanner.scan(/\s*\!\s*/) br = parse_paren_expression(scanner) ~br if br else parse_filter_branch(scanner) end if expr and scanner.scan(/\s*\)\s*/) expr end end end