Skip to content

Commit 91438fd

Browse files
authored
Merge pull request #152 – bytes mode for default arguments
With `bytes_mode=True`, all arguments must be bytes. However some functions had default keyword arguments of type `str` (`unicode`). One example is `search_ext(..., filterstr='(objectClass=*), ...')`. Here is a fix. #152
2 parents 6e75fc4 + f8f8c9c commit 91438fd

File tree

4 files changed

+172
-29
lines changed

4 files changed

+172
-29
lines changed

Doc/reference/ldap.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,10 @@ and wait for and return with the server's result, or with
10681068
or :py:meth:`search_ext_s()` (client-side search limit). If non-zero
10691069
not more than *sizelimit* results are returned by the server.
10701070

1071+
.. versionchanged:: 3.0
10711072

1073+
``filterstr=None`` is equivalent to ``filterstr='(objectClass=*)'``.
1074+
10721075

10731076
.. py:method:: LDAPObject.start_tls_s() -> None
10741077

Lib/ldap/ldapobject.py

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ def result4(self,msgid=ldap.RES_ANY,all=1,timeout=None,add_ctrls=0,add_intermedi
748748
resp_data = self._bytesify_results(resp_data, with_ctrls=add_ctrls)
749749
return resp_type, resp_data, resp_msgid, decoded_resp_ctrls, resp_name, resp_value
750750

751-
def search_ext(self,base,scope,filterstr='(objectClass=*)',attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1,sizelimit=0):
751+
def search_ext(self,base,scope,filterstr=None,attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1,sizelimit=0):
752752
"""
753753
search(base, scope [,filterstr='(objectClass=*)' [,attrlist=None [,attrsonly=0]]]) -> int
754754
search_s(base, scope [,filterstr='(objectClass=*)' [,attrlist=None [,attrsonly=0]]])
@@ -793,12 +793,24 @@ def search_ext(self,base,scope,filterstr='(objectClass=*)',attrlist=None,attrson
793793
The amount of search results retrieved can be limited with the
794794
sizelimit parameter if non-zero.
795795
"""
796+
796797
if PY2:
797798
base = self._bytesify_input('base', base)
798-
filterstr = self._bytesify_input('filterstr', filterstr)
799+
if filterstr is None:
800+
# workaround for default argument,
801+
# see https://github.com/python-ldap/python-ldap/issues/147
802+
if self.bytes_mode:
803+
filterstr = b'(objectClass=*)'
804+
else:
805+
filterstr = u'(objectClass=*)'
806+
else:
807+
filterstr = self._bytesify_input('filterstr', filterstr)
799808
if attrlist is not None:
800809
attrlist = tuple(self._bytesify_input('attrlist', a)
801810
for a in attrlist)
811+
else:
812+
if filterstr is None:
813+
filterstr = '(objectClass=*)'
802814
return self._ldap_call(
803815
self._l.search_ext,
804816
base,scope,filterstr,
@@ -808,17 +820,17 @@ def search_ext(self,base,scope,filterstr='(objectClass=*)',attrlist=None,attrson
808820
timeout,sizelimit,
809821
)
810822

811-
def search_ext_s(self,base,scope,filterstr='(objectClass=*)',attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1,sizelimit=0):
823+
def search_ext_s(self,base,scope,filterstr=None,attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1,sizelimit=0):
812824
msgid = self.search_ext(base,scope,filterstr,attrlist,attrsonly,serverctrls,clientctrls,timeout,sizelimit)
813825
return self.result(msgid,all=1,timeout=timeout)[1]
814826

815-
def search(self,base,scope,filterstr='(objectClass=*)',attrlist=None,attrsonly=0):
827+
def search(self,base,scope,filterstr=None,attrlist=None,attrsonly=0):
816828
return self.search_ext(base,scope,filterstr,attrlist,attrsonly,None,None)
817829

818-
def search_s(self,base,scope,filterstr='(objectClass=*)',attrlist=None,attrsonly=0):
830+
def search_s(self,base,scope,filterstr=None,attrlist=None,attrsonly=0):
819831
return self.search_ext_s(base,scope,filterstr,attrlist,attrsonly,None,None,timeout=self.timeout)
820832

821-
def search_st(self,base,scope,filterstr='(objectClass=*)',attrlist=None,attrsonly=0,timeout=-1):
833+
def search_st(self,base,scope,filterstr=None,attrlist=None,attrsonly=0,timeout=-1):
822834
return self.search_ext_s(base,scope,filterstr,attrlist,attrsonly,None,None,timeout)
823835

824836
def start_tls_s(self):
@@ -885,7 +897,7 @@ def set_option(self,option,invalue):
885897
invalue = RequestControlTuples(invalue)
886898
return self._ldap_call(self._l.set_option,option,invalue)
887899

888-
def search_subschemasubentry_s(self,dn=''):
900+
def search_subschemasubentry_s(self,dn=None):
889901
"""
890902
Returns the distinguished name of the sub schema sub entry
891903
for a part of a DIT specified by dn.
@@ -895,9 +907,17 @@ def search_subschemasubentry_s(self,dn=''):
895907
896908
Returns: None or text/bytes depending on bytes_mode.
897909
"""
910+
if self.bytes_mode:
911+
empty_dn = b''
912+
attrname = b'subschemaSubentry'
913+
else:
914+
empty_dn = u''
915+
attrname = u'subschemaSubentry'
916+
if dn is None:
917+
dn = empty_dn
898918
try:
899919
r = self.search_s(
900-
dn,ldap.SCOPE_BASE,'(objectClass=*)',['subschemaSubentry']
920+
dn,ldap.SCOPE_BASE,None,[attrname]
901921
)
902922
except (ldap.NO_SUCH_OBJECT,ldap.NO_SUCH_ATTRIBUTE,ldap.INSUFFICIENT_ACCESS):
903923
r = []
@@ -906,11 +926,11 @@ def search_subschemasubentry_s(self,dn=''):
906926
try:
907927
if r:
908928
e = ldap.cidict.cidict(r[0][1])
909-
search_subschemasubentry_dn = e.get('subschemaSubentry',[None])[0]
929+
search_subschemasubentry_dn = e.get(attrname,[None])[0]
910930
if search_subschemasubentry_dn is None:
911931
if dn:
912932
# Try to find sub schema sub entry in root DSE
913-
return self.search_subschemasubentry_s(dn='')
933+
return self.search_subschemasubentry_s(dn=empty_dn)
914934
else:
915935
# If dn was already root DSE we can return here
916936
return None
@@ -930,7 +950,7 @@ def read_s(self,dn,filterstr=None,attrlist=None,serverctrls=None,clientctrls=Non
930950
r = self.search_ext_s(
931951
dn,
932952
ldap.SCOPE_BASE,
933-
filterstr or '(objectClass=*)',
953+
filterstr,
934954
attrlist=attrlist,
935955
serverctrls=serverctrls,
936956
clientctrls=clientctrls,
@@ -945,26 +965,34 @@ def read_subschemasubentry_s(self,subschemasubentry_dn,attrs=None):
945965
"""
946966
Returns the sub schema sub entry's data
947967
"""
968+
if self.bytes_mode:
969+
filterstr = b'(objectClass=subschema)'
970+
if attrs is None:
971+
attrs = [attr.encode('utf-8') for attr in SCHEMA_ATTRS]
972+
else:
973+
filterstr = u'(objectClass=subschema)'
974+
if attrs is None:
975+
attrs = SCHEMA_ATTRS
948976
try:
949977
subschemasubentry = self.read_s(
950978
subschemasubentry_dn,
951-
filterstr='(objectClass=subschema)',
952-
attrlist=attrs or SCHEMA_ATTRS
979+
filterstr=filterstr,
980+
attrlist=attrs
953981
)
954982
except ldap.NO_SUCH_OBJECT:
955983
return None
956984
else:
957985
return subschemasubentry
958986

959-
def find_unique_entry(self,base,scope=ldap.SCOPE_SUBTREE,filterstr='(objectClass=*)',attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1):
987+
def find_unique_entry(self,base,scope=ldap.SCOPE_SUBTREE,filterstr=None,attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1):
960988
"""
961989
Returns a unique entry, raises exception if not unique
962990
"""
963991
r = self.search_ext_s(
964992
base,
965993
scope,
966994
filterstr,
967-
attrlist=attrlist or ['*'],
995+
attrlist=attrlist,
968996
attrsonly=attrsonly,
969997
serverctrls=serverctrls,
970998
clientctrls=clientctrls,
@@ -975,14 +1003,20 @@ def find_unique_entry(self,base,scope=ldap.SCOPE_SUBTREE,filterstr='(objectClass
9751003
raise NO_UNIQUE_ENTRY('No or non-unique search result for %s' % (repr(filterstr)))
9761004
return r[0]
9771005

978-
def read_rootdse_s(self, filterstr='(objectClass=*)', attrlist=None):
1006+
def read_rootdse_s(self, filterstr=None, attrlist=None):
9791007
"""
9801008
convenience wrapper around read_s() for reading rootDSE
9811009
"""
1010+
if self.bytes_mode:
1011+
base = b''
1012+
attrlist = attrlist or [b'*', b'+']
1013+
else:
1014+
base = u''
1015+
attrlist = attrlist or [u'*', u'+']
9821016
ldap_rootdse = self.read_s(
983-
'',
1017+
base,
9841018
filterstr=filterstr,
985-
attrlist=attrlist or ['*', '+'],
1019+
attrlist=attrlist,
9861020
)
9871021
return ldap_rootdse # read_rootdse_s()
9881022

@@ -991,9 +1025,13 @@ def get_naming_contexts(self):
9911025
returns all attribute values of namingContexts in rootDSE
9921026
if namingContexts is not present (not readable) then empty list is returned
9931027
"""
1028+
if self.bytes_mode:
1029+
name = b'namingContexts'
1030+
else:
1031+
name = u'namingContexts'
9941032
return self.read_rootdse_s(
995-
attrlist=['namingContexts']
996-
).get('namingContexts', [])
1033+
attrlist=[name]
1034+
).get(name, [])
9971035

9981036

9991037
class ReconnectLDAPObject(SimpleLDAPObject):

Lib/ldap/schema/models.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class ObjectClass(SchemaElement):
127127
This list of strings contains NAMEs or OIDs of object classes
128128
this object class is derived from
129129
"""
130-
schema_attribute = 'objectClasses'
130+
schema_attribute = u'objectClasses'
131131
token_defaults = {
132132
'NAME':(()),
133133
'DESC':(None,),
@@ -225,7 +225,7 @@ class AttributeType(SchemaElement):
225225
This list of strings contains NAMEs or OIDs of attribute types
226226
this attribute type is derived from
227227
"""
228-
schema_attribute = 'attributeTypes'
228+
schema_attribute = u'attributeTypes'
229229
token_defaults = {
230230
'NAME':(()),
231231
'DESC':(None,),
@@ -319,7 +319,7 @@ class LDAPSyntax(SchemaElement):
319319
Integer flag (0 or 1) indicating whether the attribute type is marked
320320
as not human-readable (X-NOT-HUMAN-READABLE)
321321
"""
322-
schema_attribute = 'ldapSyntaxes'
322+
schema_attribute = u'ldapSyntaxes'
323323
token_defaults = {
324324
'DESC':(None,),
325325
'X-NOT-HUMAN-READABLE':(None,),
@@ -367,7 +367,7 @@ class MatchingRule(SchemaElement):
367367
syntax
368368
String contains OID of the LDAP syntax this matching rule is usable with
369369
"""
370-
schema_attribute = 'matchingRules'
370+
schema_attribute = u'matchingRules'
371371
token_defaults = {
372372
'NAME':(()),
373373
'DESC':(None,),
@@ -413,7 +413,7 @@ class MatchingRuleUse(SchemaElement):
413413
This list of strings contains NAMEs or OIDs of attribute types
414414
for which this matching rule is used
415415
"""
416-
schema_attribute = 'matchingRuleUse'
416+
schema_attribute = u'matchingRuleUse'
417417
token_defaults = {
418418
'NAME':(()),
419419
'DESC':(None,),
@@ -470,7 +470,7 @@ class DITContentRule(SchemaElement):
470470
This list of strings contains NAMEs or OIDs of attributes which
471471
may not be present in an entry of the object class
472472
"""
473-
schema_attribute = 'dITContentRules'
473+
schema_attribute = u'dITContentRules'
474474
token_defaults = {
475475
'NAME':(()),
476476
'DESC':(None,),
@@ -527,7 +527,7 @@ class DITStructureRule(SchemaElement):
527527
List of strings with NAMEs or OIDs of allowed structural object classes
528528
of superior entries in the DIT
529529
"""
530-
schema_attribute = 'dITStructureRules'
530+
schema_attribute = u'dITStructureRules'
531531

532532
token_defaults = {
533533
'NAME':(()),
@@ -591,7 +591,7 @@ class NameForm(SchemaElement):
591591
This list of strings contains NAMEs or OIDs of additional attributes
592592
an RDN may contain
593593
"""
594-
schema_attribute = 'nameForms'
594+
schema_attribute = u'nameForms'
595595
token_defaults = {
596596
'NAME':(()),
597597
'DESC':(None,),

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy