From f75d6241291eaa079d01e658efd7d00a60584830 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 10 Feb 2008 00:21:41 +0100 Subject: Start working on python conversion of minschema. (This used to be commit 239a1616644321e2d1e64985ea3f3c4971997228) --- source4/scripting/bin/minschema.py | 660 +++++++++++++++++++++++++++++++++++++ 1 file changed, 660 insertions(+) create mode 100755 source4/scripting/bin/minschema.py (limited to 'source4/scripting/bin/minschema.py') diff --git a/source4/scripting/bin/minschema.py b/source4/scripting/bin/minschema.py new file mode 100755 index 0000000000..0a16cc9886 --- /dev/null +++ b/source4/scripting/bin/minschema.py @@ -0,0 +1,660 @@ +#!/usr/bin/python +# +# work out the minimal schema for a set of objectclasses +# + +import getopt +import optparse +import samba + +parser = optparse.OptionParser("minschema ") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +parser.add_option_group(options.VersionOptions(parser)) +parser.add_option("--verbose", help="Be verbose", action="store_true") +parser.add_option("--dump-classes", action="store_true") +parser.add_option("--dump-attributes", action="store_true") +parser.add_option("--dump-subschema", action="store_true") +parser.add_option("--dump-subschema-auto", action="store_true") + +opts, args = parser.parse_args() +opts.dump_all = True + +if opts.dump_classes: + opts.dump_all = False +if opts.dump_attributes: + opts.dump_all = False +if opts.dump_subschema: + opts.dump_all = False +if dump_subschema_auto: + opts.dump_all = False + opts.dump_subschema = True +if opts.dump_all: + opts.dump_classes = True + opts.dump_attributes = True + opts.dump_subschema = True + opts.dump_subschema_auto = True + +if len(args) != 2: + parser.print_usage() + sys.exit(1) + +(url, classfile) = args + +creds = credopts.get_credentials() +ldb = Ldb(url, credentials=creds) + +objectclasses = [] +attributes = [] +rootDse = {} + +objectclasses_expanded = [] + +# the attributes we need for objectclasses +class_attrs = ["objectClass", + "subClassOf", + "governsID", + "possSuperiors", + "possibleInferiors", + "mayContain", + "mustContain", + "auxiliaryClass", + "rDNAttID", + "showInAdvancedViewOnly", + "adminDisplayName", + "adminDescription", + "objectClassCategory", + "lDAPDisplayName", + "schemaIDGUID", + "systemOnly", + "systemPossSuperiors", + "systemMayContain", + "systemMustContain", + "systemAuxiliaryClass", + "defaultSecurityDescriptor", + "systemFlags", + "defaultHidingValue", + "objectCategory", + "defaultObjectCategory", + + # this attributes are not used by w2k3 + "schemaFlagsEx", + "msDs-IntId", + "msDs-Schema-Extensions", + "classDisplayName", + "isDefunct"] + +attrib_attrs = ["objectClass", + "attributeID", + "attributeSyntax", + "isSingleValued", + "rangeLower", + "rangeUpper", + "mAPIID", + "linkID", + "showInAdvancedViewOnly", + "adminDisplayName", + "oMObjectClass", + "adminDescription", + "oMSyntax", + "searchFlags", + "extendedCharsAllowed", + "lDAPDisplayName", + "schemaIDGUID", + "attributeSecurityGUID", + "systemOnly", + "systemFlags", + "isMemberOfPartialAttributeSet", + "objectCategory", + + # this attributes are not used by w2k3 + "schemaFlagsEx", + "msDs-IntId", + "msDs-Schema-Extensions", + "classDisplayName", + "isEphemeral", + "isDefunct"] + +# +# notes: +# +# objectClassCategory +# 1: structural +# 2: abstract +# 3: auxiliary + +# +# print only if verbose is set +# +def dprintf(text): + if verbose is not None: + print text + +def get_object_cn(ldb, name): + attrs = ["cn"] + + res = ldb.search("(ldapDisplayName=%s)" % name, rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs) + assert len(res) == 1 + + cn = res[0]["cn"] + +# +# create an objectclass object +# +def obj_objectClass(ldb, name): + var o = new Object() + o.name = name + o.cn = get_object_cn(ldb, name) + return o + +# +# create an attribute object +# +def obj_attribute(ldb, name): + var o = new Object() + o.name = name + o.cn = get_object_cn(ldb, name) + return o + + +syntaxmap = dict() + +syntaxmap['2.5.5.1'] = '1.3.6.1.4.1.1466.115.121.1.12' +syntaxmap['2.5.5.2'] = '1.3.6.1.4.1.1466.115.121.1.38' +syntaxmap['2.5.5.3'] = '1.2.840.113556.1.4.1362' +syntaxmap['2.5.5.4'] = '1.2.840.113556.1.4.905' +syntaxmap['2.5.5.5'] = '1.3.6.1.4.1.1466.115.121.1.26' +syntaxmap['2.5.5.6'] = '1.3.6.1.4.1.1466.115.121.1.36' +syntaxmap['2.5.5.7'] = '1.2.840.113556.1.4.903' +syntaxmap['2.5.5.8'] = '1.3.6.1.4.1.1466.115.121.1.7' +syntaxmap['2.5.5.9'] = '1.3.6.1.4.1.1466.115.121.1.27' +syntaxmap['2.5.5.10'] = '1.3.6.1.4.1.1466.115.121.1.40' +syntaxmap['2.5.5.11'] = '1.3.6.1.4.1.1466.115.121.1.24' +syntaxmap['2.5.5.12'] = '1.3.6.1.4.1.1466.115.121.1.15' +syntaxmap['2.5.5.13'] = '1.3.6.1.4.1.1466.115.121.1.43' +syntaxmap['2.5.5.14'] = '1.2.840.113556.1.4.904' +syntaxmap['2.5.5.15'] = '1.2.840.113556.1.4.907' +syntaxmap['2.5.5.16'] = '1.2.840.113556.1.4.906' +syntaxmap['2.5.5.17'] = '1.3.6.1.4.1.1466.115.121.1.40' + +# +# map some attribute syntaxes from some apparently MS specific +# syntaxes to the standard syntaxes +# +def map_attribute_syntax(s): + if syntaxmap.has_key(s): + return syntaxmap[s] + return s + +# +# fix a string DN to use ${SCHEMADN} +# +def fix_dn(dn): + s = strstr(dn, rootDse.schemaNamingContext) + if (s == NULL) { + return dn + } + return substr(dn, 0, strlen(dn) - strlen(s)) + "${SCHEMADN}" + +# +# dump an object as ldif +# +def write_ldif_one(o, attrs): + print "dn: CN=%s,${SCHEMADN}\n" % o["cn"] + for a in attrs: + if not o.has_key(a): + continue + # special case for oMObjectClass, which is a binary object + if a == "oMObjectClass": + print "%s:: %s\n" % (a, o[a]) + continue + v = o[a] + if isinstance(v, str): + v = [v] + for j in v: + print "%s: %s\n" % (a, fix_dn(j)) + print "\n" + +# +# dump an array of objects as ldif +# +def write_ldif(o, attrs): + for i in o: + write_ldif_one(i, attrs) + + +# +# create a testDN based an an example DN +# the idea is to ensure we obey any structural rules +# +def create_testdn(exampleDN): + a = split(",", exampleDN) + a[0] = "CN=TestDN" + return ",".join(a) + +# +# find the properties of an objectclass +# +def find_objectclass_properties(ldb, o): + res = ldb.search( + expression="(ldapDisplayName=%s)" % o.name, + rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, class_attrs) + assert(len(res) == 1) + msg = res[0] + for a in msg: + o[a] = msg[a] + +# +# find the properties of an attribute +# +def find_attribute_properties(ldb, o): + res = ldb.search( + expression="(ldapDisplayName=%s)" % o.name, + rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrib_attrs) + assert(len(res) == 1) + msg = res[0] + for a in msg: + # special case for oMObjectClass, which is a binary object + if a == "oMObjectClass": + o[a] = ldb.encode(msg[a]) + continue + o[a] = msg[a] + +# +# find the auto-created properties of an objectclass. Only works for classes +# that can be created using just a DN and the objectclass +# +def find_objectclass_auto(ldb, o): + if not o.has_key("exampleDN"): + return + testdn = create_testdn(o.exampleDN) + + print "testdn is '%s'\n" % testdn + + ldif = "dn: " + testdn + ldif += "\nobjectClass: " + o.name + try: + ldb.add(ldif) + except LdbError, e: + print "error adding %s: %s\n" % (o.name, e) + print "%s\n" % ldif + return + + res = ldb.search("", testdn, ldb.SCOPE_BASE) + ldb.delete(testdn) + + for a in res.msgs[0]: + attributes[a].autocreate = True + + +# +# look at auxiliary information from a class to intuit the existance of more +# classes needed for a minimal schema +# +def expand_objectclass(ldb, o): + attrs = ["auxiliaryClass", "systemAuxiliaryClass", + "possSuperiors", "systemPossSuperiors", + "subClassOf"] + res = ldb.search( + "(&(objectClass=classSchema)(ldapDisplayName=%s))" % o.name, + rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs) + print "Expanding class %s\n" % o.name + assert(len(res) == 1) + msg = res[0] + for a in attrs: + if not msg.has_key(aname): + continue + list = msg[aname] + if isinstance(list, str): + list = [msg[aname]] + for name in list: + if not objectclasses.has_key(name): + print "Found new objectclass '%s'\n" % name + objectclasses[name] = obj_objectClass(ldb, name) + + +# +# add the must and may attributes from an objectclass to the full list +# of attributes +# +def add_objectclass_attributes(ldb, class): + attrs = ["mustContain", "systemMustContain", + "mayContain", "systemMayContain"] + for aname in attrs: + if not class.has_key(aname): + continue + alist = class[aname] + if isinstance(alist, str): + alist = [alist] + for a in alist: + if not attributes.has_key(a): + attributes[a] = obj_attribute(ldb, a) + + +# +# process an individual record, working out what attributes it has +# +def walk_dn(ldb, dn): + # get a list of all possible attributes for this object + attrs = ["allowedAttributes"] + try: + res = ldb.search("objectClass=*", dn, ldb.SCOPE_BASE, attrs) + except LdbError, e: + print "Unable to fetch allowedAttributes for '%s' - %r\n" % (dn, e) + return + allattrs = res[0]["allowedAttributes"] + try: + res = ldb.search("objectClass=*", dn, ldb.SCOPE_BASE, allattrs) + except LdbError, e: + print "Unable to fetch all attributes for '%s' - %s\n" % (dn, e) + return + msg = res[0] + for a in msg: + if not attributes.has_key(a): + attributes[a] = obj_attribute(ldb, a) + +# +# walk a naming context, looking for all records +# +def walk_naming_context(ldb, namingContext): + try: + res = ldb.search("objectClass=*", namingContext, ldb.SCOPE_DEFAULT, + ["objectClass"]) + except LdbError, e: + print "Unable to fetch objectClasses for '%s' - %s\n" % (namingContext, e) + return + for msg in res: + msg = res.msgs[r]["objectClass"] + for objectClass in msg: + if not objectclasses.has_key(objectClass): + objectclasses[objectClass] = obj_objectClass(ldb, objectClass) + objectclasses[objectClass].exampleDN = res.msgs[r]["dn"] + walk_dn(ldb, res.msgs[r].dn) + +# +# trim the may attributes for an objectClass +# +def trim_objectclass_attributes(ldb, class): + # trim possibleInferiors, + # include only the classes we extracted + if class.has_key("possibleInferiors"): + possinf = class["possibleInferiors"] + newpossinf = [] + if isinstance(possinf, str): + possinf = [possinf] + for x in possinf: + if objectclasses.has_key(x): + newpossinf[n] = x + n++ + class["possibleInferiors"] = newpossinf + + # trim systemMayContain, + # remove duplicates + if class.has_key("systemMayContain"): + sysmay = class["systemMayContain"] + newsysmay = [] + if isinstance(sysmay, str): + sysmay = [sysmay] + for x in sysmay: + dup = False + if newsysmay[0] == undefined) { + newsysmay[0] = x + else: + for (n = 0; n < newsysmay.length; n++) { + if (newsysmay[n] == x) { + dup = True + if not dup: + newsysmay[n] = x + class["systemMayContain"] = newsysmay + + # trim mayContain, + # remove duplicates + if not class.has_key("mayContain"): + may = class["mayContain"] + newmay = [] + if isinstance(may, str): + may = [may] + for x in may: + dup = False + if (newmay[0] == undefined) { + newmay[0] = x + } else { + for (n = 0; n < newmay.length; n++) { + if (newmay[n] == x) { + dup = True + if not dup: + newmay[n] = x + class["mayContain"] = newmay + +# +# load the basic attributes of an objectClass +# +def build_objectclass(ldb, name): + attrs = ["name"] + try: + res = ldb.search( + expression="(&(objectClass=classSchema)(ldapDisplayName=%s))" % name, + rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs) + except LdbError, e: + print "unknown class '%s'\n" % name + return None + if len(res) == 0: + print "unknown class '%s'\n" % name + return None + return obj_objectClass(ldb, name) + +# +# append 2 lists +# +def list_append(a1, a2): + if (a1 == undefined) { + return a2 + if (a2 == undefined) + return a1 + for (i=0;i Date: Sun, 10 Feb 2008 00:56:55 +0100 Subject: More syntax fixes, use more standard python functions. (This used to be commit ea07509b4a9335a3b3fe6f6da1124fd1aab33c96) --- source4/scripting/bin/minschema.py | 575 ++++++++++++++++--------------------- 1 file changed, 247 insertions(+), 328 deletions(-) (limited to 'source4/scripting/bin/minschema.py') diff --git a/source4/scripting/bin/minschema.py b/source4/scripting/bin/minschema.py index 0a16cc9886..fb9d7b05aa 100755 --- a/source4/scripting/bin/minschema.py +++ b/source4/scripting/bin/minschema.py @@ -3,9 +3,10 @@ # work out the minimal schema for a set of objectclasses # -import getopt import optparse import samba +from samba import getopt as options +import sys parser = optparse.OptionParser("minschema ") sambaopts = options.SambaOptions(parser) @@ -28,14 +29,14 @@ if opts.dump_attributes: opts.dump_all = False if opts.dump_subschema: opts.dump_all = False -if dump_subschema_auto: - opts.dump_all = False - opts.dump_subschema = True +if opts.dump_subschema_auto: + opts.dump_all = False + opts.dump_subschema = True if opts.dump_all: - opts.dump_classes = True - opts.dump_attributes = True - opts.dump_subschema = True - opts.dump_subschema_auto = True + opts.dump_classes = True + opts.dump_attributes = True + opts.dump_subschema = True + opts.dump_subschema_auto = True if len(args) != 2: parser.print_usage() @@ -48,9 +49,8 @@ ldb = Ldb(url, credentials=creds) objectclasses = [] attributes = [] -rootDse = {} -objectclasses_expanded = [] +objectclasses_expanded = set() # the attributes we need for objectclasses class_attrs = ["objectClass", @@ -130,33 +130,28 @@ attrib_attrs = ["objectClass", # def dprintf(text): if verbose is not None: - print text + print text def get_object_cn(ldb, name): - attrs = ["cn"] + attrs = ["cn"] - res = ldb.search("(ldapDisplayName=%s)" % name, rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs) - assert len(res) == 1 + res = ldb.search("(ldapDisplayName=%s)" % name, rootDse["schemaNamingContext"], ldb.SCOPE_SUBTREE, attrs) + assert len(res) == 1 - cn = res[0]["cn"] + return res[0]["cn"] -# -# create an objectclass object -# -def obj_objectClass(ldb, name): - var o = new Object() - o.name = name - o.cn = get_object_cn(ldb, name) - return o +class Objectclass: + def __init__(self, ldb, name): + """create an objectclass object""" + self.name = name + self.cn = get_object_cn(ldb, name) -# -# create an attribute object -# -def obj_attribute(ldb, name): - var o = new Object() - o.name = name - o.cn = get_object_cn(ldb, name) - return o + +class Attribute: + def __init__(self, ldb, name): + """create an attribute object""" + self.name = name + self.cn = get_object_cn(ldb, name) syntaxmap = dict() @@ -179,397 +174,330 @@ syntaxmap['2.5.5.15'] = '1.2.840.113556.1.4.907' syntaxmap['2.5.5.16'] = '1.2.840.113556.1.4.906' syntaxmap['2.5.5.17'] = '1.3.6.1.4.1.1466.115.121.1.40' -# -# map some attribute syntaxes from some apparently MS specific -# syntaxes to the standard syntaxes -# + def map_attribute_syntax(s): + """map some attribute syntaxes from some apparently MS specific + syntaxes to the standard syntaxes""" if syntaxmap.has_key(s): - return syntaxmap[s] - return s + return syntaxmap[s] + return s + -# -# fix a string DN to use ${SCHEMADN} -# def fix_dn(dn): - s = strstr(dn, rootDse.schemaNamingContext) - if (s == NULL) { - return dn - } - return substr(dn, 0, strlen(dn) - strlen(s)) + "${SCHEMADN}" + """fix a string DN to use ${SCHEMADN}""" + return dn.replace(rootDse["schemaNamingContext"], "${SCHEMADN}") + -# -# dump an object as ldif -# def write_ldif_one(o, attrs): - print "dn: CN=%s,${SCHEMADN}\n" % o["cn"] + """dump an object as ldif""" + print "dn: CN=%s,${SCHEMADN}\n" % o["cn"] for a in attrs: if not o.has_key(a): - continue - # special case for oMObjectClass, which is a binary object + continue + # special case for oMObjectClass, which is a binary object if a == "oMObjectClass": - print "%s:: %s\n" % (a, o[a]) - continue - v = o[a] + print "%s:: %s\n" % (a, o[a]) + continue + v = o[a] if isinstance(v, str): - v = [v] + v = [v] for j in v: - print "%s: %s\n" % (a, fix_dn(j)) - print "\n" + print "%s: %s\n" % (a, fix_dn(j)) + print "\n" -# -# dump an array of objects as ldif -# def write_ldif(o, attrs): + """dump an array of objects as ldif""" for i in o: - write_ldif_one(i, attrs) + write_ldif_one(i, attrs) -# -# create a testDN based an an example DN -# the idea is to ensure we obey any structural rules -# def create_testdn(exampleDN): - a = split(",", exampleDN) - a[0] = "CN=TestDN" - return ",".join(a) + """create a testDN based an an example DN + the idea is to ensure we obey any structural rules""" + a = exampleDN.split(",") + a[0] = "CN=TestDN" + return ",".join(a) + -# -# find the properties of an objectclass -# def find_objectclass_properties(ldb, o): - res = ldb.search( - expression="(ldapDisplayName=%s)" % o.name, - rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, class_attrs) - assert(len(res) == 1) + """the properties of an objectclass""" + res = ldb.search( + expression="(ldapDisplayName=%s)" % o.name, + basedn=rootDse["schemaNamingContext"], scope=ldb.SCOPE_SUBTREE, attrs=class_attrs) + assert(len(res) == 1) msg = res[0] for a in msg: - o[a] = msg[a] + o[a] = msg[a] -# -# find the properties of an attribute -# def find_attribute_properties(ldb, o): - res = ldb.search( - expression="(ldapDisplayName=%s)" % o.name, - rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrib_attrs) - assert(len(res) == 1) + """find the properties of an attribute""" + res = ldb.search( + expression="(ldapDisplayName=%s)" % o.name, + basedn=rootDse["schemaNamingContext"], scope=ldb.SCOPE_SUBTREE, + attrs=attrib_attrs) + assert(len(res) == 1) msg = res[0] for a in msg: - # special case for oMObjectClass, which is a binary object + # special case for oMObjectClass, which is a binary object if a == "oMObjectClass": - o[a] = ldb.encode(msg[a]) - continue - o[a] = msg[a] + o[a] = ldb.encode(msg[a]) + continue + o[a] = msg[a] + -# -# find the auto-created properties of an objectclass. Only works for classes -# that can be created using just a DN and the objectclass -# def find_objectclass_auto(ldb, o): + """find the auto-created properties of an objectclass. Only works for + classes that can be created using just a DN and the objectclass""" if not o.has_key("exampleDN"): - return - testdn = create_testdn(o.exampleDN) + return + testdn = create_testdn(o.exampleDN) - print "testdn is '%s'\n" % testdn + print "testdn is '%s'\n" % testdn - ldif = "dn: " + testdn - ldif += "\nobjectClass: " + o.name + ldif = "dn: " + testdn + ldif += "\nobjectClass: " + o.name try: ldb.add(ldif) except LdbError, e: print "error adding %s: %s\n" % (o.name, e) - print "%s\n" % ldif + print "%s\n" % ldif return - res = ldb.search("", testdn, ldb.SCOPE_BASE) - ldb.delete(testdn) + res = ldb.search("", testdn, ldb.SCOPE_BASE) + ldb.delete(testdn) for a in res.msgs[0]: - attributes[a].autocreate = True + attributes[a].autocreate = True -# -# look at auxiliary information from a class to intuit the existance of more -# classes needed for a minimal schema -# def expand_objectclass(ldb, o): - attrs = ["auxiliaryClass", "systemAuxiliaryClass", - "possSuperiors", "systemPossSuperiors", - "subClassOf"] - res = ldb.search( - "(&(objectClass=classSchema)(ldapDisplayName=%s))" % o.name, - rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs) - print "Expanding class %s\n" % o.name - assert(len(res) == 1) - msg = res[0] + """look at auxiliary information from a class to intuit the existance of + more classes needed for a minimal schema""" + attrs = ["auxiliaryClass", "systemAuxiliaryClass", + "possSuperiors", "systemPossSuperiors", + "subClassOf"] + res = ldb.search( + expression="(&(objectClass=classSchema)(ldapDisplayName=%s))" % o.name, + basedn=rootDse["schemaNamingContext"], scope=ldb.SCOPE_SUBTREE, + attrs=attrs) + print "Expanding class %s\n" % o.name + assert(len(res) == 1) + msg = res[0] for a in attrs: if not msg.has_key(aname): - continue - list = msg[aname] + continue + list = msg[aname] if isinstance(list, str): - list = [msg[aname]] + list = [msg[aname]] for name in list: if not objectclasses.has_key(name): - print "Found new objectclass '%s'\n" % name - objectclasses[name] = obj_objectClass(ldb, name) + print "Found new objectclass '%s'\n" % name + objectclasses[name] = Objectclass(ldb, name) -# -# add the must and may attributes from an objectclass to the full list -# of attributes -# -def add_objectclass_attributes(ldb, class): - attrs = ["mustContain", "systemMustContain", - "mayContain", "systemMayContain"] +def add_objectclass_attributes(ldb, objectclass): + """add the must and may attributes from an objectclass to the full list + of attributes""" + attrs = ["mustContain", "systemMustContain", + "mayContain", "systemMayContain"] for aname in attrs: - if not class.has_key(aname): - continue - alist = class[aname] + if not objectclass.has_key(aname): + continue + alist = objectclass[aname] if isinstance(alist, str): - alist = [alist] + alist = [alist] for a in alist: if not attributes.has_key(a): - attributes[a] = obj_attribute(ldb, a) + attributes[a] = Attribute(ldb, a) -# -# process an individual record, working out what attributes it has -# def walk_dn(ldb, dn): - # get a list of all possible attributes for this object - attrs = ["allowedAttributes"] + """process an individual record, working out what attributes it has""" + # get a list of all possible attributes for this object + attrs = ["allowedAttributes"] try: res = ldb.search("objectClass=*", dn, ldb.SCOPE_BASE, attrs) except LdbError, e: - print "Unable to fetch allowedAttributes for '%s' - %r\n" % (dn, e) - return - allattrs = res[0]["allowedAttributes"] + print "Unable to fetch allowedAttributes for '%s' - %r\n" % (dn, e) + return + allattrs = res[0]["allowedAttributes"] try: res = ldb.search("objectClass=*", dn, ldb.SCOPE_BASE, allattrs) except LdbError, e: print "Unable to fetch all attributes for '%s' - %s\n" % (dn, e) - return - msg = res[0] + return + msg = res[0] for a in msg: if not attributes.has_key(a): - attributes[a] = obj_attribute(ldb, a) + attributes[a] = Attribute(ldb, a) -# -# walk a naming context, looking for all records -# def walk_naming_context(ldb, namingContext): + """walk a naming context, looking for all records""" try: res = ldb.search("objectClass=*", namingContext, ldb.SCOPE_DEFAULT, ["objectClass"]) except LdbError, e: - print "Unable to fetch objectClasses for '%s' - %s\n" % (namingContext, e) - return + print "Unable to fetch objectClasses for '%s' - %s\n" % (namingContext, e) + return for msg in res: - msg = res.msgs[r]["objectClass"] + msg = res.msgs[r]["objectClass"] for objectClass in msg: if not objectclasses.has_key(objectClass): - objectclasses[objectClass] = obj_objectClass(ldb, objectClass) - objectclasses[objectClass].exampleDN = res.msgs[r]["dn"] - walk_dn(ldb, res.msgs[r].dn) - -# -# trim the may attributes for an objectClass -# -def trim_objectclass_attributes(ldb, class): - # trim possibleInferiors, - # include only the classes we extracted - if class.has_key("possibleInferiors"): - possinf = class["possibleInferiors"] - newpossinf = [] + objectclasses[objectClass] = Objectclass(ldb, objectClass) + objectclasses[objectClass].exampleDN = res.msgs[r]["dn"] + walk_dn(ldb, res.msgs[r].dn) + +def trim_objectclass_attributes(ldb, objectclass): + """trim the may attributes for an objectClass""" + # trim possibleInferiors, + # include only the classes we extracted + if objectclass.has_key("possibleInferiors"): + possinf = objectclass["possibleInferiors"] + newpossinf = [] if isinstance(possinf, str): - possinf = [possinf] + possinf = [possinf] for x in possinf: if objectclasses.has_key(x): - newpossinf[n] = x - n++ - class["possibleInferiors"] = newpossinf - - # trim systemMayContain, - # remove duplicates - if class.has_key("systemMayContain"): - sysmay = class["systemMayContain"] - newsysmay = [] + newpossinf[n] = x + n+=1 + objectclass["possibleInferiors"] = newpossinf + + # trim systemMayContain, + # remove duplicates + if objectclass.has_key("systemMayContain"): + sysmay = objectclass["systemMayContain"] + newsysmay = [] if isinstance(sysmay, str): - sysmay = [sysmay] + sysmay = [sysmay] for x in sysmay: - dup = False - if newsysmay[0] == undefined) { - newsysmay[0] = x - else: - for (n = 0; n < newsysmay.length; n++) { - if (newsysmay[n] == x) { - dup = True - if not dup: - newsysmay[n] = x - class["systemMayContain"] = newsysmay - - # trim mayContain, - # remove duplicates - if not class.has_key("mayContain"): - may = class["mayContain"] - newmay = [] + if not x in newsysmay: + newsysmay.append(x) + objectclass["systemMayContain"] = newsysmay + + # trim mayContain, + # remove duplicates + if not objectclass.has_key("mayContain"): + may = objectclass["mayContain"] + newmay = [] if isinstance(may, str): - may = [may] + may = [may] for x in may: - dup = False - if (newmay[0] == undefined) { - newmay[0] = x - } else { - for (n = 0; n < newmay.length; n++) { - if (newmay[n] == x) { - dup = True - if not dup: - newmay[n] = x - class["mayContain"] = newmay + if not x in newmay: + newmay.append(x) + objectclass["mayContain"] = newmay -# -# load the basic attributes of an objectClass -# def build_objectclass(ldb, name): - attrs = ["name"] + """load the basic attributes of an objectClass""" + attrs = ["name"] try: res = ldb.search( expression="(&(objectClass=classSchema)(ldapDisplayName=%s))" % name, - rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs) + basedn=rootDse["schemaNamingContext"], scope=ldb.SCOPE_SUBTREE, + attrs=attrs) except LdbError, e: - print "unknown class '%s'\n" % name - return None + print "unknown class '%s'\n" % name + return None if len(res) == 0: - print "unknown class '%s'\n" % name - return None - return obj_objectClass(ldb, name) - -# -# append 2 lists -# -def list_append(a1, a2): - if (a1 == undefined) { - return a2 - if (a2 == undefined) - return a1 - for (i=0;i