123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- # -*- coding: utf-8 -*-
- """
- ldap.controls.psearch - classes for Persistent Search Control
- (see https://tools.ietf.org/html/draft-ietf-ldapext-psearch)
-
- See https://www.python-ldap.org/ for project details.
- """
-
- __all__ = [
- 'PersistentSearchControl',
- 'EntryChangeNotificationControl',
- 'CHANGE_TYPES_INT',
- 'CHANGE_TYPES_STR',
- ]
-
- # Imports from python-ldap 2.4+
- import ldap.controls
- from ldap.controls import RequestControl,ResponseControl,KNOWN_RESPONSE_CONTROLS
-
- # Imports from pyasn1
- from pyasn1.type import namedtype,namedval,univ,constraint
- from pyasn1.codec.ber import encoder,decoder
- from pyasn1_modules.rfc2251 import LDAPDN
-
- #---------------------------------------------------------------------------
- # Constants and classes for Persistent Search Control
- #---------------------------------------------------------------------------
-
- CHANGE_TYPES_INT = {
- 'add':1,
- 'delete':2,
- 'modify':4,
- 'modDN':8,
- }
- CHANGE_TYPES_STR = {v: k for k,v in CHANGE_TYPES_INT.items()}
-
-
- class PersistentSearchControl(RequestControl):
- """
- Implements the request control for persistent search.
-
- changeTypes
- List of strings specifying the types of changes returned by the server.
- Setting to None requests all changes.
- changesOnly
- Boolean which indicates whether only changes are returned by the server.
- returnECs
- Boolean which indicates whether the server should return an
- Entry Change Notification response control
- """
-
- class PersistentSearchControlValue(univ.Sequence):
- componentType = namedtype.NamedTypes(
- namedtype.NamedType('changeTypes',univ.Integer()),
- namedtype.NamedType('changesOnly',univ.Boolean()),
- namedtype.NamedType('returnECs',univ.Boolean()),
- )
-
- controlType = "2.16.840.1.113730.3.4.3"
-
- def __init__(self,criticality=True,changeTypes=None,changesOnly=False,returnECs=True):
- self.criticality,self.changesOnly,self.returnECs = \
- criticality,changesOnly,returnECs
- self.changeTypes = changeTypes or CHANGE_TYPES_INT.values()
-
- def encodeControlValue(self):
- if not type(self.changeTypes)==type(0):
- # Assume a sequence type of integers to be OR-ed
- changeTypes_int = 0
- for ct in self.changeTypes:
- changeTypes_int = changeTypes_int|CHANGE_TYPES_INT.get(ct,ct)
- self.changeTypes = changeTypes_int
- p = self.PersistentSearchControlValue()
- p.setComponentByName('changeTypes',univ.Integer(self.changeTypes))
- p.setComponentByName('changesOnly',univ.Boolean(self.changesOnly))
- p.setComponentByName('returnECs',univ.Boolean(self.returnECs))
- return encoder.encode(p)
-
-
- class ChangeType(univ.Enumerated):
- namedValues = namedval.NamedValues(
- ('add',1),
- ('delete',2),
- ('modify',4),
- ('modDN',8),
- )
- subtypeSpec = univ.Enumerated.subtypeSpec + constraint.SingleValueConstraint(1,2,4,8)
-
-
- class EntryChangeNotificationValue(univ.Sequence):
- componentType = namedtype.NamedTypes(
- namedtype.NamedType('changeType',ChangeType()),
- namedtype.OptionalNamedType('previousDN', LDAPDN()),
- namedtype.OptionalNamedType('changeNumber',univ.Integer()),
- )
-
-
- class EntryChangeNotificationControl(ResponseControl):
- """
- Implements the response control for persistent search.
-
- Class attributes with values extracted from the response control:
-
- changeType
- String indicating the type of change causing this result to be
- returned by the server
- previousDN
- Old DN of the entry in case of a modrdn change
- changeNumber
- A change serial number returned by the server (optional).
- """
-
- controlType = "2.16.840.1.113730.3.4.7"
-
- def decodeControlValue(self,encodedControlValue):
- ecncValue,_ = decoder.decode(encodedControlValue,asn1Spec=EntryChangeNotificationValue())
- self.changeType = int(ecncValue.getComponentByName('changeType'))
- previousDN = ecncValue.getComponentByName('previousDN')
- if previousDN.hasValue():
- self.previousDN = str(previousDN)
- else:
- self.previousDN = None
- changeNumber = ecncValue.getComponentByName('changeNumber')
- if changeNumber.hasValue():
- self.changeNumber = int(changeNumber)
- else:
- self.changeNumber = None
- return (self.changeType,self.previousDN,self.changeNumber)
-
- KNOWN_RESPONSE_CONTROLS[EntryChangeNotificationControl.controlType] = EntryChangeNotificationControl
|