|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846 |
- """
- """
-
- # Created on 2013.09.11
- #
- # Author: Giovanni Cannata
- #
- # Copyright 2013 - 2018 Giovanni Cannata
- #
- # This file is part of ldap3.
- #
- # ldap3 is free software: you can redistribute it and/or modify
- # it under the terms of the GNU Lesser General Public License as published
- # by the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # ldap3 is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU Lesser General Public License for more details.
- #
- # You should have received a copy of the GNU Lesser General Public License
- # along with ldap3 in the COPYING and COPYING.LESSER files.
- # If not, see <http://www.gnu.org/licenses/>.
-
- from os import linesep
- import re
- import json
-
- from .oid import CLASS_ABSTRACT, CLASS_STRUCTURAL, CLASS_AUXILIARY, ATTRIBUTE_USER_APPLICATION, \
- ATTRIBUTE_DIRECTORY_OPERATION, ATTRIBUTE_DISTRIBUTED_OPERATION, ATTRIBUTE_DSA_OPERATION
- from .. import SEQUENCE_TYPES, STRING_TYPES, get_config_parameter
- from ..utils.conv import escape_bytes, json_hook, check_json_dict, format_json, to_unicode
- from ..utils.ciDict import CaseInsensitiveDict
- from ..protocol.formatters.standard import format_attribute_values
- from .oid import Oids, decode_oids, decode_syntax, oid_to_string
- from ..core.exceptions import LDAPSchemaError, LDAPDefinitionError
-
-
- def constant_to_class_kind(value):
- if value == CLASS_STRUCTURAL:
- return 'Structural'
- elif value == CLASS_ABSTRACT:
- return 'Abstract'
- elif value == CLASS_AUXILIARY:
- return 'Auxiliary'
- else:
- return '<unknown>'
-
-
- def constant_to_attribute_usage(value):
- if value == ATTRIBUTE_USER_APPLICATION:
- return 'User Application'
- elif value == ATTRIBUTE_DIRECTORY_OPERATION:
- return "Directory operation"
- elif value == ATTRIBUTE_DISTRIBUTED_OPERATION:
- return 'Distributed operation'
- elif value == ATTRIBUTE_DSA_OPERATION:
- return 'DSA operation'
- else:
- return 'unknown'
-
-
- def attribute_usage_to_constant(value):
- if value == 'userApplications':
- return ATTRIBUTE_USER_APPLICATION
- elif value == 'directoryOperation':
- return ATTRIBUTE_DIRECTORY_OPERATION
- elif value == 'distributedOperation':
- return ATTRIBUTE_DISTRIBUTED_OPERATION
- elif value == 'dsaOperation':
- return ATTRIBUTE_DSA_OPERATION
- else:
- return 'unknown'
-
-
- def quoted_string_to_list(quoted_string):
- string = quoted_string.strip()
- if not string:
- return list()
-
- if string[0] == '(' and string[-1] == ')':
- string = string[1:-1]
- elements = string.split("'")
- # return [check_escape(element.strip("'").strip()) for element in elements if element.strip()]
- return [element.strip("'").strip() for element in elements if element.strip()]
-
-
- def oids_string_to_list(oid_string):
- string = oid_string.strip()
- if string[0] == '(' and string[-1] == ')':
- string = string[1:-1]
- elements = string.split('$')
- return [element.strip() for element in elements if element.strip()]
-
-
- def extension_to_tuple(extension_string):
- string = extension_string.strip()
- name, _, values = string.partition(' ')
- return name, quoted_string_to_list(values)
-
-
- def list_to_string(list_object):
- if not isinstance(list_object, SEQUENCE_TYPES):
- return list_object
-
- r = ''
- for element in list_object:
- r += (list_to_string(element) if isinstance(element, SEQUENCE_TYPES) else str(element)) + ', '
-
- return r[:-2] if r else ''
-
-
- class BaseServerInfo(object):
- def __init__(self, raw_attributes):
- self.raw = dict(raw_attributes)
-
- @classmethod
- def from_json(cls, json_definition, schema=None, custom_formatter=None):
- conf_case_insensitive_schema = get_config_parameter('CASE_INSENSITIVE_SCHEMA_NAMES')
- definition = json.loads(json_definition, object_hook=json_hook)
- if 'raw' not in definition or 'type' not in definition:
- raise LDAPDefinitionError('invalid JSON definition')
-
- if conf_case_insensitive_schema:
- attributes = CaseInsensitiveDict()
- else:
- attributes = dict()
-
- if schema:
- for attribute in definition['raw']:
- # attributes[attribute] = format_attribute_values(schema, check_escape(attribute), [check_escape(value) for value in definition['raw'][attribute]], custom_formatter)
- attributes[attribute] = format_attribute_values(schema, attribute, [value for value in definition['raw'][attribute]], custom_formatter)
- else:
- for attribute in definition['raw']:
- # attributes[attribute] = [check_escape(value) for value in definition['raw'][attribute]]
- attributes[attribute] = [value for value in definition['raw'][attribute]]
-
- if cls.__name__ != definition['type']:
- raise LDAPDefinitionError('JSON info not of type ' + cls.__name__)
-
- if definition['type'] == 'DsaInfo':
- return DsaInfo(attributes, definition['raw'])
- elif definition['type'] == 'SchemaInfo':
- if 'schema_entry' not in definition:
- raise LDAPDefinitionError('invalid schema in JSON')
- return SchemaInfo(definition['schema_entry'], attributes, definition['raw'])
-
- raise LDAPDefinitionError('invalid Info type ' + str(definition['type']) + ' in JSON definition')
-
- @classmethod
- def from_file(cls, target, schema=None, custom_formatter=None):
- if isinstance(target, STRING_TYPES):
- target = open(target, 'r')
-
- new = cls.from_json(target.read(), schema=schema, custom_formatter=custom_formatter)
- target.close()
- return new
-
- def to_file(self,
- target,
- indent=4,
- sort=True):
- if isinstance(target, STRING_TYPES):
- target = open(target, 'w+')
-
- target.writelines(self.to_json(indent=indent, sort=sort))
- target.close()
-
- def __str__(self):
- return self.__repr__()
-
- def to_json(self,
- indent=4,
- sort=True):
- json_dict = dict()
- json_dict['type'] = self.__class__.__name__
- json_dict['raw'] = self.raw
-
- if isinstance(self, SchemaInfo):
- json_dict['schema_entry'] = self.schema_entry
- elif isinstance(self, DsaInfo):
- pass
- else:
- raise LDAPDefinitionError('unable to convert ' + str(self) + ' to JSON')
-
- if str is bytes: # Python 2
- check_json_dict(json_dict)
-
- return json.dumps(json_dict, ensure_ascii=False, sort_keys=sort, indent=indent, check_circular=True, default=format_json, separators=(',', ': '))
-
-
- class DsaInfo(BaseServerInfo):
- """
- This class contains info about the ldap server (DSA) read from DSE
- as defined in RFC4512 and RFC3045. Unknown attributes are stored in the "other" dict
- """
-
- def __init__(self, attributes, raw_attributes):
- BaseServerInfo.__init__(self, raw_attributes)
- self.alt_servers = attributes.pop('altServer', None)
- self.naming_contexts = attributes.pop('namingContexts', None)
- self.supported_controls = decode_oids(attributes.pop('supportedControl', None))
- self.supported_extensions = decode_oids(attributes.pop('supportedExtension', None))
- self.supported_features = decode_oids(attributes.pop('supportedFeatures', None)) + decode_oids(attributes.pop('supportedCapabilities', None))
- self.supported_ldap_versions = attributes.pop('supportedLDAPVersion', None)
- self.supported_sasl_mechanisms = attributes.pop('supportedSASLMechanisms', None)
- self.vendor_name = attributes.pop('vendorName', None)
- self.vendor_version = attributes.pop('vendorVersion', None)
- self.schema_entry = attributes.pop('subschemaSubentry', None)
- self.other = attributes # remaining schema definition attributes not in RFC4512
-
- def __repr__(self):
- r = 'DSA info (from DSE):' + linesep
- if self.supported_ldap_versions:
- if isinstance(self.supported_ldap_versions, SEQUENCE_TYPES):
- r += (' Supported LDAP versions: ' + ', '.join([str(s) for s in self.supported_ldap_versions])) if self.supported_ldap_versions else ''
- else:
- r += (' Supported LDAP versions: ' + str(self.supported_ldap_versions))
- r += linesep
- if self.naming_contexts:
- if isinstance(self.naming_contexts, SEQUENCE_TYPES):
- r += (' Naming contexts: ' + linesep + linesep.join([' ' + str(s) for s in self.naming_contexts])) if self.naming_contexts else ''
- else:
- r += (' Naming contexts: ' + str(self.naming_contexts))
- r += linesep
- if self.alt_servers:
- if isinstance(self.alt_servers, SEQUENCE_TYPES):
- r += (' Alternative servers: ' + linesep + linesep.join([' ' + str(s) for s in self.alt_servers])) if self.alt_servers else ''
- else:
- r += (' Alternative servers: ' + str(self.alt_servers))
- r += linesep
- if self.supported_controls:
- if isinstance(self.supported_controls, SEQUENCE_TYPES):
- r += (' Supported controls: ' + linesep + linesep.join([' ' + oid_to_string(s) for s in self.supported_controls])) if self.supported_controls else ''
- else:
- r += (' Supported controls: ' + str(self.supported_controls))
- r += linesep
- if self.supported_extensions:
- if isinstance(self.supported_extensions, SEQUENCE_TYPES):
- r += (' Supported extensions: ' + linesep + linesep.join([' ' + oid_to_string(s) for s in self.supported_extensions])) if self.supported_extensions else ''
- else:
- r += (' Supported extensions: ' + str(self.supported_extensions))
- r += linesep
- if self.supported_features:
- if self.supported_features:
- if isinstance(self.supported_features, SEQUENCE_TYPES):
- r += (' Supported features: ' + linesep + linesep.join([' ' + oid_to_string(s) for s in self.supported_features])) if self.supported_features else ''
- else:
- r += (' Supported features: ' + str(self.supported_features))
- r += linesep
- if self.supported_sasl_mechanisms:
- if isinstance(self.supported_sasl_mechanisms, SEQUENCE_TYPES):
- r += (' Supported SASL mechanisms: ' + linesep + ' ' + ', '.join([str(s) for s in self.supported_sasl_mechanisms])) if self.supported_sasl_mechanisms else ''
- else:
- r += (' Supported SASL mechanisms: ' + str(self.supported_sasl_mechanisms))
- r += linesep
- if self.schema_entry:
- if isinstance(self.schema_entry, SEQUENCE_TYPES):
- r += (' Schema entry: ' + linesep + linesep.join([' ' + str(s) for s in self.schema_entry])) if self.schema_entry else ''
- else:
- r += (' Schema entry: ' + str(self.schema_entry))
- r += linesep
- if self.vendor_name:
- if isinstance(self.vendor_name, SEQUENCE_TYPES) and len(self.vendor_name) == 1:
- r += 'Vendor name: ' + self.vendor_name[0]
- else:
- r += 'Vendor name: ' + str(self.vendor_name)
- r += linesep
- if self.vendor_version:
- if isinstance(self.vendor_version, SEQUENCE_TYPES) and len(self.vendor_version) == 1:
- r += 'Vendor version: ' + self.vendor_version[0]
- else:
- r += 'Vendor version: ' + str(self.vendor_version)
- r += linesep
- r += 'Other:' + linesep
- for k, v in self.other.items():
- r += ' ' + str(k) + ': ' + linesep
- try:
- r += (linesep.join([' ' + str(s) for s in v])) if isinstance(v, SEQUENCE_TYPES) else str(v)
- except UnicodeDecodeError:
- r += (linesep.join([' ' + str(escape_bytes(s)) for s in v])) if isinstance(v, SEQUENCE_TYPES) else str(escape_bytes(v))
- r += linesep
- return r
-
-
- class SchemaInfo(BaseServerInfo):
- """
- This class contains info about the ldap server schema read from an entry (default entry is DSE)
- as defined in RFC4512. Unknown attributes are stored in the "other" dict
- """
-
- def __init__(self, schema_entry, attributes, raw_attributes):
- BaseServerInfo.__init__(self, raw_attributes)
- self.schema_entry = schema_entry
- self.create_time_stamp = attributes.pop('createTimestamp', None)
- self.modify_time_stamp = attributes.pop('modifyTimestamp', None)
- self.attribute_types = AttributeTypeInfo.from_definition(attributes.pop('attributeTypes', []))
- self.object_classes = ObjectClassInfo.from_definition(attributes.pop('objectClasses', []))
- self.matching_rules = MatchingRuleInfo.from_definition(attributes.pop('matchingRules', []))
- self.matching_rule_uses = MatchingRuleUseInfo.from_definition(attributes.pop('matchingRuleUse', []))
- self.dit_content_rules = DitContentRuleInfo.from_definition(attributes.pop('dITContentRules', []))
- self.dit_structure_rules = DitStructureRuleInfo.from_definition(attributes.pop('dITStructureRules', []))
- self.name_forms = NameFormInfo.from_definition(attributes.pop('nameForms', []))
- self.ldap_syntaxes = LdapSyntaxInfo.from_definition(attributes.pop('ldapSyntaxes', []))
- self.other = attributes # remaining schema definition attributes not in RFC4512
-
- # links attributes to class objects
- if self.object_classes and self.attribute_types:
- for object_class in self.object_classes: # CaseInsensitiveDict return keys while iterating
- for attribute in self.object_classes[object_class].must_contain:
- try:
- self.attribute_types[attribute].mandatory_in.append(object_class)
- except KeyError:
- pass
- for attribute in self.object_classes[object_class].may_contain:
- try:
- self.attribute_types[attribute].optional_in.append(object_class)
- except KeyError:
- pass
-
- def is_valid(self):
- if self.object_classes or self.attribute_types or self.matching_rules or self.matching_rule_uses or self.dit_content_rules or self.dit_structure_rules or self.name_forms or self.ldap_syntaxes:
- return True
- return False
-
- def __repr__(self):
- r = 'DSA Schema from: ' + self.schema_entry
- r += linesep
- if isinstance(self.attribute_types, SEQUENCE_TYPES):
- r += (' Attribute types:' + linesep + ' ' + ', '.join([str(self.attribute_types[s]) for s in self.attribute_types])) if self.attribute_types else ''
- else:
- r += (' Attribute types:' + str(self.attribute_types))
- r += linesep
- if isinstance(self.object_classes, SEQUENCE_TYPES):
- r += (' Object classes:' + linesep + ' ' + ', '.join([str(self.object_classes[s]) for s in self.object_classes])) if self.object_classes else ''
- else:
- r += (' Object classes:' + str(self.object_classes))
- r += linesep
- if isinstance(self.matching_rules, SEQUENCE_TYPES):
- r += (' Matching rules:' + linesep + ' ' + ', '.join([str(self.matching_rules[s]) for s in self.matching_rules])) if self.matching_rules else ''
- else:
- r += (' Matching rules:' + str(self.matching_rules))
- r += linesep
- if isinstance(self.matching_rule_uses, SEQUENCE_TYPES):
- r += (' Matching rule uses:' + linesep + ' ' + ', '.join([str(self.matching_rule_uses[s]) for s in self.matching_rule_uses])) if self.matching_rule_uses else ''
- else:
- r += (' Matching rule uses:' + str(self.matching_rule_uses))
- r += linesep
- if isinstance(self.dit_content_rules, SEQUENCE_TYPES):
- r += (' DIT content rules:' + linesep + ' ' + ', '.join([str(self.dit_content_rules[s]) for s in self.dit_content_rules])) if self.dit_content_rules else ''
- else:
- r += (' DIT content rules:' + str(self.dit_content_rules))
- r += linesep
- if isinstance(self.dit_structure_rules, SEQUENCE_TYPES):
- r += (' DIT structure rules:' + linesep + ' ' + ', '.join([str(self.dit_structure_rules[s]) for s in self.dit_structure_rules])) if self.dit_structure_rules else ''
- else:
- r += (' DIT structure rules:' + str(self.dit_structure_rules))
- r += linesep
- if isinstance(self.name_forms, SEQUENCE_TYPES):
- r += (' Name forms:' + linesep + ' ' + ', '.join([str(self.name_forms[s]) for s in self.name_forms])) if self.name_forms else ''
- else:
- r += (' Name forms:' + str(self.name_forms))
- r += linesep
- if isinstance(self.ldap_syntaxes, SEQUENCE_TYPES):
- r += (' LDAP syntaxes:' + linesep + ' ' + ', '.join([str(self.ldap_syntaxes[s]) for s in self.ldap_syntaxes])) if self.ldap_syntaxes else ''
- else:
- r += (' LDAP syntaxes:' + str(self.ldap_syntaxes))
- r += linesep
- r += 'Other:' + linesep
-
- for k, v in self.other.items():
- r += ' ' + str(k) + ': ' + linesep
- try:
- r += (linesep.join([' ' + str(s) for s in v])) if isinstance(v, SEQUENCE_TYPES) else str(v)
- except UnicodeDecodeError:
- r += (linesep.join([' ' + str(escape_bytes(s)) for s in v])) if isinstance(v, SEQUENCE_TYPES) else str(escape_bytes(v))
- r += linesep
- return r
-
-
- class BaseObjectInfo(object):
- """
- Base class for objects defined in the schema as per RFC4512
- """
-
- def __init__(self,
- oid=None,
- name=None,
- description=None,
- obsolete=False,
- extensions=None,
- experimental=None,
- definition=None):
-
- self.oid = oid
- self.name = name
- self.description = description
- self.obsolete = obsolete
- self.extensions = extensions
- self.experimental = experimental
- self.raw_definition = definition
- self._oid_info = None
-
- @property
- def oid_info(self):
- if self._oid_info is None and self.oid:
- self._oid_info = Oids.get(self.oid, '')
-
- return self._oid_info if self._oid_info else None
-
- def __str__(self):
- return self.__repr__()
-
- def __repr__(self):
- r = ': ' + self.oid
- r += ' [OBSOLETE]' if self.obsolete else ''
- r += (linesep + ' Short name: ' + list_to_string(self.name)) if self.name else ''
- r += (linesep + ' Description: ' + self.description) if self.description else ''
- r += '<__desc__>'
- r += (linesep + ' Extensions:' + linesep + linesep.join([' ' + s[0] + ': ' + list_to_string(s[1]) for s in self.extensions])) if self.extensions else ''
- r += (linesep + ' Experimental:' + linesep + linesep.join([' ' + s[0] + ': ' + list_to_string(s[1]) for s in self.experimental])) if self.experimental else ''
- r += (linesep + ' OidInfo: ' + str(self.oid_info)) if self.oid_info else ''
- r += linesep
- return r
-
- @classmethod
- def from_definition(cls, definitions):
- conf_case_insensitive_schema = get_config_parameter('CASE_INSENSITIVE_SCHEMA_NAMES')
- conf_ignore_malformed_schema = get_config_parameter('IGNORE_MALFORMED_SCHEMA')
-
- ret_dict = CaseInsensitiveDict() if conf_case_insensitive_schema else dict()
-
- if not definitions:
- return CaseInsensitiveDict() if conf_case_insensitive_schema else dict()
-
- for object_definition in definitions:
- object_definition = to_unicode(object_definition.strip(), from_server=True)
- if object_definition[0] == '(' and object_definition[-1] == ')':
- if cls is MatchingRuleInfo:
- pattern = '| SYNTAX '
- elif cls is ObjectClassInfo:
- pattern = '| SUP | ABSTRACT| STRUCTURAL| AUXILIARY| MUST | MAY '
- elif cls is AttributeTypeInfo:
- pattern = '| SUP | EQUALITY | ORDERING | SUBSTR | SYNTAX | SINGLE-VALUE| COLLECTIVE| NO-USER-MODIFICATION| USAGE '
- elif cls is MatchingRuleUseInfo:
- pattern = '| APPLIES '
- elif cls is LdapSyntaxInfo:
- pattern = ''
- elif cls is DitContentRuleInfo:
- pattern = '| AUX | MUST | MAY | NOT '
- elif cls is DitStructureRuleInfo:
- pattern = '| FORM | SUP '
- elif cls is NameFormInfo:
- pattern = '| OC | MUST | MAY '
- else:
- raise LDAPSchemaError('unknown schema definition class')
-
- splitted = re.split('( NAME | DESC | OBSOLETE| X-| E-' + pattern + ')', object_definition[1:-1])
- values = splitted[::2]
- separators = splitted[1::2]
- separators.insert(0, 'OID')
- defs = list(zip(separators, values))
- object_def = cls()
- for d in defs:
- key = d[0].strip()
- value = d[1].strip()
- if key == 'OID':
- object_def.oid = value
- elif key == 'NAME':
- object_def.name = quoted_string_to_list(value)
- elif key == 'DESC':
- object_def.description = value.strip("'")
- elif key == 'OBSOLETE':
- object_def.obsolete = True
- elif key == 'SYNTAX':
- object_def.syntax = oids_string_to_list(value)
- elif key == 'SUP':
- object_def.superior = oids_string_to_list(value)
- elif key == 'ABSTRACT':
- object_def.kind = CLASS_ABSTRACT
- elif key == 'STRUCTURAL':
- object_def.kind = CLASS_STRUCTURAL
- elif key == 'AUXILIARY':
- object_def.kind = CLASS_AUXILIARY
- elif key == 'MUST':
- object_def.must_contain = oids_string_to_list(value)
- elif key == 'MAY':
- object_def.may_contain = oids_string_to_list(value)
- elif key == 'EQUALITY':
- object_def.equality = oids_string_to_list(value)
- elif key == 'ORDERING':
- object_def.ordering = oids_string_to_list(value)
- elif key == 'SUBSTR':
- object_def.substr = oids_string_to_list(value)
- elif key == 'SINGLE-VALUE':
- object_def.single_value = True
- elif key == 'COLLECTIVE':
- object_def.collective = True
- elif key == 'NO-USER-MODIFICATION':
- object_def.no_user_modification = True
- elif key == 'USAGE':
- object_def.usage = attribute_usage_to_constant(value)
- elif key == 'APPLIES':
- object_def.apply_to = oids_string_to_list(value)
- elif key == 'AUX':
- object_def.auxiliary_classes = oids_string_to_list(value)
- elif key == 'FORM':
- object_def.name_form = oids_string_to_list(value)
- elif key == 'OC':
- object_def.object_class = oids_string_to_list(value)
- elif key == 'NOT':
- object_def.not_contains = oids_string_to_list(value)
- elif key == 'X-':
- if not object_def.extensions:
- object_def.extensions = []
- object_def.extensions.append(extension_to_tuple('X-' + value))
- elif key == 'E-':
- if not object_def.experimental:
- object_def.experimental = []
- object_def.experimental.append(extension_to_tuple('E-' + value))
- else:
- if not conf_ignore_malformed_schema:
- raise LDAPSchemaError('malformed schema definition key:' + key + ' - use get_info=NONE in Server definition')
- else:
- return CaseInsensitiveDict() if conf_case_insensitive_schema else dict()
- object_def.raw_definition = object_definition
- if hasattr(object_def, 'syntax') and object_def.syntax and len(object_def.syntax) == 1:
- object_def.min_length = None
- if object_def.syntax[0].endswith('}'):
- try:
- object_def.min_length = int(object_def.syntax[0][object_def.syntax[0].index('{') + 1:-1])
- object_def.syntax[0] = object_def.syntax[0][:object_def.syntax[0].index('{')]
- except Exception:
- pass
- else:
- object_def.min_length = None
- object_def.syntax[0] = object_def.syntax[0].strip("'")
- object_def.syntax = object_def.syntax[0]
- if hasattr(object_def, 'name') and object_def.name:
- for name in object_def.name:
- ret_dict[name] = object_def
- else:
- ret_dict[object_def.oid] = object_def
-
- else:
- if not conf_ignore_malformed_schema:
- raise LDAPSchemaError('malformed schema definition, use get_info=NONE in Server definition')
- else:
- return CaseInsensitiveDict() if conf_case_insensitive_schema else dict()
- return ret_dict
-
-
- class MatchingRuleInfo(BaseObjectInfo):
- """
- As per RFC 4512 (4.1.3)
- """
-
- def __init__(self,
- oid=None,
- name=None,
- description=None,
- obsolete=False,
- syntax=None,
- extensions=None,
- experimental=None,
- definition=None):
-
- BaseObjectInfo.__init__(self,
- oid=oid,
- name=name,
- description=description,
- obsolete=obsolete,
- extensions=extensions,
- experimental=experimental,
- definition=definition)
- self.syntax = syntax
-
- def __repr__(self):
- r = (linesep + ' Syntax: ' + list_to_string(self.syntax)) if self.syntax else ''
- return 'Matching rule' + BaseObjectInfo.__repr__(self).replace('<__desc__>', r)
-
-
- class MatchingRuleUseInfo(BaseObjectInfo):
- """
- As per RFC 4512 (4.1.4)
- """
-
- def __init__(self,
- oid=None,
- name=None,
- description=None,
- obsolete=False,
- apply_to=None,
- extensions=None,
- experimental=None,
- definition=None):
- BaseObjectInfo.__init__(self,
- oid=oid,
- name=name,
- description=description,
- obsolete=obsolete,
- extensions=extensions,
- experimental=experimental,
- definition=definition)
- self.apply_to = apply_to
-
- def __repr__(self):
- r = (linesep + ' Apply to: ' + list_to_string(self.apply_to)) if self.apply_to else ''
- return 'Matching rule use' + BaseObjectInfo.__repr__(self).replace('<__desc__>', r)
-
-
- class ObjectClassInfo(BaseObjectInfo):
- """
- As per RFC 4512 (4.1.1)
- """
-
- def __init__(self,
- oid=None,
- name=None,
- description=None,
- obsolete=False,
- superior=None,
- kind=None,
- must_contain=None,
- may_contain=None,
- extensions=None,
- experimental=None,
- definition=None):
-
- BaseObjectInfo.__init__(self,
- oid=oid,
- name=name,
- description=description,
- obsolete=obsolete,
- extensions=extensions,
- experimental=experimental,
- definition=definition)
- self.superior = superior
- self.kind = kind
- self.must_contain = must_contain or []
- self.may_contain = may_contain or []
-
- def __repr__(self):
- r = ''
- r += (linesep + ' Type: ' + constant_to_class_kind(self.kind)) if self.kind else ''
- r += (linesep + ' Superior: ' + list_to_string(self.superior)) if self.superior else ''
- r += (linesep + ' Must contain attributes: ' + list_to_string(self.must_contain)) if self.must_contain else ''
- r += (linesep + ' May contain attributes: ' + list_to_string(self.may_contain)) if self.may_contain else ''
- return 'Object class' + BaseObjectInfo.__repr__(self).replace('<__desc__>', r)
-
-
- class AttributeTypeInfo(BaseObjectInfo):
- """
- As per RFC 4512 (4.1.2)
- """
-
- def __init__(self,
- oid=None,
- name=None,
- description=None,
- obsolete=False,
- superior=None,
- equality=None,
- ordering=None,
- substring=None,
- syntax=None,
- min_length=None,
- single_value=False,
- collective=False,
- no_user_modification=False,
- usage=None,
- extensions=None,
- experimental=None,
- definition=None):
-
- BaseObjectInfo.__init__(self,
- oid=oid,
- name=name,
- description=description,
- obsolete=obsolete,
- extensions=extensions,
- experimental=experimental,
- definition=definition)
- self.superior = superior
- self.equality = equality
- self.ordering = ordering
- self.substring = substring
- self.syntax = syntax
- self.min_length = min_length
- self.single_value = single_value
- self.collective = collective
- self.no_user_modification = no_user_modification
- self.usage = usage
- self.mandatory_in = []
- self.optional_in = []
-
- def __repr__(self):
- r = ''
- r += linesep + ' Single value: ' + str(self.single_value)
- r += linesep + ' Collective: True' if self.collective else ''
- r += (linesep + ' Superior: ' + list_to_string(self.superior)) if self.superior else ''
- r += linesep + ' No user modification: True' if self.no_user_modification else ''
- r += (linesep + ' Usage: ' + constant_to_attribute_usage(self.usage)) if self.usage else ''
- r += (linesep + ' Equality rule: ' + list_to_string(self.equality)) if self.equality else ''
- r += (linesep + ' Ordering rule: ' + list_to_string(self.ordering)) if self.ordering else ''
- r += (linesep + ' Substring rule: ' + list_to_string(self.substring)) if self.substring else ''
- r += (linesep + ' Syntax: ' + (self.syntax + (' [' + str(decode_syntax(self.syntax)))) + ']') if self.syntax else ''
- r += (linesep + ' Minimum length: ' + str(self.min_length)) if isinstance(self.min_length, int) else ''
- r += linesep + ' Mandatory in: ' + list_to_string(self.mandatory_in) if self.mandatory_in else ''
- r += linesep + ' Optional in: ' + list_to_string(self.optional_in) if self.optional_in else ''
- return 'Attribute type' + BaseObjectInfo.__repr__(self).replace('<__desc__>', r)
-
-
- class LdapSyntaxInfo(BaseObjectInfo):
- """
- As per RFC 4512 (4.1.5)
- """
-
- def __init__(self,
- oid=None,
- description=None,
- extensions=None,
- experimental=None,
- definition=None):
-
- BaseObjectInfo.__init__(self,
- oid=oid,
- name=None,
- description=description,
- obsolete=False,
- extensions=extensions,
- experimental=experimental,
- definition=definition)
-
- def __repr__(self):
- return 'LDAP syntax' + BaseObjectInfo.__repr__(self).replace('<__desc__>', '')
-
-
- class DitContentRuleInfo(BaseObjectInfo):
- """
- As per RFC 4512 (4.1.6)
- """
-
- def __init__(self,
- oid=None,
- name=None,
- description=None,
- obsolete=False,
- auxiliary_classes=None,
- must_contain=None,
- may_contain=None,
- not_contains=None,
- extensions=None,
- experimental=None,
- definition=None):
-
- BaseObjectInfo.__init__(self,
- oid=oid,
- name=name,
- description=description,
- obsolete=obsolete,
- extensions=extensions,
- experimental=experimental,
- definition=definition)
-
- self.auxiliary_classes = auxiliary_classes
- self.must_contain = must_contain
- self.may_contain = may_contain
- self.not_contains = not_contains
-
- def __repr__(self):
- r = (linesep + ' Auxiliary classes: ' + list_to_string(self.auxiliary_classes)) if self.auxiliary_classes else ''
- r += (linesep + ' Must contain: ' + list_to_string(self.must_contain)) if self.must_contain else ''
- r += (linesep + ' May contain: ' + list_to_string(self.may_contain)) if self.may_contain else ''
- r += (linesep + ' Not contains: ' + list_to_string(self.not_contains)) if self.not_contains else ''
- return 'DIT content rule' + BaseObjectInfo.__repr__(self).replace('<__desc__>', r)
-
-
- class DitStructureRuleInfo(BaseObjectInfo):
- """
- As per RFC 4512 (4.1.7.1)
- """
-
- def __init__(self,
- oid=None,
- name=None,
- description=None,
- obsolete=False,
- name_form=None,
- superior=None,
- extensions=None,
- experimental=None,
- definition=None):
-
- BaseObjectInfo.__init__(self,
- oid=oid,
- name=name,
- description=description,
- obsolete=obsolete,
- extensions=extensions,
- experimental=experimental,
- definition=definition)
- self.superior = superior
- self.name_form = name_form
-
- def __repr__(self):
- r = (linesep + ' Superior rules: ' + list_to_string(self.superior)) if self.superior else ''
- r += (linesep + ' Name form: ' + list_to_string(self.name_form)) if self.name_form else ''
- return 'DIT content rule' + BaseObjectInfo.__repr__(self).replace('<__desc__>', r)
-
-
- class NameFormInfo(BaseObjectInfo):
- """
- As per RFC 4512 (4.1.7.2)
- """
-
- def __init__(self,
- oid=None,
- name=None,
- description=None,
- obsolete=False,
- object_class=None,
- must_contain=None,
- may_contain=None,
- extensions=None,
- experimental=None,
- definition=None):
-
- BaseObjectInfo.__init__(self,
- oid=oid,
- name=name,
- description=description,
- obsolete=obsolete,
- extensions=extensions,
- experimental=experimental,
- definition=definition)
- self.object_class = object_class
- self.must_contain = must_contain
- self.may_contain = may_contain
-
- def __repr__(self):
- r = (linesep + ' Object class: ' + list_to_string(self.object_class)) if self.object_class else ''
- r += (linesep + ' Must contain: ' + list_to_string(self.must_contain)) if self.must_contain else ''
- r += (linesep + ' May contain: ' + list_to_string(self.may_contain)) if self.may_contain else ''
- return 'DIT content rule' + BaseObjectInfo.__repr__(self).replace('<__desc__>', r)
|