codekingpro/portable-devtools
115k
1#2# This file is part of pyasn1 software.3#4# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>5# License: https://pyasn1.readthedocs.io/en/latest/license.html6#7from collections import OrderedDict8import warnings9 10from pyasn1 import debug11from pyasn1 import error12from pyasn1.compat import _MISSING13from pyasn1.type import base14from pyasn1.type import char15from pyasn1.type import tag16from pyasn1.type import univ17from pyasn1.type import useful18 19__all__ = ['encode']20 21LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_ENCODER)22 23 24class AbstractItemEncoder(object):25 def encode(self, value, encodeFun, **options):26 raise error.PyAsn1Error('Not implemented')27 28 29class BooleanEncoder(AbstractItemEncoder):30 def encode(self, value, encodeFun, **options):31 return bool(value)32 33 34class IntegerEncoder(AbstractItemEncoder):35 def encode(self, value, encodeFun, **options):36 return int(value)37 38 39class BitStringEncoder(AbstractItemEncoder):40 def encode(self, value, encodeFun, **options):41 return str(value)42 43 44class OctetStringEncoder(AbstractItemEncoder):45 def encode(self, value, encodeFun, **options):46 return value.asOctets()47 48 49class TextStringEncoder(AbstractItemEncoder):50 def encode(self, value, encodeFun, **options):51 return str(value)52 53 54class NullEncoder(AbstractItemEncoder):55 def encode(self, value, encodeFun, **options):56 return None57 58 59class ObjectIdentifierEncoder(AbstractItemEncoder):60 def encode(self, value, encodeFun, **options):61 return str(value)62 63 64class RelativeOIDEncoder(AbstractItemEncoder):65 def encode(self, value, encodeFun, **options):66 return str(value)67 68 69class RealEncoder(AbstractItemEncoder):70 def encode(self, value, encodeFun, **options):71 return float(value)72 73 74class SetEncoder(AbstractItemEncoder):75 protoDict = dict76 77 def encode(self, value, encodeFun, **options):78 inconsistency = value.isInconsistent79 if inconsistency:80 raise error.PyAsn1Error(81 f"ASN.1 object {value.__class__.__name__} is inconsistent")82 83 namedTypes = value.componentType84 substrate = self.protoDict()85 86 for idx, (key, subValue) in enumerate(value.items()):87 if namedTypes and namedTypes[idx].isOptional and not value[idx].isValue:88 continue89 substrate[key] = encodeFun(subValue, **options)90 return substrate91 92 93class SequenceEncoder(SetEncoder):94 protoDict = OrderedDict95 96 97class SequenceOfEncoder(AbstractItemEncoder):98 def encode(self, value, encodeFun, **options):99 inconsistency = value.isInconsistent100 if inconsistency:101 raise error.PyAsn1Error(102 f"ASN.1 object {value.__class__.__name__} is inconsistent")103 return [encodeFun(x, **options) for x in value]104 105 106class ChoiceEncoder(SequenceEncoder):107 pass108 109 110class AnyEncoder(AbstractItemEncoder):111 def encode(self, value, encodeFun, **options):112 return value.asOctets()113 114 115TAG_MAP = {116 univ.Boolean.tagSet: BooleanEncoder(),117 univ.Integer.tagSet: IntegerEncoder(),118 univ.BitString.tagSet: BitStringEncoder(),119 univ.OctetString.tagSet: OctetStringEncoder(),120 univ.Null.tagSet: NullEncoder(),121 univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(),122 univ.RelativeOID.tagSet: RelativeOIDEncoder(),123 univ.Enumerated.tagSet: IntegerEncoder(),124 univ.Real.tagSet: RealEncoder(),125 # Sequence & Set have same tags as SequenceOf & SetOf126 univ.SequenceOf.tagSet: SequenceOfEncoder(),127 univ.SetOf.tagSet: SequenceOfEncoder(),128 univ.Choice.tagSet: ChoiceEncoder(),129 # character string types130 char.UTF8String.tagSet: TextStringEncoder(),131 char.NumericString.tagSet: TextStringEncoder(),132 char.PrintableString.tagSet: TextStringEncoder(),133 char.TeletexString.tagSet: TextStringEncoder(),134 char.VideotexString.tagSet: TextStringEncoder(),135 char.IA5String.tagSet: TextStringEncoder(),136 char.GraphicString.tagSet: TextStringEncoder(),137 char.VisibleString.tagSet: TextStringEncoder(),138 char.GeneralString.tagSet: TextStringEncoder(),139 char.UniversalString.tagSet: TextStringEncoder(),140 char.BMPString.tagSet: TextStringEncoder(),141 # useful types142 useful.ObjectDescriptor.tagSet: OctetStringEncoder(),143 useful.GeneralizedTime.tagSet: OctetStringEncoder(),144 useful.UTCTime.tagSet: OctetStringEncoder()145}146 147# Put in ambiguous & non-ambiguous types for faster codec lookup148TYPE_MAP = {149 univ.Boolean.typeId: BooleanEncoder(),150 univ.Integer.typeId: IntegerEncoder(),151 univ.BitString.typeId: BitStringEncoder(),152 univ.OctetString.typeId: OctetStringEncoder(),153 univ.Null.typeId: NullEncoder(),154 univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(),155 univ.RelativeOID.typeId: RelativeOIDEncoder(),156 univ.Enumerated.typeId: IntegerEncoder(),157 univ.Real.typeId: RealEncoder(),158 # Sequence & Set have same tags as SequenceOf & SetOf159 univ.Set.typeId: SetEncoder(),160 univ.SetOf.typeId: SequenceOfEncoder(),161 univ.Sequence.typeId: SequenceEncoder(),162 univ.SequenceOf.typeId: SequenceOfEncoder(),163 univ.Choice.typeId: ChoiceEncoder(),164 univ.Any.typeId: AnyEncoder(),165 # character string types166 char.UTF8String.typeId: OctetStringEncoder(),167 char.NumericString.typeId: OctetStringEncoder(),168 char.PrintableString.typeId: OctetStringEncoder(),169 char.TeletexString.typeId: OctetStringEncoder(),170 char.VideotexString.typeId: OctetStringEncoder(),171 char.IA5String.typeId: OctetStringEncoder(),172 char.GraphicString.typeId: OctetStringEncoder(),173 char.VisibleString.typeId: OctetStringEncoder(),174 char.GeneralString.typeId: OctetStringEncoder(),175 char.UniversalString.typeId: OctetStringEncoder(),176 char.BMPString.typeId: OctetStringEncoder(),177 # useful types178 useful.ObjectDescriptor.typeId: OctetStringEncoder(),179 useful.GeneralizedTime.typeId: OctetStringEncoder(),180 useful.UTCTime.typeId: OctetStringEncoder()181}182 183 184class SingleItemEncoder(object):185 186 TAG_MAP = TAG_MAP187 TYPE_MAP = TYPE_MAP188 189 def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored):190 self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP191 self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP192 193 def __call__(self, value, **options):194 if not isinstance(value, base.Asn1Item):195 raise error.PyAsn1Error(196 'value is not valid (should be an instance of an ASN.1 Item)')197 198 if LOG:199 debug.scope.push(type(value).__name__)200 LOG('encoder called for type %s '201 '<%s>' % (type(value).__name__, value.prettyPrint()))202 203 tagSet = value.tagSet204 205 try:206 concreteEncoder = self._typeMap[value.typeId]207 208 except KeyError:209 # use base type for codec lookup to recover untagged types210 baseTagSet = tag.TagSet(211 value.tagSet.baseTag, value.tagSet.baseTag)212 213 try:214 concreteEncoder = self._tagMap[baseTagSet]215 216 except KeyError:217 raise error.PyAsn1Error('No encoder for %s' % (value,))218 219 if LOG:220 LOG('using value codec %s chosen by '221 '%s' % (concreteEncoder.__class__.__name__, tagSet))222 223 pyObject = concreteEncoder.encode(value, self, **options)224 225 if LOG:226 LOG('encoder %s produced: '227 '%s' % (type(concreteEncoder).__name__, repr(pyObject)))228 debug.scope.pop()229 230 return pyObject231 232 233class Encoder(object):234 SINGLE_ITEM_ENCODER = SingleItemEncoder235 236 def __init__(self, **options):237 self._singleItemEncoder = self.SINGLE_ITEM_ENCODER(**options)238 239 def __call__(self, pyObject, asn1Spec=None, **options):240 return self._singleItemEncoder(241 pyObject, asn1Spec=asn1Spec, **options)242 243 244#: Turns ASN.1 object into a Python built-in type object(s).245#:246#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)247#: walks all its components recursively and produces a Python built-in type or a tree248#: of those.249#:250#: One exception is that instead of :py:class:`dict`, the :py:class:`OrderedDict`251#: is used to preserve ordering of the components in ASN.1 SEQUENCE.252#:253#: Parameters254#: ----------255# asn1Value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)256#: pyasn1 object to encode (or a tree of them)257#:258#: Returns259#: -------260#: : :py:class:`object`261#: Python built-in type instance (or a tree of them)262#:263#: Raises264#: ------265#: ~pyasn1.error.PyAsn1Error266#: On encoding errors267#:268#: Examples269#: --------270#: Encode ASN.1 value object into native Python types271#:272#: .. code-block:: pycon273#:274#: >>> seq = SequenceOf(componentType=Integer())275#: >>> seq.extend([1, 2, 3])276#: >>> encode(seq)277#: [1, 2, 3]278#:279encode = SingleItemEncoder()280 281def __getattr__(attr: str):282 if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):283 warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning, stacklevel=2)284 return globals()[newAttr]285 raise AttributeError(attr)286 