Development of an internal social media platform with personalised dashboards for students
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.

psearch.py 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # -*- coding: utf-8 -*-
  2. """
  3. ldap.controls.psearch - classes for Persistent Search Control
  4. (see https://tools.ietf.org/html/draft-ietf-ldapext-psearch)
  5. See https://www.python-ldap.org/ for project details.
  6. """
  7. __all__ = [
  8. 'PersistentSearchControl',
  9. 'EntryChangeNotificationControl',
  10. 'CHANGE_TYPES_INT',
  11. 'CHANGE_TYPES_STR',
  12. ]
  13. # Imports from python-ldap 2.4+
  14. import ldap.controls
  15. from ldap.controls import RequestControl,ResponseControl,KNOWN_RESPONSE_CONTROLS
  16. # Imports from pyasn1
  17. from pyasn1.type import namedtype,namedval,univ,constraint
  18. from pyasn1.codec.ber import encoder,decoder
  19. from pyasn1_modules.rfc2251 import LDAPDN
  20. #---------------------------------------------------------------------------
  21. # Constants and classes for Persistent Search Control
  22. #---------------------------------------------------------------------------
  23. CHANGE_TYPES_INT = {
  24. 'add':1,
  25. 'delete':2,
  26. 'modify':4,
  27. 'modDN':8,
  28. }
  29. CHANGE_TYPES_STR = {v: k for k,v in CHANGE_TYPES_INT.items()}
  30. class PersistentSearchControl(RequestControl):
  31. """
  32. Implements the request control for persistent search.
  33. changeTypes
  34. List of strings specifying the types of changes returned by the server.
  35. Setting to None requests all changes.
  36. changesOnly
  37. Boolean which indicates whether only changes are returned by the server.
  38. returnECs
  39. Boolean which indicates whether the server should return an
  40. Entry Change Notification response control
  41. """
  42. class PersistentSearchControlValue(univ.Sequence):
  43. componentType = namedtype.NamedTypes(
  44. namedtype.NamedType('changeTypes',univ.Integer()),
  45. namedtype.NamedType('changesOnly',univ.Boolean()),
  46. namedtype.NamedType('returnECs',univ.Boolean()),
  47. )
  48. controlType = "2.16.840.1.113730.3.4.3"
  49. def __init__(self,criticality=True,changeTypes=None,changesOnly=False,returnECs=True):
  50. self.criticality,self.changesOnly,self.returnECs = \
  51. criticality,changesOnly,returnECs
  52. self.changeTypes = changeTypes or CHANGE_TYPES_INT.values()
  53. def encodeControlValue(self):
  54. if not type(self.changeTypes)==type(0):
  55. # Assume a sequence type of integers to be OR-ed
  56. changeTypes_int = 0
  57. for ct in self.changeTypes:
  58. changeTypes_int = changeTypes_int|CHANGE_TYPES_INT.get(ct,ct)
  59. self.changeTypes = changeTypes_int
  60. p = self.PersistentSearchControlValue()
  61. p.setComponentByName('changeTypes',univ.Integer(self.changeTypes))
  62. p.setComponentByName('changesOnly',univ.Boolean(self.changesOnly))
  63. p.setComponentByName('returnECs',univ.Boolean(self.returnECs))
  64. return encoder.encode(p)
  65. class ChangeType(univ.Enumerated):
  66. namedValues = namedval.NamedValues(
  67. ('add',1),
  68. ('delete',2),
  69. ('modify',4),
  70. ('modDN',8),
  71. )
  72. subtypeSpec = univ.Enumerated.subtypeSpec + constraint.SingleValueConstraint(1,2,4,8)
  73. class EntryChangeNotificationValue(univ.Sequence):
  74. componentType = namedtype.NamedTypes(
  75. namedtype.NamedType('changeType',ChangeType()),
  76. namedtype.OptionalNamedType('previousDN', LDAPDN()),
  77. namedtype.OptionalNamedType('changeNumber',univ.Integer()),
  78. )
  79. class EntryChangeNotificationControl(ResponseControl):
  80. """
  81. Implements the response control for persistent search.
  82. Class attributes with values extracted from the response control:
  83. changeType
  84. String indicating the type of change causing this result to be
  85. returned by the server
  86. previousDN
  87. Old DN of the entry in case of a modrdn change
  88. changeNumber
  89. A change serial number returned by the server (optional).
  90. """
  91. controlType = "2.16.840.1.113730.3.4.7"
  92. def decodeControlValue(self,encodedControlValue):
  93. ecncValue,_ = decoder.decode(encodedControlValue,asn1Spec=EntryChangeNotificationValue())
  94. self.changeType = int(ecncValue.getComponentByName('changeType'))
  95. previousDN = ecncValue.getComponentByName('previousDN')
  96. if previousDN.hasValue():
  97. self.previousDN = str(previousDN)
  98. else:
  99. self.previousDN = None
  100. changeNumber = ecncValue.getComponentByName('changeNumber')
  101. if changeNumber.hasValue():
  102. self.changeNumber = int(changeNumber)
  103. else:
  104. self.changeNumber = None
  105. return (self.changeType,self.previousDN,self.changeNumber)
  106. KNOWN_RESPONSE_CONTROLS[EntryChangeNotificationControl.controlType] = EntryChangeNotificationControl