-#!/usr/bin/env python
-#
# create schema.ldif (as a string) from WSPP documentation
#
# based on minschema.py and minschema_wspp
#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""Generate LDIF from WSPP documentation."""
import re
import base64
+import uuid
bitFields = {}
bitFields["searchflags"] = {
'fATTINDEX': 31, # IX
'fPDNTATTINDEX': 30, # PI
- 'fANR': 29, #AR
+ 'fANR': 29, # AR
'fPRESERVEONDELETE': 28, # PR
'fCOPY': 27, # CP
'fTUPLEINDEX': 26, # TP
# ADTS: 2.2.10
bitFields["systemflags"] = {
- 'FLAG_ATTR_NOT_REPLICATED': 31, 'FLAG_CR_NTDS_NC': 31, # NR
- 'FLAG_ATTR_REQ_PARTIAL_SET_MEMBER': 30, 'FLAG_CR_NTDS_DOMAIN': 30, # PS
- 'FLAG_ATTR_IS_CONSTRUCTED': 29, 'FLAG_CR_NTDS_NOT_GC_REPLICATED': 29, # CS
- 'FLAG_ATTR_IS_OPERATIONAL': 28, # OP
- 'FLAG_SCHEMA_BASE_OBJECT': 27, # BS
- 'FLAG_ATTR_IS_RDN': 26, # RD
- 'FLAG_DISALLOW_MOVE_ON_DELETE': 6, # DE
- 'FLAG_DOMAIN_DISALLOW_MOVE': 5, # DM
- 'FLAG_DOMAIN_DISALLOW_RENAME': 4, # DR
- 'FLAG_CONFIG_ALLOW_LIMITED_MOVE': 3, # AL
- 'FLAG_CONFIG_ALLOW_MOVE': 2, # AM
- 'FLAG_CONFIG_ALLOW_RENAME': 1, # AR
- 'FLAG_DISALLOW_DELETE': 0 # DD
+ 'FLAG_ATTR_NOT_REPLICATED': 31, 'FLAG_CR_NTDS_NC': 31, # NR
+ 'FLAG_ATTR_REQ_PARTIAL_SET_MEMBER': 30, 'FLAG_CR_NTDS_DOMAIN': 30, # PS
+ 'FLAG_ATTR_IS_CONSTRUCTED': 29, 'FLAG_CR_NTDS_NOT_GC_REPLICATED': 29, # CS
+ 'FLAG_ATTR_IS_OPERATIONAL': 28, # OP
+ 'FLAG_SCHEMA_BASE_OBJECT': 27, # BS
+ 'FLAG_ATTR_IS_RDN': 26, # RD
+ 'FLAG_DISALLOW_MOVE_ON_DELETE': 6, # DE
+ 'FLAG_DOMAIN_DISALLOW_MOVE': 5, # DM
+ 'FLAG_DOMAIN_DISALLOW_RENAME': 4, # DR
+ 'FLAG_CONFIG_ALLOW_LIMITED_MOVE': 3, # AL
+ 'FLAG_CONFIG_ALLOW_MOVE': 2, # AM
+ 'FLAG_CONFIG_ALLOW_RENAME': 1, # AR
+ 'FLAG_DISALLOW_DELETE': 0 # DD
}
# ADTS: 2.2.11
def __read_folded_line(f, buffer):
""" reads a line from an LDIF file, unfolding it"""
line = buffer
-
+
while True:
l = f.readline()
# preserves '\n '
line = line + l
else:
- # non-continued line
+ # non-continued line
if line == "":
line = l
# buffer contains the start of the next possibly folded line
buffer = l
break
-
+
return (line, buffer)
attr_type_re = re.compile("^([A-Za-z]+[A-Za-z0-9-]*):")
buffer = ""
-
+
while True:
entry = []
-
+
while True:
(l, buffer) = __read_folded_line(f, buffer)
-
+
if l[:1] == "#":
continue
if m:
if l[-1:] == "\n":
l = l[:-1]
-
+
entry.append(l)
else:
print >>sys.stderr, "Invalid line: %s" % l,
value = value.replace("\n ", "")
value = value.replace(" ", "")
-
+
try:
# some attributes already have numeric values
o = int(value)
def __write_ldif_one(entry):
"""Write out entry as LDIF"""
out = []
-
+
for l in entry:
if isinstance(l[1], str):
vl = [l[1]]
if l[0].lower() == 'omobjectclass':
out.append("%s:: %s" % (l[0], l[1]))
continue
-
+
for v in vl:
out.append("%s: %s" % (l[0], v))
return "\n".join(out)
-
+
def __transform_entry(entry, objectClass):
"""Perform transformations required to convert the LDIF-like schema
file entries to LDIF, including Samba-specific stuff."""
-
+
entry = [l.split(":", 1) for l in entry]
cn = ""
-
+
for l in entry:
key = l[0].lower()
l[1] = l[1].lstrip()
if not cn and key == "cn":
cn = l[1]
-
+
if key in multivalued_attrs:
# unlike LDIF, these are comma-separated
l[1] = l[1].replace("\n ", "")
l[1] = l[1].replace(" ", "")
l[1] = l[1].split(",")
-
+
if key in bitFields:
l[1] = __convert_bitfield(key, l[1])
entry.insert(0, ["dn", "CN=%s,${SCHEMADN}" % cn])
entry.insert(1, ["objectClass", ["top", objectClass]])
entry.insert(2, ["cn", cn])
-
+ entry.insert(2, ["objectGUID", str(uuid.uuid4())])
+ entry.insert(2, ["adminDescription", cn])
+ entry.insert(2, ["adminDisplayName", cn])
+
for l in entry:
key = l[0].lower()
"""Load and transform a schema file."""
out = []
-
+
f = open(filename, "rU")
for entry in __read_raw_entries(f):
out.append(__write_ldif_one(__transform_entry(entry, objectClass)))
attr_ldif = ""
classes_ldif = ""
-
+
if dump_attributes:
attr_ldif = __parse_schema_file(attr_file, "attributeSchema")
if dump_classes:
except IndexError:
print >>sys.stderr, "Usage: %s attr-file.txt classes-file.txt" % (sys.argv[0])
sys.exit(1)
-
- print read_ms_schema(attr_file, classes_file)
-
+ print read_ms_schema(attr_file, classes_file)