doc/news.rst | 2 ++ pyderasn.py | 29 +++++++++++++++++++++++------ tests/test_pyderasn.py | 4 ++-- diff --git a/doc/news.rst b/doc/news.rst index 1c0dea1bd46d9c3b5a3333f0208a4f9961306bac997424ddea5779838c6e1107..1bbb50b6eda98d53f6e0a50c004d873ff096dc0770e126daf29c2c7530f5cd8e 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -6,6 +6,8 @@ 4.4 --- * All errors are inherited from ASN1Error class +* NumericString/PrintableString has allowable_chars property holding all + allowed characters .. _release4.3: diff --git a/pyderasn.py b/pyderasn.py index a13e1ac5c29842bfe994fe0a382651bb3169eaaa2d5dbccdfe967f77a1eff027..5d540b1b6e0e47ca69d8b6ab8dde6a4b2175ac484ca354739016abf56eabdb4d 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -555,6 +555,7 @@ from six import iterbytes from six import PY2 from six import string_types from six import text_type +from six import unichr as six_unichr from six.moves import xrange as six_xrange @@ -3492,39 +3493,55 @@ encoding = "utf-8" asn1_type_name = "UTF8String" -class NumericString(CommonString): +class AllowableCharsMixin(object): + @property + def allowable_chars(self): + if PY2: + return self._allowable_chars + return set(six_unichr(c) for c in self._allowable_chars) + + +class NumericString(AllowableCharsMixin, CommonString): """Numeric string Its value is properly sanitized: only ASCII digits with spaces can be stored. + + >>> NumericString().allowable_chars + set(['3', '4', '7', '5', '1', '0', '8', '9', ' ', '6', '2']) """ __slots__ = () tag_default = tag_encode(18) encoding = "ascii" asn1_type_name = "NumericString" - allowable_chars = set(digits.encode("ascii") + b" ") + _allowable_chars = set(digits.encode("ascii") + b" ") def _value_sanitize(self, value): value = super(NumericString, self)._value_sanitize(value) - if not set(value) <= self.allowable_chars: + if not set(value) <= self._allowable_chars: raise DecodeError("non-numeric value") return value -class PrintableString(CommonString): +class PrintableString(AllowableCharsMixin, CommonString): """Printable string Its value is properly sanitized: see X.680 41.4 table 10. + + >>> PrintableString().allowable_chars + >>> set([' ', "'", ..., 'z']) """ __slots__ = () tag_default = tag_encode(19) encoding = "ascii" asn1_type_name = "PrintableString" - allowable_chars = set((ascii_letters + digits + " '()+,-./:=?").encode("ascii")) + _allowable_chars = set( + (ascii_letters + digits + " '()+,-./:=?").encode("ascii") + ) def _value_sanitize(self, value): value = super(PrintableString, self)._value_sanitize(value) - if not set(value) <= self.allowable_chars: + if not set(value) <= self._allowable_chars: raise DecodeError("non-printable value") return value diff --git a/tests/test_pyderasn.py b/tests/test_pyderasn.py index 43ed60780cb7ab4e2f28db1d9f1c8bd5dfdec0c93577fc805c79c00edda43130..1c23bc05bb593fcdbec8275cb5c477369dfc35b72a9f429c2c88013dc5f93ad5 100644 --- a/tests/test_pyderasn.py +++ b/tests/test_pyderasn.py @@ -5869,10 +5869,10 @@ seq = Seq() seq["erste"] = PrintableString("test") self.assertSequenceEqual(seq.encode(), hexdec("3006130474657374")) # Asterisk is actually not allowable - PrintableString.allowable_chars |= set(b"*") + PrintableString._allowable_chars |= set(b"*") seq["erste"] = PrintableString("test*") self.assertSequenceEqual(seq.encode(), hexdec("30071305746573742a")) - PrintableString.allowable_chars -= set(b"*") + PrintableString._allowable_chars -= set(b"*") class Seq(Sequence): schema = (