1# 2# This file is part of pyasn1 software. 3# 4# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com> 5# License: http://snmplabs.com/pyasn1/license.html 6# 7import sys 8 9from pyasn1 import error 10from pyasn1.type import tag 11from pyasn1.type import univ 12 13__all__ = ['NumericString', 'PrintableString', 'TeletexString', 'T61String', 'VideotexString', 14 'IA5String', 'GraphicString', 'VisibleString', 'ISO646String', 15 'GeneralString', 'UniversalString', 'BMPString', 'UTF8String'] 16 17NoValue = univ.NoValue 18noValue = univ.noValue 19 20 21class AbstractCharacterString(univ.OctetString): 22 """Creates |ASN.1| schema or value object. 23 24 |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, 25 its objects are immutable and duck-type Python 2 :class:`str` or Python 3 26 :class:`bytes`. When used in octet-stream context, |ASN.1| type assumes 27 "|encoding|" encoding. 28 29 Keyword Args 30 ------------ 31 value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object 32 :class:`unicode` object (Python 2) or :class:`str` (Python 3), 33 alternatively :class:`str` (Python 2) or :class:`bytes` (Python 3) 34 representing octet-stream of serialised unicode string 35 (note `encoding` parameter) or |ASN.1| class instance. 36 If `value` is not given, schema object will be created. 37 38 tagSet: :py:class:`~pyasn1.type.tag.TagSet` 39 Object representing non-default ASN.1 tag(s) 40 41 subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` 42 Object representing non-default ASN.1 subtype constraint(s). Constraints 43 verification for |ASN.1| type occurs automatically on object 44 instantiation. 45 46 encoding: :py:class:`str` 47 Unicode codec ID to encode/decode :class:`unicode` (Python 2) or 48 :class:`str` (Python 3) the payload when |ASN.1| object is used 49 in octet-stream context. 50 51 Raises 52 ------ 53 ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error 54 On constraint violation or bad initializer. 55 """ 56 57 if sys.version_info[0] <= 2: 58 def __str__(self): 59 try: 60 # `str` is Py2 text representation 61 return self._value.encode(self.encoding) 62 63 except UnicodeEncodeError: 64 exc = sys.exc_info()[1] 65 raise error.PyAsn1UnicodeEncodeError( 66 "Can't encode string '%s' with codec " 67 "%s" % (self._value, self.encoding), exc 68 ) 69 70 def __unicode__(self): 71 return unicode(self._value) 72 73 def prettyIn(self, value): 74 try: 75 if isinstance(value, unicode): 76 return value 77 elif isinstance(value, str): 78 return value.decode(self.encoding) 79 elif isinstance(value, (tuple, list)): 80 return self.prettyIn(''.join([chr(x) for x in value])) 81 elif isinstance(value, univ.OctetString): 82 return value.asOctets().decode(self.encoding) 83 else: 84 return unicode(value) 85 86 except (UnicodeDecodeError, LookupError): 87 exc = sys.exc_info()[1] 88 raise error.PyAsn1UnicodeDecodeError( 89 "Can't decode string '%s' with codec " 90 "%s" % (value, self.encoding), exc 91 ) 92 93 def asOctets(self, padding=True): 94 return str(self) 95 96 def asNumbers(self, padding=True): 97 return tuple([ord(x) for x in str(self)]) 98 99 else: 100 def __str__(self): 101 # `unicode` is Py3 text representation 102 return str(self._value) 103 104 def __bytes__(self): 105 try: 106 return self._value.encode(self.encoding) 107 except UnicodeEncodeError: 108 exc = sys.exc_info()[1] 109 raise error.PyAsn1UnicodeEncodeError( 110 "Can't encode string '%s' with codec " 111 "%s" % (self._value, self.encoding), exc 112 ) 113 114 def prettyIn(self, value): 115 try: 116 if isinstance(value, str): 117 return value 118 elif isinstance(value, bytes): 119 return value.decode(self.encoding) 120 elif isinstance(value, (tuple, list)): 121 return self.prettyIn(bytes(value)) 122 elif isinstance(value, univ.OctetString): 123 return value.asOctets().decode(self.encoding) 124 else: 125 return str(value) 126 127 except (UnicodeDecodeError, LookupError): 128 exc = sys.exc_info()[1] 129 raise error.PyAsn1UnicodeDecodeError( 130 "Can't decode string '%s' with codec " 131 "%s" % (value, self.encoding), exc 132 ) 133 134 def asOctets(self, padding=True): 135 return bytes(self) 136 137 def asNumbers(self, padding=True): 138 return tuple(bytes(self)) 139 140 # 141 # See OctetString.prettyPrint() for the explanation 142 # 143 144 def prettyOut(self, value): 145 return value 146 147 def prettyPrint(self, scope=0): 148 # first see if subclass has its own .prettyOut() 149 value = self.prettyOut(self._value) 150 151 if value is not self._value: 152 return value 153 154 return AbstractCharacterString.__str__(self) 155 156 def __reversed__(self): 157 return reversed(self._value) 158 159 160class NumericString(AbstractCharacterString): 161 __doc__ = AbstractCharacterString.__doc__ 162 163 #: Set (on class, not on instance) or return a 164 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 165 #: associated with |ASN.1| type. 166 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 167 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18) 168 ) 169 encoding = 'us-ascii' 170 171 # Optimization for faster codec lookup 172 typeId = AbstractCharacterString.getTypeId() 173 174 175class PrintableString(AbstractCharacterString): 176 __doc__ = AbstractCharacterString.__doc__ 177 178 #: Set (on class, not on instance) or return a 179 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 180 #: associated with |ASN.1| type. 181 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 182 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 19) 183 ) 184 encoding = 'us-ascii' 185 186 # Optimization for faster codec lookup 187 typeId = AbstractCharacterString.getTypeId() 188 189 190class TeletexString(AbstractCharacterString): 191 __doc__ = AbstractCharacterString.__doc__ 192 193 #: Set (on class, not on instance) or return a 194 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 195 #: associated with |ASN.1| type. 196 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 197 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20) 198 ) 199 encoding = 'iso-8859-1' 200 201 # Optimization for faster codec lookup 202 typeId = AbstractCharacterString.getTypeId() 203 204 205class T61String(TeletexString): 206 __doc__ = TeletexString.__doc__ 207 208 # Optimization for faster codec lookup 209 typeId = AbstractCharacterString.getTypeId() 210 211 212class VideotexString(AbstractCharacterString): 213 __doc__ = AbstractCharacterString.__doc__ 214 215 #: Set (on class, not on instance) or return a 216 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 217 #: associated with |ASN.1| type. 218 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 219 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 21) 220 ) 221 encoding = 'iso-8859-1' 222 223 # Optimization for faster codec lookup 224 typeId = AbstractCharacterString.getTypeId() 225 226 227class IA5String(AbstractCharacterString): 228 __doc__ = AbstractCharacterString.__doc__ 229 230 #: Set (on class, not on instance) or return a 231 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 232 #: associated with |ASN.1| type. 233 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 234 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 22) 235 ) 236 encoding = 'us-ascii' 237 238 # Optimization for faster codec lookup 239 typeId = AbstractCharacterString.getTypeId() 240 241 242class GraphicString(AbstractCharacterString): 243 __doc__ = AbstractCharacterString.__doc__ 244 245 #: Set (on class, not on instance) or return a 246 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 247 #: associated with |ASN.1| type. 248 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 249 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 25) 250 ) 251 encoding = 'iso-8859-1' 252 253 # Optimization for faster codec lookup 254 typeId = AbstractCharacterString.getTypeId() 255 256 257class VisibleString(AbstractCharacterString): 258 __doc__ = AbstractCharacterString.__doc__ 259 260 #: Set (on class, not on instance) or return a 261 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 262 #: associated with |ASN.1| type. 263 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 264 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26) 265 ) 266 encoding = 'us-ascii' 267 268 # Optimization for faster codec lookup 269 typeId = AbstractCharacterString.getTypeId() 270 271 272class ISO646String(VisibleString): 273 __doc__ = VisibleString.__doc__ 274 275 # Optimization for faster codec lookup 276 typeId = AbstractCharacterString.getTypeId() 277 278class GeneralString(AbstractCharacterString): 279 __doc__ = AbstractCharacterString.__doc__ 280 281 #: Set (on class, not on instance) or return a 282 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 283 #: associated with |ASN.1| type. 284 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 285 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27) 286 ) 287 encoding = 'iso-8859-1' 288 289 # Optimization for faster codec lookup 290 typeId = AbstractCharacterString.getTypeId() 291 292 293class UniversalString(AbstractCharacterString): 294 __doc__ = AbstractCharacterString.__doc__ 295 296 #: Set (on class, not on instance) or return a 297 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 298 #: associated with |ASN.1| type. 299 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 300 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 28) 301 ) 302 encoding = "utf-32-be" 303 304 # Optimization for faster codec lookup 305 typeId = AbstractCharacterString.getTypeId() 306 307 308class BMPString(AbstractCharacterString): 309 __doc__ = AbstractCharacterString.__doc__ 310 311 #: Set (on class, not on instance) or return a 312 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 313 #: associated with |ASN.1| type. 314 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 315 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30) 316 ) 317 encoding = "utf-16-be" 318 319 # Optimization for faster codec lookup 320 typeId = AbstractCharacterString.getTypeId() 321 322 323class UTF8String(AbstractCharacterString): 324 __doc__ = AbstractCharacterString.__doc__ 325 326 #: Set (on class, not on instance) or return a 327 #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) 328 #: associated with |ASN.1| type. 329 tagSet = AbstractCharacterString.tagSet.tagImplicitly( 330 tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) 331 ) 332 encoding = "utf-8" 333 334 # Optimization for faster codec lookup 335 typeId = AbstractCharacterString.getTypeId() 336