1""" 2ldap.controls.deref - classes for 3(see https://tools.ietf.org/html/draft-masarati-ldap-deref) 4 5See https://www.python-ldap.org/ for project details. 6""" 7 8__all__ = [ 9 'DEREF_CONTROL_OID', 10 'DereferenceControl', 11] 12 13import ldap.controls 14from ldap.controls import LDAPControl,KNOWN_RESPONSE_CONTROLS 15 16import pyasn1_modules.rfc2251 17from pyasn1.type import namedtype,univ,tag 18from pyasn1.codec.ber import encoder,decoder 19from pyasn1_modules.rfc2251 import LDAPDN,AttributeDescription,AttributeDescriptionList,AttributeValue 20 21 22DEREF_CONTROL_OID = '1.3.6.1.4.1.4203.666.5.16' 23 24 25# Request types 26#--------------------------------------------------------------------------- 27 28# For compatibility with ASN.1 declaration in I-D 29AttributeList = AttributeDescriptionList 30 31class DerefSpec(univ.Sequence): 32 componentType = namedtype.NamedTypes( 33 namedtype.NamedType( 34 'derefAttr', 35 AttributeDescription() 36 ), 37 namedtype.NamedType( 38 'attributes', 39 AttributeList() 40 ), 41 ) 42 43class DerefSpecs(univ.SequenceOf): 44 componentType = DerefSpec() 45 46# Response types 47#--------------------------------------------------------------------------- 48 49 50class AttributeValues(univ.SetOf): 51 componentType = AttributeValue() 52 53 54class PartialAttribute(univ.Sequence): 55 componentType = namedtype.NamedTypes( 56 namedtype.NamedType('type', AttributeDescription()), 57 namedtype.NamedType('vals', AttributeValues()), 58 ) 59 60 61class PartialAttributeList(univ.SequenceOf): 62 componentType = PartialAttribute() 63 tagSet = univ.Sequence.tagSet.tagImplicitly( 64 tag.Tag(tag.tagClassContext,tag.tagFormatConstructed,0) 65 ) 66 67 68class DerefRes(univ.Sequence): 69 componentType = namedtype.NamedTypes( 70 namedtype.NamedType('derefAttr', AttributeDescription()), 71 namedtype.NamedType('derefVal', LDAPDN()), 72 namedtype.OptionalNamedType('attrVals', PartialAttributeList()), 73 ) 74 75 76class DerefResultControlValue(univ.SequenceOf): 77 componentType = DerefRes() 78 79 80class DereferenceControl(LDAPControl): 81 controlType = DEREF_CONTROL_OID 82 83 def __init__(self,criticality=False,derefSpecs=None): 84 LDAPControl.__init__(self,self.controlType,criticality) 85 self.derefSpecs = derefSpecs or {} 86 87 def _derefSpecs(self): 88 deref_specs = DerefSpecs() 89 i = 0 90 for deref_attr,deref_attribute_names in self.derefSpecs.items(): 91 deref_spec = DerefSpec() 92 deref_attributes = AttributeList() 93 for j in range(len(deref_attribute_names)): 94 deref_attributes.setComponentByPosition(j,deref_attribute_names[j]) 95 deref_spec.setComponentByName('derefAttr',AttributeDescription(deref_attr)) 96 deref_spec.setComponentByName('attributes',deref_attributes) 97 deref_specs.setComponentByPosition(i,deref_spec) 98 i += 1 99 return deref_specs 100 101 def encodeControlValue(self): 102 return encoder.encode(self._derefSpecs()) 103 104 def decodeControlValue(self,encodedControlValue): 105 decodedValue,_ = decoder.decode(encodedControlValue,asn1Spec=DerefResultControlValue()) 106 self.derefRes = {} 107 for deref_res in decodedValue: 108 deref_attr,deref_val,deref_vals = deref_res[0],deref_res[1],deref_res[2] 109 partial_attrs_dict = { 110 str(tv[0]): [str(v) for v in tv[1]] 111 for tv in deref_vals or [] 112 } 113 try: 114 self.derefRes[str(deref_attr)].append((str(deref_val),partial_attrs_dict)) 115 except KeyError: 116 self.derefRes[str(deref_attr)] = [(str(deref_val),partial_attrs_dict)] 117 118KNOWN_RESPONSE_CONTROLS[DereferenceControl.controlType] = DereferenceControl 119