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