/usr/share/pyca/pylib/ldif.py is in pyca 20031119-0.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | """
ldif.py - Various routines for handling LDIF data
This module is distributed under the terms of the
GPL (GNU GENERAL PUBLIC LICENSE) Version 2
(see http://www.gnu.org/copyleft/gpl.html)
"""
__version__ = '0.2.5'
import sys,string,binascii,re
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
attr_pattern = r'[\w;.]+(;[\w_-]+)*'
data_pattern = '([^,]+|".*?")'
rdn_pattern = attr_pattern + r'[\s]*=[\s]*' + data_pattern
dn_pattern = rdn_pattern + r'([\s]*,[\s]*' + rdn_pattern + r')*'
#rdn_regex = re.compile('^%s$' % rdn_pattern)
dn_regex = re.compile('^%s$' % dn_pattern)
ldif_pattern = '^((dn(:|::) %(dn_pattern)s)|(%(attr_pattern)s(:|::) %(data_pattern)s)$)+' % vars()
ldif_regex = re.compile('^%s$' % ldif_pattern,re.M)
def is_dn(s):
"""
returns 1 if s is a LDAP DN
"""
rm = dn_regex.match(s)
return rm!=None and rm.group(0)==s
def is_ascii(s):
"""
returns 1 if s is plain ASCII
"""
if s:
pos=0 ; s_len = len(s)
while ((ord(s[pos]) & 0x80) == 0) and (pos<s_len-1):
pos=pos+1
if pos<s_len-1:
return 0
else:
return (ord(s[pos]) & 0x80) == 0
else:
return 1
def BinaryAttribute(attr,buf,col=77):
"""
Convert buf to a binary attribute representation
"""
b64buf = '%s:: ' % (attr)
buflen = len(buf)
pos=0
while pos<buflen:
b64buf = '%s%s' % (b64buf,binascii.b2a_base64(buf[pos:min(buflen,pos+57)])[:-1])
pos = pos+57
b64buflen = len(b64buf)
pos=col
result = b64buf[0:min(b64buflen,col)]
while pos<b64buflen:
result = '%s\n %s' % (result,b64buf[pos:min(b64buflen,pos+col-1)])
pos = pos+col-1
return '%s\n' % result
def CreateLDIF(
dn, # string-represantation of distinguished name
entry={}, # dictionary holding the LDAP entry {attr:data}
binary_attrs=[]
):
"""
Create LDIF formatted entry.
The trailing empty line is NOT added.
"""
# Write line dn: first
if is_ascii(dn):
result = ['dn: %s\n' % (dn)]
else:
result = [BinaryAttribute('dn',dn)]
objectclasses = entry.get('objectclass',entry.get('objectClass',[]))
for oc in objectclasses:
result.append('objectclass: %s\n' % oc)
attrs = entry.keys()[:]
try:
attrs.remove('objectclass')
attrs.remove('objectClass')
except ValueError:
pass
attrs.sort()
for attr in attrs:
if attr in binary_attrs:
for data in entry[attr]:
result.append(BinaryAttribute(attr,data))
else:
for data in entry[attr]:
if is_ascii(data):
result.append('%s: %s\n' % (attr,data))
else:
result.append(BinaryAttribute(attr,data))
return string.join(result,'')
def ParseLDIF(
f=StringIO(), # file-object for reading LDIF input
ignore_attrs=[], # list of attribute types to ignore
maxentries=0 # (if non-zero) specifies the maximum number of
# entries to be read from f
):
"""
Parse LDIF data read from file object f
"""
result = []
# lower-case all
ignored_attrs = map(string.lower,ignore_attrs)
# Read very first line
s = f.readline()
entries_read = 0
while s and (not maxentries or entries_read<maxentries):
# Reading new entry
# Reset entry data
dn = ''; entry = {}; attr = ''; data = ''
s = string.rstrip(s)
while s:
# Reading new attribute line
attr,data=string.split(s,':',1)
if data[0]==':':
# Read attr:: data line => binary data assumed
data = data[1:]
binary = 1
else:
# Read attr: data line
binary = 0
s = f.readline()
s = string.rstrip(s)
# Reading continued multi-line data
while s and s[0]==' ':
data = data + string.strip(s)
# Read next line
s = f.readline()
s = string.rstrip(s)
attr = string.lower(string.strip(attr))
if not attr in ignored_attrs:
if binary:
# binary data has to be BASE64 decoded
data = binascii.a2b_base64(data)
else:
data = string.strip(data)
# Add attr: data to entry
if attr=='dn':
dn = string.strip(data) ; attr = '' ; data = ''
if not is_dn(dn):
raise ValueError, 'No valid string-representation of distinguished name.'
else:
if entry.has_key(attr):
entry[attr].append(data)
else:
entry[attr]=[data]
# end of entry reached marked by newline character(s)
if entry:
# append entry to result list
result.append((dn,entry))
entries_read = entries_read+1
# Start reading next entry
s = f.readline()
return result
|