|
From: Alain S. <asp...@gm...> - 2007-05-24 19:16:25
|
On 5/24/07, Michael Str=F6der <mi...@st...> wrote:
>
> Alain Spineux wrote:
> >
> > Yes but what about unknown field type ?
>
> If you really want to dive into this look in directory
> pylib/w2lapp/schema/ of web2ldap's source. It works for me but I did not
> consider this whole framework mature enough to be incorporated into
> python-ldap.
I dont want to look at the schema:
Here are the sources and the results.
I use your more appropriate name for unicode testing :-)
#!/usr/bin/env python2.4
import sys, os, time
import ldap, ldapurl, ldap.modlist
import types
import datetime
host=3D'localhost'
port=3D389
base_dn=3D'dc=3Dasxnet,dc=3Dloc'
if True:
who=3D'cn=3Dmanager,cn=3Dinternal,dc=3Dasxnet,dc=3Dloc'
cred=3D''********'
else:
who=3D'cn=3Dnobody,cn=3Dinternal,dc=3Dasxnet,dc=3Dloc'
cred=3D'iMmTWz5pJ+lwY7i6M/BU61ngo1aBLyqQhRrrKbEc'
def unicode2utf8(st):
"""Convert unicode (and only unicode) string into utf-8 raw string as
expected by ldap"""
if isinstance(st, types.UnicodeType):
return st.encode('utf-8')
else:
return st
def utf82unicode(st):
"""encode st into utf-8"""
return st.decode('utf-8')
def encode_modlist(modlist, no_op):
"""encode ldap modlist structure
set no_op=3DTrue for Tuple of kind (int,str,[str,...])
and False for (str, [str,...])
"""
for i, mod in enumerate(modlist):
if no_op:
attr_name, attr_values=3Dmod
else:
op, attr_name, attr_values=3Dmod
attr_name=3Dunicode2utf8(attr_name)
if isinstance(attr_values, (types.ListType, types.TupleType)):
attr_values=3Dmap(unicode2utf8, attr_values)
else:
attr_values=3Dunicode2utf8(attr_values)
if no_op:
modlist[i]=3D(attr_name, attr_values)
else:
modlist[i]=3D(op, attr_name, attr_values)
return modlist
class UnicodeLDAPObject(ldap.ldapobject.LDAPObject):
expiration_delay=3D300
def __init__(self, uri, **kwargs):
ldap.ldapobject.LDAPObject.__init__(self, uri, **kwargs)
self.unicode_decoder=3D{} # (msgid, expiration, decoder_data)
# I use an expiration time to avoid the list to become to big when
the
# server don't answere any request
def search_ext(self,base,scope, filterstr, attrlist, *args, **kwargs):
# base,scope,
filterstr=3D'(objectClass=3D*)',attrlist=3DNone,attrsonly=3D0,serverctrls=
=3DNone,clientctrls=3DNone,timeout=3D-1,sizelimit=3D0
# convert filter
filterstr=3Dunicode2utf8(filterstr)
# convert arglist and keep a copy of original values for later
decoding
u_attrlist=3Dattrlist
decoder=3D{}
if u_attrlist!=3DNone:
attrlist=3D[]
for attr in u_attrlist:
if isinstance(attr, types.UnicodeType):
attr=3Dattr.encode('utf-8')
# print 'ATTR', attr
decoder[attr]=3DTrue
attrlist.append(attr)
msgid=3Dldap.ldapobject.LDAPObject.search_ext(self,base,scope,
filterstr, attrlist, *args, **kwargs)
if decoder:
timeout=3Dkwargs.get('timeout', None)
if timeout=3D=3DNone or timeout<=3D0:
timeout=3Dself.expiration_delay
self.unicode_decoder[msgid]=3D(msgid,
datetime.datetime.now()+datetime.timedelta(seconds=3Dtimeout),
decoder)
return msgid
def result3(self, *args, **kwargs):
# kwargs=3D(self, msgid=3D_ldap.RES_ANY,all=3D1,timeout=3DNone):
rtype, rdata, rmsgid, decoded_serverctrls=3D
ldap.ldapobject.LDAPObject.result3(self, *args, **kwargs)
if self.unicode_decoder.has_key(rmsgid):
msgid, expire, decoder=3Dself.unicode_decoder[rmsgid]
if rtype not in [ ldap.RES_SEARCH_ENTRY,
ldap.RES_SEARCH_REFERENCE ]:
# this was the last result
del self.unicode_decoder[rmsgid]
else:
# reset the timeout
timeout=3Dkwargs.get('timeout', None)
if timeout=3D=3DNone or timeout<=3D0:
timeout=3Dself.expiration_delay
self.unicode_decoder[msgid]=3D(msgid,
datetime.datetime.now()+datetime.timedelta(seconds=3Dtimeout),
decoder)
# now decode the result
if rdata:
if rtype in [ldap.RES_SEARCH_ENTRY,
ldap.RES_SEARCH_REFERENCE, ldap.RES_SEARCH_RESULT]:
# FIXME: I dont know what is a RES_SEARCH_REFERENCE
rdata_u=3D[]
for i, (dn, attrs) in enumerate(rdata):
# FIXME: should I handle the 'dn' the same way
if decoder.has_key('dn'):
dn=3Dutf82unicode(dn)
for key in attrs.keys():
if decoder.has_key(key):
attrs[key]=3Dmap(utf82unicode, attrs[key])
# print '\tITEM=3D', dn, attrs
rdata[i]=3D(dn, attrs)
else:
# no decoder for this =3D> nothing to decode
pass
# remove other expired decoder info
now=3Ddatetime.datetime.now()
for msgid in self.unicode_decoder.keys():
if self.unicode_decoder[rmsgid][1]<now:
del self.unicode_decoder[rmsgid]
return rtype, rdata, rmsgid, decoded_serverctrls
def add_ext(self, dn, modlist, *args, **kwargs):
# args=3D(self,dn,modlist,serverctrls=3DNone,clientctrls=3DNone)
dn=3Dunicode2utf8(dn)
# print 'MODLIST', modlist
modlist=3Dencode_modlist(modlist, True)
# print 'MODLIST unicode', modlist
return ldap.ldapobject.LDAPObject.add_ext(self, dn, modlist, *args,
**kwargs)
def modify_ext(self, dn, modlist, *args, **kwargs):
# args=3D(self,dn,modlist,serverctrls=3DNone,clientctrls=3DNone)
dn=3Dunicode2utf8(dn)
# print 'MODLIST', modlist
modlist=3Dencode_modlist(modlist, False)
# print 'MODLIST unicode', modlist
return ldap.ldapobject.LDAPObject.modify_ext(self, dn, modlist,
*args, **kwargs)
def delete_ext(self, dn, *args, **kwargs):
# args=3D(self,dn,serverctrls=3DNone,clientctrls=3DNone)
dn=3Dunicode2utf8(dn)
return ldap.ldapobject.LDAPObject.delete_ext(self, dn, *args,
**kwargs)
def print_ldap_result(ldap_result):
for dn, item in ldap_result:
print 'DN=3D', repr(dn)
for k, v in item.iteritems():
print '\t%s: %s' % (k, repr(v))
print
ldap_url=3Dldapurl.LDAPUrl('ldap://%s:%d/%s' % (host, port, base_dn))
ldap_url.applyDefaults({
'who': who,
'cred' : cred, })
#l=3Dldap.ldapobject.LDAPObject(ldap_url.initializeUrl())
l=3DUnicodeLDAPObject(ldap_url.initializeUrl())
l.simple_bind_s(ldap_url.who, ldap_url.cred)
print 'Connected as', l.whoami_s()
first_name=3D'Michael'
first_name2=3Du'Micha\xebl'
last_name=3Du'Str\xf6der'
email=3D'mi...@st...'
street=3Du'Hauptstra\xe1e'
country=3D'Germany'
cn=3D'%s %s' %(first_name, last_name)
dn=3D'cn=3D%s,%s' %(cn, base_dn)
info=3D{
u'cn' : (cn, ),
'mail' : (email, ),
'objectClass' : ('top', 'inetOrgPerson', 'kolabInetOrgPerson',),
u'sn' : (last_name, ),
u'givenName' : (first_name, ),
u'street': (street, ),
'c': (country, ),
'telephoneNumber': '+49 1111111111',
}
ldap_result=3Dl.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=3D%s)' % (cn,) =
,
info.keys())
if ldap_result:
print '=3D=3D Found'
print_ldap_result(ldap_result)
l.delete_s(dn)
print '=3D=3D Deleted'
l.add_s(dn, ldap.modlist.addModlist(info))
print '=3D=3D Created'
ldap_result=3Dl.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=3D%s)' % (cn,) =
,
info.keys())
print_ldap_result(ldap_result)
l.modify_s(dn, [(ldap.MOD_REPLACE, u'givenName', first_name2),
(ldap.MOD_ADD, 'telephoneNumber', ( '+49 1234567890', )),
])
print '=3D=3DModified'
ldap_result=3Dl.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=3D%s)' % (cn,) =
,
info.keys())
print_ldap_result(ldap_result)
print '=3D=3DDisplay once more'
ldap_result=3Dl.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=3D%s)' % (cn,) =
,
['*', '+', u'dn', u'givenName', u'creatorsName'] )
print_ldap_result(ldap_result)
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Connected as dn:cn=3Dmanager,cn=3Dinternal,dc=3Dasxnet,dc=3Dloc
=3D=3D Found
DN=3D 'cn=3DMichael Str\xc3\xb6der,dc=3Dasxnet,dc=3Dloc'
telephoneNumber: ['+49 1111111111', '+49 1234567890']
c: ['Germany']
cn: [u'Michael Str\xf6der']
objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
street: [u'Hauptstra\xe1e']
sn: [u'Str\xf6der']
mail: ['mi...@st...']
givenName: [u'Micha\xebl']
=3D=3D Deleted
=3D=3D Created
DN=3D 'cn=3DMichael Str\xc3\xb6der,dc=3Dasxnet,dc=3Dloc'
telephoneNumber: ['+49 1111111111']
c: ['Germany']
cn: [u'Michael Str\xf6der']
objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
street: [u'Hauptstra\xe1e']
sn: [u'Str\xf6der']
mail: ['mi...@st...']
givenName: [u'Michael']
=3D=3DModified
DN=3D 'cn=3DMichael Str\xc3\xb6der,dc=3Dasxnet,dc=3Dloc'
telephoneNumber: ['+49 1111111111', '+49 1234567890']
c: ['Germany']
cn: [u'Michael Str\xf6der']
objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
street: [u'Hauptstra\xe1e']
sn: [u'Str\xf6der']
mail: ['mi...@st...']
givenName: [u'Micha\xebl']
=3D=3DDisplay more
DN=3D 'cn=3DMichael Str\xc3\xb6der,dc=3Dasxnet,dc=3Dloc'
telephoneNumber: ['+49 1111111111', '+49 1234567890']
c: ['Germany']
cn: [u'Michael Str\xf6der']
objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
street: [u'Hauptstra\xe1e']
sn: [u'Str\xf6der']
mail: ['mi...@st...']
givenName: [u'Micha\xebl']
=3D=3DDisplay once more
DN=3D u'cn=3DMichael Str\xf6der,dc=3Dasxnet,dc=3Dloc'
telephoneNumber: ['+49 1111111111', '+49 1234567890']
c: ['Germany']
entryCSN: ['20070524191126Z#000002#00#000000']
cn: ['Michael Str\xc3\xb6der']
entryDN: ['cn=3DMichael Str\xc3\xb6der,dc=3Dasxnet,dc=3Dloc']
createTimestamp: ['20070524191126Z']
objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
creatorsName: [u'cn=3Dmanager,cn=3Dinternal,dc=3Dasxnet,dc=3Dloc']
entryUUID: ['5099e82e-9e76-102b-830b-0da78c7bd35e']
hasSubordinates: ['FALSE']
modifiersName: ['cn=3Dmanager,cn=3Dinternal,dc=3Dasxnet,dc=3Dloc']
street: ['Hauptstra\xc3\xa1e']
sn: ['Str\xc3\xb6der']
structuralObjectClass: ['inetOrgPerson']
subschemaSubentry: ['cn=3DSubschema']
mail: ['mi...@st...']
givenName: [u'Micha\xebl']
modifyTimestamp: ['20070524191126Z']
--=20
--
Alain Spineux
aspineux gmail com
May the sources be with you
|