From: Alain S. <asp...@gm...> - 2007-05-31 12:25:57
|
Hi I changed my code to make it more modular. class UnicodeLDAPInterface: ldapbaseclass=3DNone .... my code goes HERE class UnicodeLDAPObject(UnicodeLDAPInterface, LDAPObject): ldapbaseclass=3DLDAPObject class UnicodeReconnectLDAPObject(UnicodeLDAPInterface, ReconnectLDAPObject)= : ldapbaseclass=3DReconnectLDAPObject Here is the full code #!/usr/bin/env python2.4 import types, datetime import ldap, ldapurl, ldap.modlist from ldap.ldapobject import LDAPObject from ldap.ldapobject import ReconnectLDAPObject 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 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 class UnicodeLDAPInterface: ldapbaseclass=3DNone decoder_expiration_delay=3D300 # the expiration delay for an object in self.unicode_decoder def __init__(self, uri, **kwargs): self.ldapbaseclass.__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 some requests def _set_unicode_decoder(self, msgid, value): """protect unicode_decoder against multi-threading update or add the decoder """ self._ldap_object_lock.acquire() try: self.unicode_decoder[msgid]=3Dvalue finally: self._ldap_object_lock.release() def _remove_unicode_decoder(self, msgid): """protect unicode_decoder against multi-threading remove the decoder """ self._ldap_object_lock.acquire() try: try: del self.unicode_decoder[msgid] except: # ignore any errors pass finally: self._ldap_object_lock.release() def _get_unicode_decoder(self, msgid): """protect unicode_decoder against multi-threading read the decoder info for msgid """ self._ldap_object_lock.acquire() try: return self.unicode_decoder[msgid] finally: self._ldap_object_lock.release() def _expire_unicode_decoder(self): """cleanup any expired decoder""" self._ldap_object_lock.acquire() now=3Ddatetime.datetime.now() for msgid in self.unicode_decoder.keys(): if self.unicode_decoder[msgid][1]<now: del self.unicode_decoder[msgid] self._ldap_object_lock.release() 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_u=3Dunicode2utf8(filterstr) # convert arglist and keep a copy of original values for later decoding attrlist_u=3D[] decoder=3D{} # will keep only fields to decode if attrlist!=3DNone: for attr in attrlist: if isinstance(attr, types.UnicodeType): attr=3Dattr.encode('utf-8') decoder[attr]=3DTrue attrlist_u.append(attr) msgid=3Dself.ldapbaseclass.search_ext(self,base,scope, filterstr_u, attrlist_u, *args, **kwargs) if decoder: timeout=3Dkwargs.get('timeout', None) if timeout=3D=3DNone or timeout<=3D0: timeout=3Dself.decoder_expiration_delay self._set_unicode_decoder(msgid,(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=3Dself.ldapbaseclass.result3(self, *args, **kwargs) try: msgid, expire, decoder=3Dself._get_unicode_decoder(rmsgid) except KeyError: pass # no decoder for this =3D> nothing to decode else: if rtype not in [ ldap.RES_SEARCH_ENTRY, ldap.RES_SEARCH_REFERENCE ]: # this was the last result self._remove_unicode_decoder(rmsgid) else: # reset the timeout timeout=3Dkwargs.get('timeout', None) if timeout=3D=3DNone or timeout<=3D0: timeout=3Dself.expiration_delay self._set_unicode_decoder(msgid, (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) self._expire_unicode_decoder() 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 self.ldapbaseclass.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 self.ldapbaseclass.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 self.ldapbaseclass.delete_ext(self, dn, *args, **kwargs) def abandon_ext(self, msgid, *args, **kwargs): # args=3D(self,msgid,serverctrls=3DNone,clientctrls=3DNone) result=3Dself.ldapbaseclass.abandon_ext(self, msgid, *args, **kwarg= s) self._remove_unicode_decoder(msgid) return result def cancel_ext(self, cancelid, *args, **kwargs): # args=3D(self,msgid,serverctrls=3DNone,clientctrls=3DNone) result=3Dself.ldapbaseclass.cancel_ext(self, cancelid, *args, **kwargs) self._remove_unicode_decoder(cancelid) return result class UnicodeLDAPObject(UnicodeLDAPInterface, LDAPObject): ldapbaseclass=3DLDAPObject class UnicodeReconnectLDAPObject(UnicodeLDAPInterface, ReconnectLDAPObject)= : ldapbaseclass=3DReconnectLDAPObject if __name__=3D=3D'__main__': import sys, os, time 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' ldap_url=3Dldapurl.LDAPUrl('ldap://%s:%d/%s' % (host, port, base_dn)) ldap_url.applyDefaults({ 'who': who, 'cred' : cred, }) print ldap_url #l=3DLDAPObject(ldap_url.initializeUrl()) #l=3DUnicodeLDAPObject(ldap_url.initializeUrl()) l=3DUnicodeReconnectLDAPObject(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)' % (c= n,) , 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)' % (c= n,) , 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)' % (c= n,) , 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)' % (c= n,) , ['*', '+', u'dn', u'givenName', u'creatorsName'] ) _print_ldap_result(ldap_result) On 5/29/07, Alain Spineux <asp...@gm...> wrote: > > Hi Michael > > When investigating about python and unicode, I read somewhere (in a PEP > I thing) that python functions should accept and manage unicode string > as well as normal string.Of course if these strings could contains user > readable characters. > > This is not the case for python-ldap functions. Sometime when calling > python-ldap, we don't know well the origin ( a function is not suposed > to know its caller :-) of the arguments we are using : user input, > web interface, mysql database, ldap result, web form, > literal, text file, text parsing... some are unicode, other not. > I thing python-ldap function must accept unicode arguments. > > As we discussed at length previously, the decoding of the result is > less easy because, the library cannot guess alone the meaning of > these values. > > I'm not supporting the idea of downloading and use the ldap > schema. I cannot imaging a connection less application > like a web application doing that at any request! Or keeping a cache > for the schema ... > > Anyway I see 2 solutions > > 1. Let result() return non unicode strings. _HERE_ The user know all > returned > strings are normal strings utf-8 encoded and he can do the encoding > himself. A helper function doing the job for the result structure > should be welcome. > > 2. Do the conversion regarding the info provided in the query, as my > source sample does. > > I answer now some of your previous comment: > > > > In this case maybe is it possible to use [ '*', u'givenName', u'sn' ] > > > to convert only 'givenName' and 'sn' > > > But then you will not gain much! Still the application has to know whic= h > > attributes have to be converted. =3D> It's not worth hiding the convers= ion > > > within python-ldap. > > I don't really hide the conversion, because the user has to request it > using > unicode field name. And second, I do more work: I keep a link between > the msgid and the request to know with fields I have to convert and > also destroy the link when unneeded anymore. > > > The only clean solution would be something involving LDAP schema > processing! > > You know better than me how costly it is, in developing time, and its > overhead for CPU and network load. > Do you really consider to add the schema processing for unicode > integration in the future? Or are you > hoping that someone will send you a patch :-) ? > > > I know you were not very exited by my ideas, anyway the unicode support > for > argument encoding is important. (this is my opinion) > Feel free to suggest some cosmetic changes: function name, class name, th= e > > way I wrap your base class ..... > > Keep in mind, none of my code break compatibility with existing > application. > > Best regards. > > > > On 5/24/07, Alain Spineux <asp...@gm...> wrote: > > > > > > > > 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,serverctr= ls=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=3D kwargs.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[ke= y]) > > > > # 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)' % (c= n,) , > > 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)' % (c= n,) , > > 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)' % (c= n,) , > > ['*', '+', 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=3Dlo= c'] > > entryUUID: ['5099e82e-9e76-102b-830b-0da78c7bd35e'] > > hasSubordinates: ['FALSE'] > > modifiersName: ['cn=3Dmanager,cn=3Dinternal,dc=3Dasxnet,dc=3Dlo= c'] > > street: ['Hauptstra\xc3\xa1e'] > > sn: ['Str\xc3\xb6der'] > > structuralObjectClass: ['inetOrgPerson'] > > subschemaSubentry: ['cn=3DSubschema'] > > mail: [' mi...@st...'] > > givenName: [u'Micha\xebl'] > > modifyTimestamp: ['20070524191126Z'] > > > > > > > > > > > > -- > > -- > > Alain Spineux > > aspineux gmail com > > May the sources be with you > > > > > > -- > -- > Alain Spineux > aspineux gmail com > May the sources be with you > --=20 -- Alain Spineux aspineux gmail com May the sources be with you |