1#!/usr/bin/python 2# 3# Create DisplaySpecifiers LDIF (as a string) from the documents provided by 4# Microsoft under the WSPP. 5# 6# Copyright (C) Andrew Kroeger <andrew@id10ts.net> 2009 7# 8# Based on ms_schema.py 9# 10# This program is free software; you can redistribute it and/or modify 11# it under the terms of the GNU General Public License as published by 12# the Free Software Foundation; either version 3 of the License, or 13# (at your option) any later version. 14# 15# This program is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License 21# along with this program. If not, see <http://www.gnu.org/licenses/>. 22 23import re 24 25def __read_folded_line(f, buffer): 26 """Read a line from an LDIF file, unfolding it""" 27 line = buffer 28 29 while True: 30 l = f.readline() 31 32 if l[:1] == " ": 33 # continued line 34 35 # cannot fold an empty line 36 assert(line != "" and line != "\n") 37 38 # preserves '\n ' 39 line = line + l 40 else: 41 # non-continued line 42 if line == "": 43 line = l 44 45 if l == "": 46 # eof, definitely won't be folded 47 break 48 else: 49 # marks end of a folded line 50 # line contains the now unfolded line 51 # buffer contains the start of the next possibly folded line 52 buffer = l 53 break 54 55 return (line, buffer) 56 57# Only compile regexp once. 58# Will not match options after the attribute type. 59attr_type_re = re.compile("^([A-Za-z][A-Za-z0-9-]*):") 60 61def __read_raw_entries(f): 62 """Read an LDIF entry, only unfolding lines""" 63 64 buffer = "" 65 66 while True: 67 entry = [] 68 69 while True: 70 (l, buffer) = __read_folded_line(f, buffer) 71 72 if l[:1] == "#": 73 continue 74 75 if l == "\n" or l == "": 76 break 77 78 m = attr_type_re.match(l) 79 80 if m: 81 if l[-1:] == "\n": 82 l = l[:-1] 83 84 entry.append(l) 85 else: 86 print >>sys.stderr, "Invalid line: %s" % l, 87 sys.exit(1) 88 89 if len(entry): 90 yield entry 91 92 if l == "": 93 break 94 95def fix_dn(dn): 96 """Fix a string DN to use ${CONFIGDN}""" 97 98 if dn.find("<Configuration NC Distinguished Name>") != -1: 99 dn = dn.replace("\n ", "") 100 return dn.replace("<Configuration NC Distinguished Name>", "${CONFIGDN}") 101 else: 102 return dn 103 104def __write_ldif_one(entry): 105 """Write out entry as LDIF""" 106 out = [] 107 108 for l in entry: 109 if l[2] == 0: 110 out.append("%s: %s" % (l[0], l[1])) 111 else: 112 # This is a base64-encoded value 113 out.append("%s:: %s" % (l[0], l[1])) 114 115 return "\n".join(out) 116 117def __transform_entry(entry): 118 """Perform required transformations to the Microsoft-provided LDIF""" 119 120 temp_entry = [] 121 122 for l in entry: 123 t = [] 124 125 if l.find("::") != -1: 126 # This is a base64-encoded value 127 t = l.split(":: ", 1) 128 t.append(1) 129 else: 130 t = l.split(": ", 1) 131 t.append(0) 132 133 key = t[0].lower() 134 135 if key == "changetype": 136 continue 137 138 if key == "distinguishedname": 139 continue 140 141 if key == "instancetype": 142 continue 143 144 if key == "name": 145 continue 146 147 if key == "cn": 148 continue 149 150 if key == "objectcategory": 151 continue 152 153 if key == "showinadvancedviewonly": 154 value = t[1].upper().lstrip().rstrip() 155 if value == "TRUE": 156 # Remove showInAdvancedViewOnly attribute if it is set to the 157 # default value of TRUE 158 continue 159 160 t[1] = fix_dn(t[1]) 161 162 temp_entry.append(t) 163 164 entry = temp_entry 165 166 return entry 167 168def read_ms_ldif(filename): 169 """Read and transform Microsoft-provided LDIF file.""" 170 171 out = [] 172 173 f = open(filename, "rU") 174 for entry in __read_raw_entries(f): 175 out.append(__write_ldif_one(__transform_entry(entry))) 176 177 return "\n\n".join(out) + "\n\n" 178 179if __name__ == '__main__': 180 import sys 181 182 try: 183 display_specifiers_file = sys.argv[1] 184 except IndexError: 185 print >>sys.stderr, "Usage: %s display-specifiers-ldif-file.txt" % (sys.argv[0]) 186 sys.exit(1) 187 188 print read_ms_ldif(display_specifiers_file) 189 190