You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

144 lines
6.1 KiB

  1. """
  2. """
  3. # Created on 2014.07.08
  4. #
  5. # Author: Giovanni Cannata
  6. #
  7. # Copyright 2014 - 2019 Giovanni Cannata
  8. #
  9. # This file is part of ldap3.
  10. #
  11. # ldap3 is free software: you can redistribute it and/or modify
  12. # it under the terms of the GNU Lesser General Public License as published
  13. # by the Free Software Foundation, either version 3 of the License, or
  14. # (at your option) any later version.
  15. #
  16. # ldap3 is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU Lesser General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU Lesser General Public License
  22. # along with ldap3 in the COPYING and COPYING.LESSER files.
  23. # If not, see <http://www.gnu.org/licenses/>.
  24. from ... import SUBTREE, DEREF_ALWAYS
  25. from ...utils.dn import safe_dn
  26. from ...core.results import DO_NOT_RAISE_EXCEPTIONS, RESULT_SIZE_LIMIT_EXCEEDED
  27. from ...core.exceptions import LDAPOperationResult
  28. from ...utils.log import log, log_enabled, ERROR, BASIC, PROTOCOL, NETWORK, EXTENDED
  29. def paged_search_generator(connection,
  30. search_base,
  31. search_filter,
  32. search_scope=SUBTREE,
  33. dereference_aliases=DEREF_ALWAYS,
  34. attributes=None,
  35. size_limit=0,
  36. time_limit=0,
  37. types_only=False,
  38. get_operational_attributes=False,
  39. controls=None,
  40. paged_size=100,
  41. paged_criticality=False):
  42. if connection.check_names and search_base:
  43. search_base = safe_dn(search_base)
  44. responses = []
  45. original_connection = None
  46. original_auto_referrals = connection.auto_referrals
  47. connection.auto_referrals = False # disable auto referrals because it cannot handle paged searches
  48. cookie = True # performs search operation at least one time
  49. cachekey = None # for referrals cache
  50. while cookie:
  51. result = connection.search(search_base,
  52. search_filter,
  53. search_scope,
  54. dereference_aliases,
  55. attributes,
  56. size_limit,
  57. time_limit,
  58. types_only,
  59. get_operational_attributes,
  60. controls,
  61. paged_size,
  62. paged_criticality,
  63. None if cookie is True else cookie)
  64. if not isinstance(result, bool):
  65. response, result = connection.get_response(result)
  66. else:
  67. response = connection.response
  68. result = connection.result
  69. if result['referrals'] and original_auto_referrals: # if rererrals are returned start over the loop with a new connection to the referral
  70. if not original_connection:
  71. original_connection = connection
  72. _, connection, cachekey = connection.strategy.create_referral_connection(result['referrals']) # change connection to a valid referrals
  73. continue
  74. responses.extend(response)
  75. try:
  76. cookie = result['controls']['1.2.840.113556.1.4.319']['value']['cookie']
  77. except KeyError:
  78. cookie = None
  79. if connection.raise_exceptions and result and result['result'] not in DO_NOT_RAISE_EXCEPTIONS:
  80. if log_enabled(PROTOCOL):
  81. log(PROTOCOL, 'paged search operation result <%s> for <%s>', result, connection)
  82. if result['result'] == RESULT_SIZE_LIMIT_EXCEEDED:
  83. while responses:
  84. yield responses.pop()
  85. raise LDAPOperationResult(result=result['result'], description=result['description'], dn=result['dn'], message=result['message'], response_type=result['type'])
  86. while responses:
  87. yield responses.pop()
  88. if original_connection:
  89. connection = original_connection
  90. if connection.use_referral_cache and cachekey:
  91. connection.strategy.referral_cache[cachekey] = connection
  92. else:
  93. connection.unbind()
  94. connection.auto_referrals = original_auto_referrals
  95. connection.response = None
  96. def paged_search_accumulator(connection,
  97. search_base,
  98. search_filter,
  99. search_scope=SUBTREE,
  100. dereference_aliases=DEREF_ALWAYS,
  101. attributes=None,
  102. size_limit=0,
  103. time_limit=0,
  104. types_only=False,
  105. get_operational_attributes=False,
  106. controls=None,
  107. paged_size=100,
  108. paged_criticality=False):
  109. if connection.check_names and search_base:
  110. search_base = safe_dn(search_base)
  111. responses = []
  112. for response in paged_search_generator(connection,
  113. search_base,
  114. search_filter,
  115. search_scope,
  116. dereference_aliases,
  117. attributes,
  118. size_limit,
  119. time_limit,
  120. types_only,
  121. get_operational_attributes,
  122. controls,
  123. paged_size,
  124. paged_criticality):
  125. responses.append(response)
  126. connection.response = responses
  127. return responses