Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
search.py580 linesDownload Raw Back to operation
1"""
2"""
3
4# Created on 2013.06.02
5#
6# Author: Giovanni Cannata
7#
8# Copyright 2013 - 2020 Giovanni Cannata
9#
10# This file is part of ldap3.
11#
12# ldap3 is free software: you can redistribute it and/or modify
13# it under the terms of the GNU Lesser General Public License as published
14# by the Free Software Foundation, either version 3 of the License, or
15# (at your option) any later version.
16#
17# ldap3 is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20# GNU Lesser General Public License for more details.
21#
22# You should have received a copy of the GNU Lesser General Public License
23# along with ldap3 in the COPYING and COPYING.LESSER files.
24# If not, see <http://www.gnu.org/licenses/>.
25
26from string import whitespace
27from os import linesep
28
29from .. import DEREF_NEVER, BASE, LEVEL, SUBTREE, DEREF_SEARCH, DEREF_BASE, DEREF_ALWAYS, NO_ATTRIBUTES, SEQUENCE_TYPES, get_config_parameter, STRING_TYPES
30
31from ..core.exceptions import LDAPInvalidFilterError, LDAPAttributeError, LDAPInvalidScopeError, LDAPInvalidDereferenceAliasesError
32from ..utils.ciDict import CaseInsensitiveDict
33from ..protocol.rfc4511 import SearchRequest, LDAPDN, Scope, DerefAliases, Integer0ToMax, TypesOnly, \
34    AttributeSelection, Selector, EqualityMatch, AttributeDescription, AssertionValue, Filter, \
35    Not, And, Or, ApproxMatch, GreaterOrEqual, LessOrEqual, ExtensibleMatch, Present, SubstringFilter, \
36    Substrings, Final, Initial, Any, ResultCode, Substring, MatchingRule, Type, MatchValue, DnAttributes
37from ..operation.bind import referrals_to_list
38from ..protocol.convert import ava_to_dict, attributes_to_list, search_refs_to_list, validate_assertion_value, prepare_filter_for_sending, search_refs_to_list_fast
39from ..protocol.formatters.standard import format_attribute_values
40from ..utils.conv import to_unicode, to_raw
41
42ROOT = 0
43AND = 1
44OR = 2
45NOT = 3
46MATCH_APPROX = 4
47MATCH_GREATER_OR_EQUAL = 5
48MATCH_LESS_OR_EQUAL = 6
49MATCH_EXTENSIBLE = 7
50MATCH_PRESENT = 8
51MATCH_SUBSTRING = 9
52MATCH_EQUAL = 10
53
54SEARCH_OPEN = 20
55SEARCH_OPEN_OR_CLOSE = 21
56SEARCH_MATCH_OR_CLOSE = 22
57SEARCH_MATCH_OR_CONTROL = 23
58
59
60class FilterNode(object):
61    def __init__(self, tag=None, assertion=None):
62        self.tag = tag
63        self.parent = None
64        self.assertion = assertion
65        self.elements = []
66
67    def append(self, filter_node):
68        filter_node.parent = self
69        self.elements.append(filter_node)
70        return filter_node
71
72    def __str__(self, pos=0):
73        self.__repr__(pos)
74
75    def __repr__(self, pos=0):
76        node_tags = ['ROOT', 'AND', 'OR', 'NOT', 'MATCH_APPROX', 'MATCH_GREATER_OR_EQUAL', 'MATCH_LESS_OR_EQUAL', 'MATCH_EXTENSIBLE', 'MATCH_PRESENT', 'MATCH_SUBSTRING', 'MATCH_EQUAL']
77        representation = ' ' * pos + 'tag: ' + node_tags[self.tag] + ' - assertion: ' + str(self.assertion)
78        if self.elements:
79            representation += ' - elements: ' + str(len(self.elements))
80            for element in self.elements:
81                representation += linesep + ' ' * pos + element.__repr__(pos + 2)
82        return representation
83
84
85def evaluate_match(match, schema, auto_escape, auto_encode, validator, check_names):
86    left_part, equal_sign, right_part = match.strip().partition('=')
87    if not equal_sign:
88        raise LDAPInvalidFilterError('invalid matching assertion')
89    if left_part.endswith('~'):  # approximate match '~='
90        tag = MATCH_APPROX
91        left_part = left_part[:-1].strip()
92        right_part = right_part.strip()
93        assertion = {'attr': left_part, 'value': validate_assertion_value(schema, left_part, right_part, auto_escape, auto_encode, validator, check_names)}
94    elif left_part.endswith('>'):  # greater or equal match '>='
95        tag = MATCH_GREATER_OR_EQUAL
96        left_part = left_part[:-1].strip()
97        right_part = right_part.strip()
98        assertion = {'attr': left_part, 'value': validate_assertion_value(schema, left_part, right_part, auto_escape, auto_encode, validator, check_names)}
99    elif left_part.endswith('<'):  # less or equal match '<='
100        tag = MATCH_LESS_OR_EQUAL
101        left_part = left_part[:-1].strip()
102        right_part = right_part.strip()
103        assertion = {'attr': left_part, 'value': validate_assertion_value(schema, left_part, right_part, auto_escape, auto_encode, validator, check_names)}
104    elif left_part.endswith(':'):  # extensible match ':='
105        tag = MATCH_EXTENSIBLE
106        left_part = left_part[:-1].strip()
107        right_part = right_part.strip()
108        extended_filter_list = left_part.split(':')
109        matching_rule = False
110        dn_attributes = False
111        attribute_name = False
112        if extended_filter_list[0] == '':  # extensible filter format [:dn]:matchingRule:=assertionValue
113            if len(extended_filter_list) == 2 and extended_filter_list[1].lower().strip() != 'dn':
114                matching_rule = extended_filter_list[1]
115            elif len(extended_filter_list) == 3 and extended_filter_list[1].lower().strip() == 'dn':
116                dn_attributes = True
117                matching_rule = extended_filter_list[2]
118            else:
119                raise LDAPInvalidFilterError('invalid extensible filter')
120        elif len(extended_filter_list) <= 3:  # extensible filter format attr[:dn][:matchingRule]:=assertionValue
121            if len(extended_filter_list) == 1:
122                attribute_name = extended_filter_list[0]
123            elif len(extended_filter_list) == 2:
124                attribute_name = extended_filter_list[0]
125                if extended_filter_list[1].lower().strip() == 'dn':
126                    dn_attributes = True
127                else:
128                    matching_rule = extended_filter_list[1]
129            elif len(extended_filter_list) == 3 and extended_filter_list[1].lower().strip() == 'dn':
130                attribute_name = extended_filter_list[0]
131                dn_attributes = True
132                matching_rule = extended_filter_list[2]
133            else:
134                raise LDAPInvalidFilterError('invalid extensible filter')
135
136        if not attribute_name and not matching_rule:
137            raise LDAPInvalidFilterError('invalid extensible filter')
138        attribute_name = attribute_name.strip() if attribute_name else False
139        matching_rule = matching_rule.strip() if matching_rule else False
140        assertion = {'attr': attribute_name, 'value': validate_assertion_value(schema, attribute_name, right_part, auto_escape, auto_encode, validator, check_names), 'matchingRule': matching_rule, 'dnAttributes': dn_attributes}
141    elif right_part == '*':  # attribute present match '=*'
142        tag = MATCH_PRESENT
143        left_part = left_part.strip()
144        assertion = {'attr': left_part}
145    elif '*' in right_part:  # substring match '=initial*substring*substring*final'
146        tag = MATCH_SUBSTRING
147        left_part = left_part.strip()
148        right_part = right_part.strip()
149        substrings = right_part.split('*')
150        initial = validate_assertion_value(schema, left_part, substrings[0], auto_escape, auto_encode, validator, check_names) if substrings[0] else None
151        final = validate_assertion_value(schema, left_part, substrings[-1], auto_escape, auto_encode, validator, check_names) if substrings[-1] else None
152        any_string = [validate_assertion_value(schema, left_part, substring, auto_escape, auto_encode, validator, check_names) for substring in substrings[1:-1] if substring]
153        #assertion = {'attr': left_part, 'initial': initial, 'any': any_string, 'final': final}
154        assertion = {'attr': left_part}
155        if initial:
156            assertion['initial'] =  initial
157        if any_string:
158            assertion['any'] = any_string
159        if final:
160            assertion['final'] =  final
161    else:  # equality match '='
162        tag = MATCH_EQUAL
163        left_part = left_part.strip()
164        right_part = right_part.strip()
165        assertion = {'attr': left_part, 'value': validate_assertion_value(schema, left_part, right_part, auto_escape, auto_encode, validator, check_names)}
166
167    return FilterNode(tag, assertion)
168
169
170def parse_filter(search_filter, schema, auto_escape, auto_encode, validator, check_names):
171    if str is not bytes and isinstance(search_filter, bytes):  # python 3 with byte filter
172        search_filter = to_unicode(search_filter)
173    search_filter = search_filter.strip()
174    if search_filter and search_filter.count('(') == search_filter.count(')') and search_filter.startswith('(') and search_filter.endswith(')'):
175        state = SEARCH_OPEN_OR_CLOSE
176        root = FilterNode(ROOT)
177        current_node = root
178        start_pos = None
179        skip_white_space = True
180        just_closed = False
181        for pos, c in enumerate(search_filter):
182            if skip_white_space and c in whitespace:
183                continue
184            elif (state == SEARCH_OPEN or state == SEARCH_OPEN_OR_CLOSE) and c == '(':
185                state = SEARCH_MATCH_OR_CONTROL
186                just_closed = False
187            elif state == SEARCH_MATCH_OR_CONTROL and c in '&!|':
188                if c == '&':
189                    current_node = current_node.append(FilterNode(AND))
190                elif c == '|':
191                    current_node = current_node.append(FilterNode(OR))
192                elif c == '!':
193                    current_node = current_node.append(FilterNode(NOT))
194                state = SEARCH_OPEN
195            elif (state == SEARCH_MATCH_OR_CLOSE or state == SEARCH_OPEN_OR_CLOSE) and c == ')':
196                if just_closed:
197                    current_node = current_node.parent
198                else:
199                    just_closed = True
200                    skip_white_space = True
201                    end_pos = pos
202                    if start_pos:
203                        if current_node.tag == NOT and len(current_node.elements) > 0:
204                            raise LDAPInvalidFilterError('NOT (!) clause in filter cannot be multiple')
205                        current_node.append(evaluate_match(search_filter[start_pos:end_pos], schema, auto_escape, auto_encode, validator, check_names))
206                start_pos = None
207                state = SEARCH_OPEN_OR_CLOSE
208            elif (state == SEARCH_MATCH_OR_CLOSE or state == SEARCH_MATCH_OR_CONTROL) and c not in '()':
209                skip_white_space = False
210                if not start_pos:
211                    start_pos = pos
212                state = SEARCH_MATCH_OR_CLOSE
213            else:
214                raise LDAPInvalidFilterError('malformed filter')
215        if len(root.elements) != 1:
216            raise LDAPInvalidFilterError('missing boolean operator in filter')
217        return root
218    else:
219        raise LDAPInvalidFilterError('invalid filter')
220
221
222def compile_filter(filter_node):
223    """Builds ASN1 structure for filter, converts from filter LDAP escaping to bytes"""
224    compiled_filter = Filter()
225    if filter_node.tag == AND:
226        boolean_filter = And()
227        pos = 0
228        for element in filter_node.elements:
229            boolean_filter[pos] = compile_filter(element)
230            pos += 1
231        compiled_filter['and'] = boolean_filter
232    elif filter_node.tag == OR:
233        boolean_filter = Or()
234        pos = 0
235        for element in filter_node.elements:
236            boolean_filter[pos] = compile_filter(element)
237            pos += 1
238        compiled_filter['or'] = boolean_filter
239    elif filter_node.tag == NOT:
240        boolean_filter = Not()
241        boolean_filter['innerNotFilter'] = compile_filter(filter_node.elements[0])
242        compiled_filter.setComponentByName('notFilter', boolean_filter, verifyConstraints=False)  # do not verify constraints because of hack for recursive filters in rfc4511
243
244    elif filter_node.tag == MATCH_APPROX:
245        matching_filter = ApproxMatch()
246        matching_filter['attributeDesc'] = AttributeDescription(filter_node.assertion['attr'])
247        matching_filter['assertionValue'] = AssertionValue(prepare_filter_for_sending(filter_node.assertion['value']))
248        compiled_filter['approxMatch'] = matching_filter
249    elif filter_node.tag == MATCH_GREATER_OR_EQUAL:
250        matching_filter = GreaterOrEqual()
251        matching_filter['attributeDesc'] = AttributeDescription(filter_node.assertion['attr'])
252        matching_filter['assertionValue'] = AssertionValue(prepare_filter_for_sending(filter_node.assertion['value']))
253        compiled_filter['greaterOrEqual'] = matching_filter
254    elif filter_node.tag == MATCH_LESS_OR_EQUAL:
255        matching_filter = LessOrEqual()
256        matching_filter['attributeDesc'] = AttributeDescription(filter_node.assertion['attr'])
257        matching_filter['assertionValue'] = AssertionValue(prepare_filter_for_sending(filter_node.assertion['value']))
258        compiled_filter['lessOrEqual'] = matching_filter
259    elif filter_node.tag == MATCH_EXTENSIBLE:
260        matching_filter = ExtensibleMatch()
261        if filter_node.assertion['matchingRule']:
262            matching_filter['matchingRule'] = MatchingRule(filter_node.assertion['matchingRule'])
263        if filter_node.assertion['attr']:
264            matching_filter['type'] = Type(filter_node.assertion['attr'])
265        matching_filter['matchValue'] = MatchValue(prepare_filter_for_sending(filter_node.assertion['value']))
266        matching_filter['dnAttributes'] = DnAttributes(filter_node.assertion['dnAttributes'])
267        compiled_filter['extensibleMatch'] = matching_filter
268    elif filter_node.tag == MATCH_PRESENT:
269        matching_filter = Present(AttributeDescription(filter_node.assertion['attr']))
270        compiled_filter['present'] = matching_filter
271    elif filter_node.tag == MATCH_SUBSTRING:
272        matching_filter = SubstringFilter()
273        matching_filter['type'] = AttributeDescription(filter_node.assertion['attr'])
274        substrings = Substrings()
275        pos = 0
276        if 'initial' in filter_node.assertion and filter_node.assertion['initial']:
277            substrings[pos] = Substring().setComponentByName('initial', Initial(prepare_filter_for_sending(filter_node.assertion['initial'])))
278            pos += 1
279        if 'any' in filter_node.assertion and filter_node.assertion['any']:
280            for substring in filter_node.assertion['any']:
281                substrings[pos] = Substring().setComponentByName('any', Any(prepare_filter_for_sending(substring)))
282                pos += 1
283        if 'final' in filter_node.assertion and filter_node.assertion['final']:
284            substrings[pos] = Substring().setComponentByName('final', Final(prepare_filter_for_sending(filter_node.assertion['final'])))
285        matching_filter['substrings'] = substrings
286        compiled_filter['substringFilter'] = matching_filter
287    elif filter_node.tag == MATCH_EQUAL:
288        matching_filter = EqualityMatch()
289        matching_filter['attributeDesc'] = AttributeDescription(filter_node.assertion['attr'])
290        matching_filter['assertionValue'] = AssertionValue(prepare_filter_for_sending(filter_node.assertion['value']))
291        compiled_filter.setComponentByName('equalityMatch', matching_filter)
292    else:
293        raise LDAPInvalidFilterError('unknown filter node tag')
294
295    return compiled_filter
296
297
298def build_attribute_selection(attribute_list, schema):
299    conf_attributes_excluded_from_check = [v.lower() for v in get_config_parameter('ATTRIBUTES_EXCLUDED_FROM_CHECK')]
300
301    attribute_selection = AttributeSelection()
302    for index, attribute in enumerate(attribute_list):
303        if schema and schema.attribute_types:
304            if ';' in attribute:  # exclude tags from validation
305                if not attribute[0:attribute.index(';')] in schema.attribute_types and attribute.lower() not in conf_attributes_excluded_from_check:
306                    raise LDAPAttributeError('invalid attribute type in attribute list: ' + attribute)
307            else:
308                if attribute not in schema.attribute_types and attribute.lower() not in conf_attributes_excluded_from_check:
309                    raise LDAPAttributeError('invalid attribute type in attribute list: ' + attribute)
310        attribute_selection[index] = Selector(attribute)
311
312    return attribute_selection
313
314
315def search_operation(search_base,
316                     search_filter,
317                     search_scope,
318                     dereference_aliases,
319                     attributes,
320                     size_limit,
321                     time_limit,
322                     types_only,
323                     auto_escape,
324                     auto_encode,
325                     schema=None,
326                     validator=None,
327                     check_names=False):
328    # SearchRequest ::= [APPLICATION 3] SEQUENCE {
329    # baseObject      LDAPDN,
330    #     scope           ENUMERATED {
331    #         baseObject              (0),
332    #         singleLevel             (1),
333    #         wholeSubtree            (2),
334    #     ...  },
335    #     derefAliases    ENUMERATED {
336    #         neverDerefAliases       (0),
337    #         derefInSearching        (1),
338    #         derefFindingBaseObj     (2),
339    #         derefAlways             (3) },
340    #     sizeLimit       INTEGER (0 ..  maxInt),
341    #     timeLimit       INTEGER (0 ..  maxInt),
342    #     typesOnly       BOOLEAN,
343    #     filter          Filter,
344    #     attributes      AttributeSelection }
345    request = SearchRequest()
346    request['baseObject'] = LDAPDN(search_base)
347
348    if search_scope == BASE or search_scope == 0:
349        request['scope'] = Scope('baseObject')
350    elif search_scope == LEVEL or search_scope == 1:
351        request['scope'] = Scope('singleLevel')
352    elif search_scope == SUBTREE or search_scope == 2:
353        request['scope'] = Scope('wholeSubtree')
354    else:
355        raise LDAPInvalidScopeError('invalid scope type')
356
357    if dereference_aliases == DEREF_NEVER or dereference_aliases == 0:
358        request['derefAliases'] = DerefAliases('neverDerefAliases')
359    elif dereference_aliases == DEREF_SEARCH or dereference_aliases == 1:
360        request['derefAliases'] = DerefAliases('derefInSearching')
361    elif dereference_aliases == DEREF_BASE or dereference_aliases == 2:
362        request['derefAliases'] = DerefAliases('derefFindingBaseObj')
363    elif dereference_aliases == DEREF_ALWAYS or dereference_aliases == 3:
364        request['derefAliases'] = DerefAliases('derefAlways')
365    else:
366        raise LDAPInvalidDereferenceAliasesError('invalid dereference aliases type')
367
368    request['sizeLimit'] = Integer0ToMax(size_limit)
369    request['timeLimit'] = Integer0ToMax(time_limit)
370    request['typesOnly'] = TypesOnly(True) if types_only else TypesOnly(False)
371    request['filter'] = compile_filter(parse_filter(search_filter, schema, auto_escape, auto_encode, validator, check_names).elements[0])  # parse the searchFilter string and compile it starting from the root node
372    if not isinstance(attributes, SEQUENCE_TYPES):
373        attributes = [NO_ATTRIBUTES]
374
375    request['attributes'] = build_attribute_selection(attributes, schema)
376
377    return request
378
379
380def decode_vals(vals):
381    try:
382        return [str(val) for val in vals if val] if vals else None
383    except UnicodeDecodeError:
384        return decode_raw_vals(vals)
385
386def decode_vals_fast(vals):
387    try:
388        return [to_unicode(val[3], from_server=True) for val in vals if val] if vals else None
389    except UnicodeDecodeError:
390        return [val[3] for val in vals if val] if vals else None
391
392
393def attributes_to_dict(attribute_list):
394    conf_case_insensitive_attributes = get_config_parameter('CASE_INSENSITIVE_ATTRIBUTE_NAMES')
395    attributes = CaseInsensitiveDict() if conf_case_insensitive_attributes else dict()
396    for attribute in attribute_list:
397            attributes[str(attribute['type'])] = decode_vals(attribute['vals'])
398    return attributes
399
400
401def attributes_to_dict_fast(attribute_list):
402    conf_case_insensitive_attributes = get_config_parameter('CASE_INSENSITIVE_ATTRIBUTE_NAMES')
403    attributes = CaseInsensitiveDict() if conf_case_insensitive_attributes else dict()
404    for attribute in attribute_list:
405        attributes[to_unicode(attribute[3][0][3], from_server=True)] = decode_vals_fast(attribute[3][1][3])
406
407    return attributes
408
409
410def decode_raw_vals(vals):
411    return [bytes(val) for val in vals] if vals else None
412
413
414def decode_raw_vals_fast(vals):
415    return [bytes(val[3]) for val in vals] if vals else None
416
417
418def raw_attributes_to_dict(attribute_list):
419    conf_case_insensitive_attributes = get_config_parameter('CASE_INSENSITIVE_ATTRIBUTE_NAMES')
420
421    attributes = CaseInsensitiveDict() if conf_case_insensitive_attributes else dict()
422    for attribute in attribute_list:
423        attributes[str(attribute['type'])] = decode_raw_vals(attribute['vals'])
424
425    return attributes
426
427
428def raw_attributes_to_dict_fast(attribute_list):
429    conf_case_insensitive_attributes = get_config_parameter('CASE_INSENSITIVE_ATTRIBUTE_NAMES')
430    attributes = CaseInsensitiveDict() if conf_case_insensitive_attributes else dict()
431    for attribute in attribute_list:
432        attributes[to_unicode(attribute[3][0][3], from_server=True)] = decode_raw_vals_fast(attribute[3][1][3])
433
434    return attributes
435
436
437def checked_attributes_to_dict(attribute_list, schema=None, custom_formatter=None):
438    conf_case_insensitive_attributes = get_config_parameter('CASE_INSENSITIVE_ATTRIBUTE_NAMES')
439
440    checked_attributes = CaseInsensitiveDict() if conf_case_insensitive_attributes else dict()
441    for attribute in attribute_list:
442        name = str(attribute['type'])
443        checked_attributes[name] = format_attribute_values(schema, name, decode_raw_vals(attribute['vals']) or [], custom_formatter)
444    return checked_attributes
445
446
447def checked_attributes_to_dict_fast(attribute_list, schema=None, custom_formatter=None):
448    conf_case_insensitive_attributes = get_config_parameter('CASE_INSENSITIVE_ATTRIBUTE_NAMES')
449
450    checked_attributes = CaseInsensitiveDict() if conf_case_insensitive_attributes else dict()
451    for attribute in attribute_list:
452        name = to_unicode(attribute[3][0][3], from_server=True)
453        checked_attributes[name] = format_attribute_values(schema, name, decode_raw_vals_fast(attribute[3][1][3]) or [], custom_formatter)
454    return checked_attributes
455
456
457def matching_rule_assertion_to_string(matching_rule_assertion):
458    return str(matching_rule_assertion)
459
460
461def filter_to_string(filter_object):
462    filter_type = filter_object.getName()
463    filter_string = '('
464    if filter_type == 'and':
465        filter_string += '&'
466        for f in filter_object['and']:
467            filter_string += filter_to_string(f)
468    elif filter_type == 'or':
469        filter_string += '|'
470        for f in filter_object['or']:
471            filter_string += filter_to_string(f)
472    elif filter_type == 'notFilter':
473        filter_string += '!' + filter_to_string(filter_object['notFilter']['innerNotFilter'])
474    elif filter_type == 'equalityMatch':
475        ava = ava_to_dict(filter_object['equalityMatch'])
476        filter_string += ava['attribute'] + '=' + ava['value']
477    elif filter_type == 'substringFilter':
478        attribute = filter_object['substringFilter']['type']
479        filter_string += str(attribute) + '='
480        for substring in filter_object['substringFilter']['substrings']:
481            component = substring.getName()
482            if substring[component] is not None and substring[component].hasValue():
483                if component == 'initial':
484                    filter_string += str(substring['initial']) + '*'
485                elif component == 'any':
486                    filter_string += str(substring['any']) if filter_string.endswith('*') else '*' + str(substring['any'])
487                    filter_string += '*'
488                elif component == 'final':
489                    filter_string += '*' + str(substring['final'])
490    elif filter_type == 'greaterOrEqual':
491        ava = ava_to_dict(filter_object['greaterOrEqual'])
492        filter_string += ava['attribute'] + '>=' + ava['value']
493    elif filter_type == 'lessOrEqual':
494        ava = ava_to_dict(filter_object['lessOrEqual'])
495        filter_string += ava['attribute'] + '<=' + ava['value']
496    elif filter_type == 'present':
497        filter_string += str(filter_object['present']) + '=*'
498    elif filter_type == 'approxMatch':
499        ava = ava_to_dict(filter_object['approxMatch'])
500        filter_string += ava['attribute'] + '~=' + ava['value']
501    elif filter_type == 'extensibleMatch':
502        filter_string += matching_rule_assertion_to_string(filter_object['extensibleMatch'])
503    else:
504        raise LDAPInvalidFilterError('error converting filter to string')
505    filter_string += ')'
506
507    if str is bytes:  # Python2, forces conversion to Unicode
508        filter_string = to_unicode(filter_string)
509
510    return filter_string
511
512
513def search_request_to_dict(request):
514    return {'base': str(request['baseObject']),
515            'scope': int(request['scope']),
516            'dereferenceAlias': int(request['derefAliases']),
517            'sizeLimit': int(request['sizeLimit']),
518            'timeLimit': int(request['timeLimit']),
519            'typesOnly': bool(request['typesOnly']),
520            'filter': filter_to_string(request['filter']),
521            'attributes': attributes_to_list(request['attributes'])}
522
523
524def search_result_entry_response_to_dict(response, schema, custom_formatter, check_names):
525    entry = dict()
526    # entry['dn'] = str(response['object'])
527    if response['object']:
528        if isinstance(response['object'], STRING_TYPES):  # mock strategies return string not a PyAsn1 object
529            entry['raw_dn'] = to_raw(response['object'])
530            entry['dn'] = to_unicode(response['object'])
531        else:
532            entry['raw_dn'] = str(response['object'])
533            entry['dn'] = to_unicode(bytes(response['object']), from_server=True)
534    else:
535        entry['raw_dn'] = b''
536        entry['dn'] = ''
537    entry['raw_attributes'] = raw_attributes_to_dict(response['attributes'])
538    if check_names:
539        entry['attributes'] = checked_attributes_to_dict(response['attributes'], schema, custom_formatter)
540    else:
541        entry['attributes'] = attributes_to_dict(response['attributes'])
542
543    return entry
544
545
546def search_result_done_response_to_dict(response):
547    result = {'result': int(response['resultCode']),
548            'description': ResultCode().getNamedValues().getName(response['resultCode']),
549            'message': str(response['diagnosticMessage']),
550            'dn': str(response['matchedDN']),
551            'referrals': referrals_to_list(response['referral'])}
552
553    if 'controls' in response:  # used for returning controls in Mock strategies
554        result['controls'] = dict()
555        for control in response['controls']:
556            result['controls'][control[0]] = control[1]
557
558    return result
559
560
561def search_result_reference_response_to_dict(response):
562    return {'uri': search_refs_to_list(response)}
563
564
565def search_result_entry_response_to_dict_fast(response, schema, custom_formatter, check_names):
566    entry_dict = dict()
567    entry_dict['raw_dn'] = response[0][3]
568    entry_dict['dn'] = to_unicode(response[0][3], from_server=True)
569    entry_dict['raw_attributes'] = raw_attributes_to_dict_fast(response[1][3])  # attributes
570    if check_names:
571        entry_dict['attributes'] = checked_attributes_to_dict_fast(response[1][3], schema, custom_formatter)  # attributes
572    else:
573        entry_dict['attributes'] = attributes_to_dict_fast(response[1][3])  # attributes
574
575    return entry_dict
576
577
578def search_result_reference_response_to_dict_fast(response):
579    return {'uri': search_refs_to_list_fast([r[3] for r in response])}
580 
codekingpro/portable-devtools · Team Ai