diff --git a/msldap/client.py b/msldap/client.py index dbc1c0e..604b2fe 100644 --- a/msldap/client.py +++ b/msldap/client.py @@ -156,7 +156,7 @@ async def get_domain_name(self): return domain, err - async def pagedsearch(self, query:str, attributes:List[str], controls:List[Tuple[str, str, str]] = None, tree:str = None, search_scope:int=2): + async def pagedsearch(self, query:str, attributes:List[str], controls:List[Tuple[str, str, str]] = None, tree:str = None, search_scope:int=2, raw: bool = False): """ Performs a paged search on the AD, using the filter and attributes as a normal query does. !The LDAP connection MUST be active before invoking this function! @@ -171,6 +171,8 @@ async def pagedsearch(self, query:str, attributes:List[str], controls:List[Tuple :type tree: str :param search_scope: LDAP search scope :type search_scope: int + :param raw: Return the attributes without conversion + :type raw: bool :return: Async generator which yields (`dict`, None) tuple on success or (None, `Exception`) on error :rtype: Iterator[(:class:`dict`, :class:`Exception`)] @@ -209,7 +211,8 @@ async def pagedsearch(self, query:str, attributes:List[str], controls:List[Tuple size_limit = self.ldap_query_page_size, controls = controls, rate_limit=self.ldap_query_ratelimit, - search_scope=search_scope + search_scope=search_scope, + raw=raw ): if err is not None: diff --git a/msldap/connection.py b/msldap/connection.py index 4789467..5a1b84f 100644 --- a/msldap/connection.py +++ b/msldap/connection.py @@ -751,7 +751,7 @@ async def search(self, base:str, query:str, attributes:List[bytes], search_scope except Exception as e: yield (None, e) - async def pagedsearch(self, base:str, query:str, attributes:List[bytes], search_scope:int = 2, size_limit:int = 1000, typesOnly:bool = False, derefAliases:bool = 0, timeLimit:int = None, controls:List[Control] = None, rate_limit:int = 0): + async def pagedsearch(self, base:str, query:str, attributes:List[bytes], search_scope:int = 2, size_limit:int = 1000, typesOnly:bool = False, derefAliases:bool = 0, timeLimit:int = None, controls:List[Control] = None, rate_limit:int = 0, raw: bool = False): """ Paged search is the same as the search operation and uses it under the hood. Adds automatic control to read all results in a paged manner. @@ -773,8 +773,11 @@ async def pagedsearch(self, base:str, query:str, attributes:List[bytes], search_ :type timeLimit: int :param controls: additional controls to be passed in the query :type controls: dict - :param rate_limit: time to sleep bwetween each query + :param rate_limit: time to sleep between each query :type rate_limit: float + :param raw: Return the attributes without conversion + :type raw: bool + :return: Async generator which yields (`dict`, None) tuple on success or (None, `Exception`) on error :rtype: Iterator[(:class:`dict`, :class:`Exception`)] """ @@ -835,7 +838,7 @@ async def pagedsearch(self, base:str, query:str, attributes:List[bytes], search_ else: raise Exception('SearchControl missing from server response!') else: - yield (convert_result(res['protocolOp']), None) + yield (convert_result(res['protocolOp'], raw), None) if cookie == b'': break diff --git a/msldap/protocol/typeconversion.py b/msldap/protocol/typeconversion.py index 198b88d..d2605f1 100644 --- a/msldap/protocol/typeconversion.py +++ b/msldap/protocol/typeconversion.py @@ -430,29 +430,31 @@ def encode_attributes(x): return res -def convert_attributes(x): +def convert_attributes(x, raw=False): t = {} for e in x: #print(e) k = e['type'].decode() #print('k: %s' % k) - - if k in MSLDAP_BUILTIN_ATTRIBUTE_TYPES: - t[k] = MSLDAP_BUILTIN_ATTRIBUTE_TYPES[k](e['attributes'], False) - elif k in LDAP_WELL_KNOWN_ATTRS: - t[k] = LDAP_WELL_KNOWN_ATTRS[k](e['attributes'], False) - else: - logger.debug('Unknown type! %s data: %s' % (k, e['attributes'])) + if raw: t[k] = e['attributes'] + else: + if k in MSLDAP_BUILTIN_ATTRIBUTE_TYPES: + t[k] = MSLDAP_BUILTIN_ATTRIBUTE_TYPES[k](e['attributes'], False) + elif k in LDAP_WELL_KNOWN_ATTRS: + t[k] = LDAP_WELL_KNOWN_ATTRS[k](e['attributes'], False) + else: + logger.debug('Unknown type! %s data: %s' % (k, e['attributes'])) + t[k] = e['attributes'] return t -def convert_result(x): +def convert_result(x, raw=False): #print(x) #import traceback #traceback.print_stack() return { 'objectName' : x['objectName'].decode(), - 'attributes' : convert_attributes(x['attributes']) + 'attributes' : convert_attributes(x['attributes'], raw) }