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