336 lines
11 KiB
Python
336 lines
11 KiB
Python
|
#
|
||
|
# This file is part of pyasn1 software.
|
||
|
#
|
||
|
# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>
|
||
|
# License: https://pyasn1.readthedocs.io/en/latest/license.html
|
||
|
#
|
||
|
import sys
|
||
|
|
||
|
from pyasn1 import error
|
||
|
from pyasn1.type import tag
|
||
|
from pyasn1.type import univ
|
||
|
|
||
|
__all__ = ['NumericString', 'PrintableString', 'TeletexString', 'T61String', 'VideotexString',
|
||
|
'IA5String', 'GraphicString', 'VisibleString', 'ISO646String',
|
||
|
'GeneralString', 'UniversalString', 'BMPString', 'UTF8String']
|
||
|
|
||
|
NoValue = univ.NoValue
|
||
|
noValue = univ.noValue
|
||
|
|
||
|
|
||
|
class AbstractCharacterString(univ.OctetString):
|
||
|
"""Creates |ASN.1| schema or value object.
|
||
|
|
||
|
|ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`,
|
||
|
its objects are immutable and duck-type Python 2 :class:`str` or Python 3
|
||
|
:class:`bytes`. When used in octet-stream context, |ASN.1| type assumes
|
||
|
"|encoding|" encoding.
|
||
|
|
||
|
Keyword Args
|
||
|
------------
|
||
|
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
|
||
|
:class:`unicode` object (Python 2) or :class:`str` (Python 3),
|
||
|
alternatively :class:`str` (Python 2) or :class:`bytes` (Python 3)
|
||
|
representing octet-stream of serialised unicode string
|
||
|
(note `encoding` parameter) or |ASN.1| class instance.
|
||
|
If `value` is not given, schema object will be created.
|
||
|
|
||
|
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
|
||
|
Object representing non-default ASN.1 tag(s)
|
||
|
|
||
|
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
||
|
Object representing non-default ASN.1 subtype constraint(s). Constraints
|
||
|
verification for |ASN.1| type occurs automatically on object
|
||
|
instantiation.
|
||
|
|
||
|
encoding: :py:class:`str`
|
||
|
Unicode codec ID to encode/decode :class:`unicode` (Python 2) or
|
||
|
:class:`str` (Python 3) the payload when |ASN.1| object is used
|
||
|
in octet-stream context.
|
||
|
|
||
|
Raises
|
||
|
------
|
||
|
~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error
|
||
|
On constraint violation or bad initializer.
|
||
|
"""
|
||
|
|
||
|
if sys.version_info[0] <= 2:
|
||
|
def __str__(self):
|
||
|
try:
|
||
|
# `str` is Py2 text representation
|
||
|
return self._value.encode(self.encoding)
|
||
|
|
||
|
except UnicodeEncodeError:
|
||
|
exc = sys.exc_info()[1]
|
||
|
raise error.PyAsn1UnicodeEncodeError(
|
||
|
"Can't encode string '%s' with codec "
|
||
|
"%s" % (self._value, self.encoding), exc
|
||
|
)
|
||
|
|
||
|
def __unicode__(self):
|
||
|
return unicode(self._value)
|
||
|
|
||
|
def prettyIn(self, value):
|
||
|
try:
|
||
|
if isinstance(value, unicode):
|
||
|
return value
|
||
|
elif isinstance(value, str):
|
||
|
return value.decode(self.encoding)
|
||
|
elif isinstance(value, (tuple, list)):
|
||
|
return self.prettyIn(''.join([chr(x) for x in value]))
|
||
|
elif isinstance(value, univ.OctetString):
|
||
|
return value.asOctets().decode(self.encoding)
|
||
|
else:
|
||
|
return unicode(value)
|
||
|
|
||
|
except (UnicodeDecodeError, LookupError):
|
||
|
exc = sys.exc_info()[1]
|
||
|
raise error.PyAsn1UnicodeDecodeError(
|
||
|
"Can't decode string '%s' with codec "
|
||
|
"%s" % (value, self.encoding), exc
|
||
|
)
|
||
|
|
||
|
def asOctets(self, padding=True):
|
||
|
return str(self)
|
||
|
|
||
|
def asNumbers(self, padding=True):
|
||
|
return tuple([ord(x) for x in str(self)])
|
||
|
|
||
|
else:
|
||
|
def __str__(self):
|
||
|
# `unicode` is Py3 text representation
|
||
|
return str(self._value)
|
||
|
|
||
|
def __bytes__(self):
|
||
|
try:
|
||
|
return self._value.encode(self.encoding)
|
||
|
except UnicodeEncodeError:
|
||
|
exc = sys.exc_info()[1]
|
||
|
raise error.PyAsn1UnicodeEncodeError(
|
||
|
"Can't encode string '%s' with codec "
|
||
|
"%s" % (self._value, self.encoding), exc
|
||
|
)
|
||
|
|
||
|
def prettyIn(self, value):
|
||
|
try:
|
||
|
if isinstance(value, str):
|
||
|
return value
|
||
|
elif isinstance(value, bytes):
|
||
|
return value.decode(self.encoding)
|
||
|
elif isinstance(value, (tuple, list)):
|
||
|
return self.prettyIn(bytes(value))
|
||
|
elif isinstance(value, univ.OctetString):
|
||
|
return value.asOctets().decode(self.encoding)
|
||
|
else:
|
||
|
return str(value)
|
||
|
|
||
|
except (UnicodeDecodeError, LookupError):
|
||
|
exc = sys.exc_info()[1]
|
||
|
raise error.PyAsn1UnicodeDecodeError(
|
||
|
"Can't decode string '%s' with codec "
|
||
|
"%s" % (value, self.encoding), exc
|
||
|
)
|
||
|
|
||
|
def asOctets(self, padding=True):
|
||
|
return bytes(self)
|
||
|
|
||
|
def asNumbers(self, padding=True):
|
||
|
return tuple(bytes(self))
|
||
|
|
||
|
#
|
||
|
# See OctetString.prettyPrint() for the explanation
|
||
|
#
|
||
|
|
||
|
def prettyOut(self, value):
|
||
|
return value
|
||
|
|
||
|
def prettyPrint(self, scope=0):
|
||
|
# first see if subclass has its own .prettyOut()
|
||
|
value = self.prettyOut(self._value)
|
||
|
|
||
|
if value is not self._value:
|
||
|
return value
|
||
|
|
||
|
return AbstractCharacterString.__str__(self)
|
||
|
|
||
|
def __reversed__(self):
|
||
|
return reversed(self._value)
|
||
|
|
||
|
|
||
|
class NumericString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18)
|
||
|
)
|
||
|
encoding = 'us-ascii'
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class PrintableString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 19)
|
||
|
)
|
||
|
encoding = 'us-ascii'
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class TeletexString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20)
|
||
|
)
|
||
|
encoding = 'iso-8859-1'
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class T61String(TeletexString):
|
||
|
__doc__ = TeletexString.__doc__
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class VideotexString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 21)
|
||
|
)
|
||
|
encoding = 'iso-8859-1'
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class IA5String(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 22)
|
||
|
)
|
||
|
encoding = 'us-ascii'
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class GraphicString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 25)
|
||
|
)
|
||
|
encoding = 'iso-8859-1'
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class VisibleString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26)
|
||
|
)
|
||
|
encoding = 'us-ascii'
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class ISO646String(VisibleString):
|
||
|
__doc__ = VisibleString.__doc__
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
class GeneralString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27)
|
||
|
)
|
||
|
encoding = 'iso-8859-1'
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class UniversalString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 28)
|
||
|
)
|
||
|
encoding = "utf-32-be"
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class BMPString(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30)
|
||
|
)
|
||
|
encoding = "utf-16-be"
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|
||
|
|
||
|
|
||
|
class UTF8String(AbstractCharacterString):
|
||
|
__doc__ = AbstractCharacterString.__doc__
|
||
|
|
||
|
#: Set (on class, not on instance) or return a
|
||
|
#: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s)
|
||
|
#: associated with |ASN.1| type.
|
||
|
tagSet = AbstractCharacterString.tagSet.tagImplicitly(
|
||
|
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
|
||
|
)
|
||
|
encoding = "utf-8"
|
||
|
|
||
|
# Optimization for faster codec lookup
|
||
|
typeId = AbstractCharacterString.getTypeId()
|