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.

decoder.py 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #
  2. # This file is part of pyasn1 software.
  3. #
  4. # Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
  5. # License: http://snmplabs.com/pyasn1/license.html
  6. #
  7. from pyasn1 import debug
  8. from pyasn1 import error
  9. from pyasn1.type import base
  10. from pyasn1.type import char
  11. from pyasn1.type import tag
  12. from pyasn1.type import univ
  13. from pyasn1.type import useful
  14. __all__ = ['decode']
  15. class AbstractScalarDecoder(object):
  16. def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
  17. return asn1Spec.clone(pyObject)
  18. class BitStringDecoder(AbstractScalarDecoder):
  19. def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
  20. return asn1Spec.clone(univ.BitString.fromBinaryString(pyObject))
  21. class SequenceOrSetDecoder(object):
  22. def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
  23. asn1Value = asn1Spec.clone()
  24. componentsTypes = asn1Spec.componentType
  25. for field in asn1Value:
  26. if field in pyObject:
  27. asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options)
  28. return asn1Value
  29. class SequenceOfOrSetOfDecoder(object):
  30. def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
  31. asn1Value = asn1Spec.clone()
  32. for pyValue in pyObject:
  33. asn1Value.append(decodeFun(pyValue, asn1Spec.componentType), **options)
  34. return asn1Value
  35. class ChoiceDecoder(object):
  36. def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
  37. asn1Value = asn1Spec.clone()
  38. componentsTypes = asn1Spec.componentType
  39. for field in pyObject:
  40. if field in componentsTypes:
  41. asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options)
  42. break
  43. return asn1Value
  44. tagMap = {
  45. univ.Integer.tagSet: AbstractScalarDecoder(),
  46. univ.Boolean.tagSet: AbstractScalarDecoder(),
  47. univ.BitString.tagSet: BitStringDecoder(),
  48. univ.OctetString.tagSet: AbstractScalarDecoder(),
  49. univ.Null.tagSet: AbstractScalarDecoder(),
  50. univ.ObjectIdentifier.tagSet: AbstractScalarDecoder(),
  51. univ.Enumerated.tagSet: AbstractScalarDecoder(),
  52. univ.Real.tagSet: AbstractScalarDecoder(),
  53. univ.Sequence.tagSet: SequenceOrSetDecoder(), # conflicts with SequenceOf
  54. univ.Set.tagSet: SequenceOrSetDecoder(), # conflicts with SetOf
  55. univ.Choice.tagSet: ChoiceDecoder(), # conflicts with Any
  56. # character string types
  57. char.UTF8String.tagSet: AbstractScalarDecoder(),
  58. char.NumericString.tagSet: AbstractScalarDecoder(),
  59. char.PrintableString.tagSet: AbstractScalarDecoder(),
  60. char.TeletexString.tagSet: AbstractScalarDecoder(),
  61. char.VideotexString.tagSet: AbstractScalarDecoder(),
  62. char.IA5String.tagSet: AbstractScalarDecoder(),
  63. char.GraphicString.tagSet: AbstractScalarDecoder(),
  64. char.VisibleString.tagSet: AbstractScalarDecoder(),
  65. char.GeneralString.tagSet: AbstractScalarDecoder(),
  66. char.UniversalString.tagSet: AbstractScalarDecoder(),
  67. char.BMPString.tagSet: AbstractScalarDecoder(),
  68. # useful types
  69. useful.ObjectDescriptor.tagSet: AbstractScalarDecoder(),
  70. useful.GeneralizedTime.tagSet: AbstractScalarDecoder(),
  71. useful.UTCTime.tagSet: AbstractScalarDecoder()
  72. }
  73. # Put in ambiguous & non-ambiguous types for faster codec lookup
  74. typeMap = {
  75. univ.Integer.typeId: AbstractScalarDecoder(),
  76. univ.Boolean.typeId: AbstractScalarDecoder(),
  77. univ.BitString.typeId: BitStringDecoder(),
  78. univ.OctetString.typeId: AbstractScalarDecoder(),
  79. univ.Null.typeId: AbstractScalarDecoder(),
  80. univ.ObjectIdentifier.typeId: AbstractScalarDecoder(),
  81. univ.Enumerated.typeId: AbstractScalarDecoder(),
  82. univ.Real.typeId: AbstractScalarDecoder(),
  83. # ambiguous base types
  84. univ.Set.typeId: SequenceOrSetDecoder(),
  85. univ.SetOf.typeId: SequenceOfOrSetOfDecoder(),
  86. univ.Sequence.typeId: SequenceOrSetDecoder(),
  87. univ.SequenceOf.typeId: SequenceOfOrSetOfDecoder(),
  88. univ.Choice.typeId: ChoiceDecoder(),
  89. univ.Any.typeId: AbstractScalarDecoder(),
  90. # character string types
  91. char.UTF8String.typeId: AbstractScalarDecoder(),
  92. char.NumericString.typeId: AbstractScalarDecoder(),
  93. char.PrintableString.typeId: AbstractScalarDecoder(),
  94. char.TeletexString.typeId: AbstractScalarDecoder(),
  95. char.VideotexString.typeId: AbstractScalarDecoder(),
  96. char.IA5String.typeId: AbstractScalarDecoder(),
  97. char.GraphicString.typeId: AbstractScalarDecoder(),
  98. char.VisibleString.typeId: AbstractScalarDecoder(),
  99. char.GeneralString.typeId: AbstractScalarDecoder(),
  100. char.UniversalString.typeId: AbstractScalarDecoder(),
  101. char.BMPString.typeId: AbstractScalarDecoder(),
  102. # useful types
  103. useful.ObjectDescriptor.typeId: AbstractScalarDecoder(),
  104. useful.GeneralizedTime.typeId: AbstractScalarDecoder(),
  105. useful.UTCTime.typeId: AbstractScalarDecoder()
  106. }
  107. class Decoder(object):
  108. # noinspection PyDefaultArgument
  109. def __init__(self, tagMap, typeMap):
  110. self.__tagMap = tagMap
  111. self.__typeMap = typeMap
  112. def __call__(self, pyObject, asn1Spec, **options):
  113. if debug.logger & debug.flagDecoder:
  114. logger = debug.logger
  115. else:
  116. logger = None
  117. if logger:
  118. debug.scope.push(type(pyObject).__name__)
  119. logger('decoder called at scope %s, working with type %s' % (debug.scope, type(pyObject).__name__))
  120. if asn1Spec is None or not isinstance(asn1Spec, base.Asn1Item):
  121. raise error.PyAsn1Error('asn1Spec is not valid (should be an instance of an ASN.1 Item, not %s)' % asn1Spec.__class__.__name__)
  122. try:
  123. valueDecoder = self.__typeMap[asn1Spec.typeId]
  124. except KeyError:
  125. # use base type for codec lookup to recover untagged types
  126. baseTagSet = tag.TagSet(asn1Spec.tagSet.baseTag, asn1Spec.tagSet.baseTag)
  127. try:
  128. valueDecoder = self.__tagMap[baseTagSet]
  129. except KeyError:
  130. raise error.PyAsn1Error('Unknown ASN.1 tag %s' % asn1Spec.tagSet)
  131. if logger:
  132. logger('calling decoder %s on Python type %s <%s>' % (type(valueDecoder).__name__, type(pyObject).__name__, repr(pyObject)))
  133. value = valueDecoder(pyObject, asn1Spec, self, **options)
  134. if logger:
  135. logger('decoder %s produced ASN.1 type %s <%s>' % (type(valueDecoder).__name__, type(value).__name__, repr(value)))
  136. debug.scope.pop()
  137. return value
  138. #: Turns Python objects of built-in types into ASN.1 objects.
  139. #:
  140. #: Takes Python objects of built-in types and turns them into a tree of
  141. #: ASN.1 objects (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
  142. #: may be a scalar or an arbitrary nested structure.
  143. #:
  144. #: Parameters
  145. #: ----------
  146. #: pyObject: :py:class:`object`
  147. #: A scalar or nested Python objects
  148. #:
  149. #: Keyword Args
  150. #: ------------
  151. #: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
  152. #: A pyasn1 type object to act as a template guiding the decoder. It is required
  153. #: for successful interpretation of Python objects mapping into their ASN.1
  154. #: representations.
  155. #:
  156. #: Returns
  157. #: -------
  158. #: : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
  159. #: A scalar or constructed pyasn1 object
  160. #:
  161. #: Raises
  162. #: ------
  163. #: :py:class:`~pyasn1.error.PyAsn1Error`
  164. #: On decoding errors
  165. #:
  166. #: Examples
  167. #: --------
  168. #: Decode native Python object into ASN.1 objects with ASN.1 schema
  169. #:
  170. #: .. code-block:: pycon
  171. #:
  172. #: >>> seq = SequenceOf(componentType=Integer())
  173. #: >>> s, _ = decode([1, 2, 3], asn1Spec=seq)
  174. #: >>> str(s)
  175. #: SequenceOf:
  176. #: 1 2 3
  177. #:
  178. decode = Decoder(tagMap, typeMap)