This is a collection of classes for representing objectClasses in a Treequel::Schema.
Michael Granger <ged@FaerieMUD.org>
Mahlon E. Smith <mahlon@martini.nu>
Copyright (c) 2008-2011, Michael Granger and Mahlon E. Smith All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the author/s, nor the names of the project's contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This is an object that is used to parse and query a directory's schema
Michael Granger <ged@FaerieMUD.org>
Mahlon E. Smith <mahlon@martini.nu>
Copyright (c) 2008-2011, Michael Granger and Mahlon E. Smith All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the author/s, nor the names of the project's contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Create a new Treequel::Schema from the specified
hash
. The hash
should be of the same form as the
one returned by LDAP::Conn.schema, i.e., a Hash of Arrays associated with
the keys "objectClasses", "ldapSyntaxes", "matchingRuleUse",
"attributeTypes", and "matchingRules".
# File lib/treequel/schema.rb, line 174 def initialize( hash ) @object_classes = self.parse_objectclasses( hash['objectClasses'] || [] ) @attribute_types = self.parse_attribute_types( hash['attributeTypes'] || [] ) @ldap_syntaxes = self.parse_ldap_syntaxes( hash['ldapSyntaxes'] || [] ) @matching_rules = self.parse_matching_rules( hash['matchingRules'] || [] ) @matching_rule_uses = self.parse_matching_rule_uses( hash['matchingRuleUse'] || [] ) end
Return a description of the given oids
suitable for inclusion
in an RFC4512-style schema description entry.
# File lib/treequel/schema.rb, line 155 def self::oids( *oids ) oids.flatten! if oids.length > 1 return "( %s )" % [ oids.join(" $ ") ] else return oids.first end end
Parse the given short names
string (a 'qdescrs' in the BNF)
into an Array of zero or more Strings.
# File lib/treequel/schema.rb, line 94 def self::parse_names( names ) # Treequel.logger.debug " parsing NAME attribute from: %p" % [ names ] # Unspecified if names.nil? # Treequel.logger.debug " no NAME attribute" return [] # Multi-value elsif names =~ /#{LPAREN} #{WSP} (#{QDESCRLIST}) #{WSP} #{RPAREN}/ # Treequel.logger.debug " parsing a NAME list from %p" % [ $1 ] return $1.scan( QDESCR ).collect {|qd| qd[1..-2].untaint.to_sym } # Single-value else # Return the name without the quotes # Treequel.logger.debug " dequoting a single NAME" return [ names[1..-2].untaint.to_sym ] end end
Parse a single OID into either a numeric OID string or a Symbol.
# File lib/treequel/schema.rb, line 83 def self::parse_oid( oidstring ) if oidstring =~ NUMERICOID return oidstring.untaint else return oidstring.untaint.to_sym end end
Parse the given oidstring
into an Array of OIDs, with Strings
for numeric OIDs and Symbols for aliases.
# File lib/treequel/schema.rb, line 58 def self::parse_oids( oidstring ) return [] unless oidstring unless /^ #{OIDS} $/.match( oidstring.strip ) raise Treequel::ParseError, "couldn't find an OIDLIST in %p" % [ oidstring ] end oids = $MATCH # Treequel.logger.debug " found OIDs: %p" % [ oids ] # If it's an OIDLIST, strip off leading and trailing parens and whitespace, then split # on ' $ ' and parse each OID if oids.include?( '$' ) parse_oid = self.method( :parse_oid ) return $MATCH[1..-2].strip.split( /#{WSP} #{DOLLAR} #{WSP}/ ).collect( &parse_oid ) else return [ self.parse_oid(oids) ] end end
Return a description of the given descriptors
suitable for
inclusion in an RFC4512-style schema description entry.
# File lib/treequel/schema.rb, line 126 def self::qdescrs( *descriptors ) descriptors.flatten! if descriptors.length > 1 return "( %s )" % [ descriptors.collect {|str| self.qdstring(str) }.join(" ") ] else return self.qdstring( descriptors.first ) end end
Escape and quote the specified string
according to the rules
in RFC4512/2252.
# File lib/treequel/schema.rb, line 148 def self::qdstring( string ) return "'%s'" % [ string.to_s.gsub(/\\/, '\\5c').gsub(/'/, '\\27') ] end
Set the strict-parsing flag
. Setting this to a
true
value causes schema-parsing errors to be propagated to
the caller instead of handled by the constructor, which is the default
behavior.
# File lib/treequel/schema.rb, line 45 def self::strict_parse_mode=( newval ) @strict_parse_mode = newval ? true : false end
Test whether or not strict-parsing mode is in effect.
# File lib/treequel/schema.rb, line 51 def self::strict_parse_mode? return @strict_parse_mode ? true : false end
Return a new string which is desc
with quotes stripped and any
escaped characters un-escaped.
# File lib/treequel/schema.rb, line 118 def self::unquote_desc( desc ) return nil if desc.nil? return desc.gsub( QQ, "'" ).gsub( QS, '\' )[ 1..-2 ] end
Return a human-readable representation of the object suitable for debugging.
# File lib/treequel/schema.rb, line 225 def inspect return %Q{#<%s:0x%0x %s>} % [ self.class.name, self.object_id / 2, self.ivar_descriptions.join( ', ' ), ] end
Return the Treequel::Schema::AttributeType objects that correspond to the operational attributes that are supported by the directory.
# File lib/treequel/schema.rb, line 211 def operational_attribute_types return self.attribute_types.values.find_all {|attrtype| attrtype.operational? }.uniq end
Return the schema as a human-readable english string.
# File lib/treequel/schema.rb, line 217 def to_s parts = [ "Schema:" ] parts << self.ivar_descriptions.collect {|desc| ' ' + desc } return parts.join( $/ ) end
Return descriptions of the schema's artifacts, and how many of each it has.
# File lib/treequel/schema.rb, line 350 def ivar_descriptions self.instance_variables.sort.collect do |ivar| len = self.instance_variable_get( ivar ).length "%d %s" % [ len, ivar.to_s.gsub(/_/, ' ')[1..-1] ] end end
Parse the given attributeType descriptions
into Treequel::Schema::AttributeType
objects and return them as a Hash keyed both by numeric OID and by each of
its NAME attributes (if it has any).
# File lib/treequel/schema.rb, line 263 def parse_attribute_types( descriptions ) return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc| begin attrtype = Treequel::Schema::AttributeType.parse( self, desc ) table[ attrtype.oid ] = attrtype attrtype.names.inject( table ) {|h, name| h[name] = attrtype; h } rescue Treequel::ParseError => err if self.class.strict_parse_mode? raise else self.log.warn( err.message ) end end table end end
Parse the given LDAP syntax
descriptions
into Treequel::Schema::LDAPSyntax objects and
return them as a Hash keyed by numeric OID.
# File lib/treequel/schema.rb, line 284 def parse_ldap_syntaxes( descriptions ) descriptions ||= [] return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc| begin syntax = Treequel::Schema::LDAPSyntax.parse( self, desc ) table[ syntax.oid ] = syntax rescue Treequel::ParseError => err if self.class.strict_parse_mode? raise else self.log.warn( err.message ) end end table end end
Parse the given matchingRuleUse descriptions
into Treequel::Schema::MatchingRuleUse
objects and return them as a Hash keyed both by numeric OID and by each of
its NAME attributes (if it has any).
# File lib/treequel/schema.rb, line 329 def parse_matching_rule_uses( descriptions ) descriptions ||= [] return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc| begin ruleuse = Treequel::Schema::MatchingRuleUse.parse( self, desc ) table[ ruleuse.oid ] = ruleuse ruleuse.names.inject( table ) {|h, name| h[name] = ruleuse; h } rescue Treequel::ParseError => err if self.class.strict_parse_mode? raise else self.log.warn( err.message ) end end table end end
Parse the given matchingRule descriptions
into Treequel::Schema::MatchingRule objects
and return them as a Hash keyed both by numeric OID and by each of its NAME
attributes (if it has any).
# File lib/treequel/schema.rb, line 306 def parse_matching_rules( descriptions ) descriptions ||= [] return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc| begin rule = Treequel::Schema::MatchingRule.parse( self, desc ) table[ rule.oid ] = rule rule.names.inject( table ) {|h, name| h[name] = rule; h } rescue Treequel::ParseError => err if self.class.strict_parse_mode? raise else self.log.warn( err.message ) end end table end end
Parse the given objectClass descriptions
into Treequel::Schema::ObjectClass objects,
and return them as a Hash keyed both by numeric OID and by each of its NAME
attributes (if it has any).
# File lib/treequel/schema.rb, line 241 def parse_objectclasses( descriptions ) return descriptions.inject( Treequel::Schema::Table.new ) do |table, desc| begin oc = Treequel::Schema::ObjectClass.parse( self, desc ) table[ oc.oid ] = oc oc.names.inject( table ) {|h, name| h[name] = oc; h } rescue Treequel::ParseError => err if self.class.strict_parse_mode? raise else self.log.warn( err.message ) end end table end end