mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
bug 1413336 - (1/7) update pyasn1 to 0.3.7 r=ted
MozReview-Commit-ID: L3bvhOZRQyN --HG-- rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/pyasn1/codec/native/__init__.py rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/tests/__init__.py rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/tests/codec/__init__.py rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/tests/codec/ber/__init__.py rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/tests/codec/cer/__init__.py rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/tests/codec/der/__init__.py rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/tests/codec/native/__init__.py rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/tests/compat/__init__.py rename : third_party/python/pyasn1/test/__init__.py => third_party/python/pyasn1/tests/type/__init__.py extra : rebase_source : e44063fcc7984b4c64906cf095390c2210404684
This commit is contained in:
parent
c8aadb27c8
commit
e577789849
278
third_party/python/pyasn1/CHANGES
vendored
278
third_party/python/pyasn1/CHANGES
vendored
@ -1,278 +0,0 @@
|
||||
Revision 0.1.7
|
||||
--------------
|
||||
|
||||
- License updated to vanilla BSD 2-Clause to ease package use
|
||||
(http://opensource.org/licenses/BSD-2-Clause).
|
||||
- Test suite made discoverable by unittest/unittest2 discovery feature.
|
||||
- Fix to decoder working on indefinite length substrate -- end-of-octets
|
||||
marker is now detected by both tag and value. Otherwise zero values may
|
||||
interfere with end-of-octets marker.
|
||||
- Fix to decoder to fail in cases where tagFormat indicates inappropriate
|
||||
format for the type (e.g. BOOLEAN is always PRIMITIVE, SET is always
|
||||
CONSTRUCTED and OCTET STRING is either of the two)
|
||||
- Fix to REAL type encoder to force primitive encoding form encoding.
|
||||
- Fix to CHOICE decoder to handle explicitly tagged, indefinite length
|
||||
mode encoding
|
||||
- Fix to REAL type decoder to handle negative REAL values correctly. Test
|
||||
case added.
|
||||
|
||||
Revision 0.1.6
|
||||
--------------
|
||||
|
||||
- The compact (valueless) way of encoding zero INTEGERs introduced in
|
||||
0.1.5 seems to fail miserably as the world is filled with broken
|
||||
BER decoders. So we had to back off the *encoder* for a while.
|
||||
There's still the IntegerEncoder.supportCompactZero flag which
|
||||
enables compact encoding form whenever it evaluates to True.
|
||||
- Report package version on debugging code initialization.
|
||||
|
||||
Revision 0.1.5
|
||||
--------------
|
||||
|
||||
- Documentation updated and split into chapters to better match
|
||||
web-site contents.
|
||||
- Make prettyPrint() working for non-initialized pyasn1 data objects. It
|
||||
used to throw an exception.
|
||||
- Fix to encoder to produce empty-payload INTEGER values for zeros
|
||||
- Fix to decoder to support empty-payload INTEGER and REAL values
|
||||
- Fix to unit test suites imports to be able to run each from
|
||||
their current directory
|
||||
|
||||
Revision 0.1.4
|
||||
--------------
|
||||
|
||||
- Built-in codec debugging facility added
|
||||
- Added some more checks to ObjectIdentifier BER encoder catching
|
||||
posible 2^8 overflow condition by two leading sub-OIDs
|
||||
- Implementations overriding the AbstractDecoder.valueDecoder method
|
||||
changed to return the rest of substrate behind the item being processed
|
||||
rather than the unprocessed substrate within the item (which is usually
|
||||
empty).
|
||||
- Decoder's recursiveFlag feature generalized as a user callback function
|
||||
which is passed an uninitialized object recovered from substrate and
|
||||
its uninterpreted payload.
|
||||
- Catch inappropriate substrate type passed to decoder.
|
||||
- Expose tagMap/typeMap/Decoder objects at DER decoder to uniform API.
|
||||
- Obsolete __init__.MajorVersionId replaced with __init__.__version__
|
||||
which is now in-sync with distutils.
|
||||
- Package classifiers updated.
|
||||
- The __init__.py's made non-empty (rumors are that they may be optimized
|
||||
out by package managers).
|
||||
- Bail out gracefully whenever Python version is older than 2.4.
|
||||
- Fix to Real codec exponent encoding (should be in 2's complement form),
|
||||
some more test cases added.
|
||||
- Fix in Boolean truth testing built-in methods
|
||||
- Fix to substrate underrun error handling at ObjectIdentifier BER decoder
|
||||
- Fix to BER Boolean decoder that allows other pre-computed
|
||||
values besides 0 and 1
|
||||
- Fix to leading 0x80 octet handling in DER/CER/DER ObjectIdentifier decoder.
|
||||
See http://www.cosic.esat.kuleuven.be/publications/article-1432.pdf
|
||||
|
||||
Revision 0.1.3
|
||||
--------------
|
||||
|
||||
- Include class name into asn1 value constraint violation exception.
|
||||
- Fix to OctetString.prettyOut() method that looses leading zero when
|
||||
building hex string.
|
||||
|
||||
Revision 0.1.2
|
||||
--------------
|
||||
|
||||
- Fix to __long__() to actually return longs on py2k
|
||||
- Fix to OctetString.__str__() workings of a non-initialized object.
|
||||
- Fix to quote initializer of OctetString.__repr__()
|
||||
- Minor fix towards ObjectIdentifier.prettyIn() reliability
|
||||
- ObjectIdentifier.__str__() is aliased to prettyPrint()
|
||||
- Exlicit repr() calls replaced with '%r'
|
||||
|
||||
Revision 0.1.1
|
||||
--------------
|
||||
|
||||
- Hex/bin string initializer to OctetString object reworked
|
||||
(in a backward-incompatible manner)
|
||||
- Fixed float() infinity compatibility issue (affects 2.5 and earlier)
|
||||
- Fixed a bug/typo at Boolean CER encoder.
|
||||
- Major overhawl for Python 2.4 -- 3.2 compatibility:
|
||||
+ get rid of old-style types
|
||||
+ drop string module usage
|
||||
+ switch to rich comparation
|
||||
+ drop explicit long integer type use
|
||||
+ map()/filter() replaced with list comprehension
|
||||
+ apply() replaced with */**args
|
||||
+ switched to use 'key' sort() callback function
|
||||
+ support both __nonzero__() and __bool__() methods
|
||||
+ modified not to use py3k-incompatible exception syntax
|
||||
+ getslice() operator fully replaced with getitem()
|
||||
+ dictionary operations made 2K/3K compatible
|
||||
+ base type for encoding substrate and OctetString-based types
|
||||
is now 'bytes' when running py3k and 'str' otherwise
|
||||
+ OctetString and derivatives now unicode compliant.
|
||||
+ OctetString now supports two python-neutral getters: asOcts() & asInts()
|
||||
+ print OctetString content in hex whenever it is not printable otherwise
|
||||
+ in test suite, implicit relative import replaced with the absolute one
|
||||
+ in test suite, string constants replaced with numerics
|
||||
|
||||
Revision 0.0.13
|
||||
---------------
|
||||
|
||||
- Fix to base10 normalization function that loops on univ.Real(0)
|
||||
|
||||
Revision 0.0.13b
|
||||
----------------
|
||||
|
||||
- ASN.1 Real type is now supported properly.
|
||||
- Objects of Constructed types now support __setitem__()
|
||||
- Set/Sequence objects can now be addressed by their field names (string index)
|
||||
and position (integer index).
|
||||
- Typo fix to ber.SetDecoder code that prevented guided decoding operation.
|
||||
- Fix to explicitly tagged items decoding support.
|
||||
- Fix to OctetString.prettyPrint() to better handle non-printable content.
|
||||
- Fix to repr() workings of Choice objects.
|
||||
|
||||
Revision 0.0.13a
|
||||
----------------
|
||||
|
||||
- Major codec re-design.
|
||||
- Documentation significantly improved.
|
||||
- ASN.1 Any type is now supported.
|
||||
- All example ASN.1 modules moved to separate pyasn1-modules package.
|
||||
- Fix to initial sub-OID overflow condition detection an encoder.
|
||||
- BitString initialization value verification improved.
|
||||
- The Set/Sequence.getNameByPosition() method implemented.
|
||||
- Fix to proper behaviour of PermittedAlphabetConstraint object.
|
||||
- Fix to improper Boolean substrate handling at CER/DER decoders.
|
||||
- Changes towards performance improvement:
|
||||
+ all dict.has_key() & dict.get() invocations replaced with modern syntax
|
||||
(this breaks compatibility with Python 2.1 and older).
|
||||
+ tag and tagset caches introduced to decoder
|
||||
+ decoder code improved to prevent unnecessary pyasn1 objects creation
|
||||
+ allow disabling components verification when setting components to
|
||||
structured types, this is used by decoder whilst running in guided mode.
|
||||
+ BER decoder for integer values now looks up a small set of pre-computed
|
||||
substrate values to save on decoding.
|
||||
+ a few pre-computed values configured to ObjectIdentifier BER encoder.
|
||||
+ ChoiceDecoder split-off SequenceOf one to save on unnecessary checks.
|
||||
+ replace slow hasattr()/getattr() calls with isinstance() introspection.
|
||||
+ track the number of initialized components of Constructed types to save
|
||||
on default/optional components initialization.
|
||||
+ added a shortcut ObjectIdentifier.asTuple() to be used instead of
|
||||
__getitem__() in hotspots.
|
||||
+ use Tag.asTuple() and pure integers at tag encoder.
|
||||
+ introduce and use in decoder the baseTagSet attribute of the built-in
|
||||
ASN.1 types.
|
||||
|
||||
Revision 0.0.12a
|
||||
----------------
|
||||
|
||||
- The individual tag/length/value processing methods of
|
||||
encoder.AbstractItemEncoder renamed (leading underscore stripped)
|
||||
to promote overloading in cases where partial substrate processing
|
||||
is required.
|
||||
- The ocsp.py, ldap.py example scripts added.
|
||||
- Fix to univ.ObjectIdentifier input value handler to disallow negative
|
||||
sub-IDs.
|
||||
|
||||
Revision 0.0.11a
|
||||
----------------
|
||||
|
||||
- Decoder can now treat values of unknown types as opaque OctetString.
|
||||
- Fix to Set/SetOf type decoder to handle uninitialized scalar SetOf
|
||||
components correctly.
|
||||
|
||||
Revision 0.0.10a
|
||||
----------------
|
||||
|
||||
- API versioning mechanics retired (pyasn1.v1 -> pyasn1) what makes
|
||||
it possible to zip-import pyasn1 sources (used by egg and py2exe).
|
||||
|
||||
Revision 0.0.9a
|
||||
---------------
|
||||
|
||||
- Allow any non-zero values in Boolean type BER decoder, as it's in
|
||||
accordnance with the standard.
|
||||
|
||||
Revision 0.0.8a
|
||||
---------------
|
||||
|
||||
- Integer.__index__() now supported (for Python 2.5+).
|
||||
- Fix to empty value encoding in BitString encoder, test case added.
|
||||
- Fix to SequenceOf decoder that prevents it skipping possible Choice
|
||||
typed inner component.
|
||||
- Choice.getName() method added for getting currently set component
|
||||
name.
|
||||
- OctetsString.prettyPrint() does a single str() against its value
|
||||
eliminating an extra quotes.
|
||||
|
||||
Revision 0.0.7a
|
||||
---------------
|
||||
|
||||
- Large tags (>31) now supported by codecs.
|
||||
- Fix to encoder to properly handle explicitly tagged untagged items.
|
||||
- All possible value lengths (up to 256^126) now supported by encoders.
|
||||
- Fix to Tag class constructor to prevent negative IDs.
|
||||
|
||||
Revision 0.0.6a
|
||||
---------------
|
||||
|
||||
- Make use of setuptools.
|
||||
- Constraints derivation verification (isSuperTypeOf()/isSubTypeOf()) fixed.
|
||||
- Fix to constraints comparation logic -- can't cmp() hash values as it
|
||||
may cause false positives due to hash conflicts.
|
||||
|
||||
Revision 0.0.5a
|
||||
---------------
|
||||
|
||||
- Integer BER codec reworked fixing negative values encoding bug.
|
||||
- clone() and subtype() methods of Constructed ASN.1 classes now
|
||||
accept optional cloneValueFlag flag which controls original value
|
||||
inheritance. The default is *not* to inherit original value for
|
||||
performance reasons (this may affect backward compatibility).
|
||||
Performance penalty may be huge on deeply nested Constructed objects
|
||||
re-creation.
|
||||
- Base ASN.1 types (pyasn1.type.univ.*) do not have default values
|
||||
anymore. They remain uninitialized acting as ASN.1 types. In
|
||||
this model, initialized ASN.1 types represent either types with
|
||||
default value installed or a type instance.
|
||||
- Decoders' prototypes are now class instances rather than classes.
|
||||
This is to simplify initial value installation to decoder's
|
||||
prototype value.
|
||||
- Bugfix to BitString BER decoder (trailing bits not regarded).
|
||||
- Bugfix to Constraints use as mapping keys.
|
||||
- Bugfix to Integer & BitString clone() methods
|
||||
- Bugix to the way to distinguish Set from SetOf at CER/DER SetOfEncoder
|
||||
- Adjustments to make it running on Python 1.5.
|
||||
- In tests, substrate constants converted from hex escaped literals into
|
||||
octals to overcome indefinite hex width issue occuring in young Python.
|
||||
- Minor performance optimization of TagSet.isSuperTagSetOf() method
|
||||
- examples/sshkey.py added
|
||||
|
||||
Revision 0.0.4a
|
||||
---------------
|
||||
|
||||
* Asn1ItemBase.prettyPrinter() -> *.prettyPrint()
|
||||
|
||||
Revision 0.0.3a
|
||||
---------------
|
||||
|
||||
* Simple ASN1 objects now hash to their Python value and don't
|
||||
depend upon tag/constraints/etc.
|
||||
* prettyIn & prettyOut methods of SimplleAsn1Object become public
|
||||
* many syntax fixes
|
||||
|
||||
Revision 0.0.2a
|
||||
---------------
|
||||
|
||||
* ConstraintsIntersection.isSuperTypeOf() and
|
||||
ConstraintsIntersection.hasConstraint() implemented
|
||||
* Bugfix to NamedValues initialization code
|
||||
* +/- operators added to NamedValues objects
|
||||
* Integer.__abs__() & Integer.subtype() added
|
||||
* ObjectIdentifier.prettyOut() fixes
|
||||
* Allow subclass components at SequenceAndSetBase
|
||||
* AbstractConstraint.__cmp__() dropped
|
||||
* error.Asn1Error replaced with error.PyAsn1Error
|
||||
|
||||
Revision 0.0.1a
|
||||
---------------
|
||||
|
||||
* Initial public alpha release
|
576
third_party/python/pyasn1/CHANGES.rst
vendored
Normal file
576
third_party/python/pyasn1/CHANGES.rst
vendored
Normal file
@ -0,0 +1,576 @@
|
||||
|
||||
Revision 0.3.7, released 04-10-2017
|
||||
-----------------------------------
|
||||
|
||||
- Fixed ASN.1 time types pickling/deepcopy'ing
|
||||
|
||||
Revision 0.3.6, released 21-09-2017
|
||||
-----------------------------------
|
||||
|
||||
- End-of-octets encoding optimized at ASN.1 encoders
|
||||
- The __getitem__/__setitem__ behavior of Set/Sequence and SetOf/SequenceOf
|
||||
objects aligned with the canonical Mapping and Sequence protocols in part
|
||||
- Fixed crash in ASN.1 encoder when encoding an explicitly tagged
|
||||
component of a Sequence
|
||||
|
||||
Revision 0.3.5, released 16-09-2017
|
||||
-----------------------------------
|
||||
|
||||
- Codecs signatures unified and pass the options kwargs through the
|
||||
call chain
|
||||
- Explicit tag encoding optimized to avoid unnecessary copying
|
||||
- End-of-octets sentinel encoding optimized
|
||||
- Refactored ASN.1 codecs properties to silently enforce proper
|
||||
length and chunk size encoding modes
|
||||
- Fixed DER encoder to always produce primitive encoding
|
||||
- Fixed crash at SequenceOf native decoder
|
||||
- Fixed Real.prettyPrint() to fail gracefully on overflow
|
||||
- Fixed a couple of crashes when debug mode is enabled
|
||||
|
||||
Revision 0.3.4, released 07-09-2017
|
||||
-----------------------------------
|
||||
|
||||
- Fixed Native encoder to handle SEQUENCE/SET objects without
|
||||
the componentType property
|
||||
- Added missing component-less SEQUENCE/SET objects dict duck-typing support
|
||||
- Fixed unnecessary duplicate tags detection at NamesType.tagMap
|
||||
- Fixed crash at SEQUENCE and SEQUENCE OF CER encoder when running
|
||||
in schemaless mode
|
||||
- Fixed Character types instantiation from OctetString type -- double
|
||||
unicode decoding may have scrambled the data
|
||||
|
||||
Revision 0.3.3, released 27-08-2017
|
||||
-----------------------------------
|
||||
|
||||
- Improved ASN.1 types instantiation performance
|
||||
- Improved BER/CER/DER decoder performance by not unconditionally casting
|
||||
substrate into str/bytes.
|
||||
- Fixed exponential index size growth bug when building ambiguous
|
||||
NamedTypes tree
|
||||
- Fixed constructed types decoding failure at BER codec if running
|
||||
in schema-less mode
|
||||
- Fixed crash on prettyPrint'ing a SEQUENCE with no defined components
|
||||
- Fixed SetOf ordering at CER/DER encoder
|
||||
- Fixed crash on conditional binascii module import
|
||||
- Fix to TagSet hash value build
|
||||
|
||||
Revision 0.3.2, released 04-08-2017
|
||||
-----------------------------------
|
||||
|
||||
- Fixed SequenceOf/SetOf types initialization syntax to remain
|
||||
backward compatible with pyasn1 0.2.*
|
||||
- Rectified thread safety issues by moving lazy, run-time computation
|
||||
into object initializer.
|
||||
- Fixed .isValue property to return True for empty SetOf/SequenceOf
|
||||
objects
|
||||
- Fixed GeneralizedTime/UTCTime CER/DER codecs to actually get invoked
|
||||
- Fixed DER/CER encoders handling optional SEQUENCE/SET fields containing
|
||||
nested SEQUENCE/SET with optional fields.
|
||||
- Fixed crash in SequenceOf/SetOf pretty printing and decoding (in some
|
||||
cases)
|
||||
- Fixed documentation markup issues.
|
||||
|
||||
Revision 0.3.1, released 26-07-2017
|
||||
-----------------------------------
|
||||
|
||||
- ASN.1 types __init__(), .clone() and .subtype() signatures
|
||||
refactored into keyword arguments to simplify their signatures.
|
||||
- ASN.1 types initialization refactored to minimize the use of
|
||||
relatively expensive isNoValue() call
|
||||
- Lazily pre-populate list of values of Sequence/Set/Choice types
|
||||
- NamedTypes comparison made more efficient
|
||||
- More efficient constraints computation and code clean up
|
||||
- The __getitem__() implementation of some ASN.1 types & tag object
|
||||
refactored for better performance
|
||||
- BER/CER/DER value encoders refactored to produce either tuple of
|
||||
bytes or octet-stream depending on what is more optimal
|
||||
- Reduced the frequency of expensive isinstance() calls
|
||||
- Tag-related classes optimized, refactored into properties and
|
||||
documented.
|
||||
- The NamedValues implementation refactored to mimic Python dict, its use
|
||||
in ASN.1 types refactored into properties and better documented.
|
||||
WARNING: this change introduces a deviation from original API.
|
||||
- NamedType family of classes overhauled, optimized and documented.
|
||||
- The `componentType` attribute of constructed ASN.1 types turned
|
||||
read-only on instances.
|
||||
- Sequence/Set DER/CER/DER decoder optimized to skip the case of
|
||||
reordered components handling when not necessary.
|
||||
- Tags and constraints-related getter methods refactored into read-only
|
||||
instance attributes.
|
||||
- The .hasValue() method refactored into .isValue property. All ASN.1
|
||||
objects now support them, not just scalars.
|
||||
- The Real.{isInfinity, isPlusInfinity, isMinusInfinity} methods
|
||||
refactored into properties and renamed into IsInf, IsPlusInf and isMinusInf
|
||||
- The end-of-octets type refactored to ensure it is a singleton. Codecs
|
||||
changed to rely on that for better performance.
|
||||
- Codecs lookup made more efficient at BER/CER/DER decoder main loop by
|
||||
assigning `typeId` to every ASN.1 type, not just ambiguous ones.
|
||||
- The .getComponent*() methods of constructed ASN.1 types changed
|
||||
to lazily instantiate underlying type rather than return `None`.
|
||||
This should simplify its API as initialization like `X[0][1] = 2` becomes
|
||||
possible.
|
||||
WARNING: this change introduces a deviation from the original API.
|
||||
- The .setComponent*() methods of SetOf/SequenceOf types changed not
|
||||
to allow uninitialized "holes" inside the sequences of their components.
|
||||
They now behave similarly to Python lists.
|
||||
WARNING: this change introduces a deviation from the original API.
|
||||
- Default and optional components en/decoding of Constructed type
|
||||
refactored towards better efficiency and more control.
|
||||
- OctetsString and Any decoder optimized to avoid creating ASN.1
|
||||
objects for chunks of substrate. Instead they now join substrate
|
||||
chunks together and create ASN.1 object from it just once.
|
||||
- The GeneralizedTime and UTCTime types now support to/from Python
|
||||
datetime object conversion.
|
||||
- Unit tests added for the `compat` sub-package.
|
||||
- Fixed BitString named bits initialization bug.
|
||||
- Fixed non-functional tag cache (when running Python 2) at DER decoder.
|
||||
- Fixed chunked encoding restriction on DER encoder.
|
||||
- Fixed SET components ordering at DER encoder.
|
||||
- Fixed BIT STRING & OCTET STRING encoding to be always non-chunked (e.g.
|
||||
primitive) at DER encoder
|
||||
- Fixed `compat.integer.from_bytes()` behaviour on empty input.
|
||||
|
||||
Revision 0.2.3, released 25-02-2017
|
||||
-----------------------------------
|
||||
|
||||
- Improved SEQUENCE/SET/CHOICE decoding performance by maintaining a single shared
|
||||
NamedType object for all instances of SEQUENCE/SET object.
|
||||
- Improved INTEGER encoding/decoding by switching to Python's built-in
|
||||
integer serialization functions.
|
||||
- Improved BitString performance by rebasing it onto Python int type and leveraging
|
||||
fast Integer serialization functions.
|
||||
- BitString type usability improved in many ways: for example bitshifting and
|
||||
numeric operation on BitString is now possible.
|
||||
- Minor ObjectIdentifier type performance optimization.
|
||||
- ASN.1 character types refactored to keep unicode contents internally
|
||||
(rather than serialized octet stream) and duck-type it directly.
|
||||
- ASN.1 OctetString initialized from a Python object performs bytes()
|
||||
on it when running on Python 3 (used to do str() which is probably
|
||||
less logical).
|
||||
- Missing support for NoValue.__sizeof__ added.
|
||||
- Added checks to make sure SEQUENCE/SET components being assigned
|
||||
match the prototypes.
|
||||
- Setter methods for constructed types consistently accept matchTags
|
||||
and matchConstraints flags to control the strictness of inner
|
||||
components compatibility verification. Previously, these checks
|
||||
were tied to verifyConstraints flag, now they are all independent.
|
||||
- General documentation improvements here and there.
|
||||
- Fix to __reversed__() magic to make it returning an iterator.
|
||||
- Test suite simplified and unified.
|
||||
- The __all__ variable added to most of the Python modules.
|
||||
- The "test" directory renamed into "tests" not to collide with
|
||||
the "test" module.
|
||||
|
||||
Revision 0.2.2, released 07-02-2017
|
||||
-----------------------------------
|
||||
|
||||
- FIX TO A SECURITY WEAKNESS: define length only decoders could have successfully
|
||||
processed indefinite length serialization.
|
||||
- FIX TO A SECURITY WEAKNESS: canonical decoders (CER/DER) may have successfully
|
||||
consumed non-canonical variations of (otherwise valid) serialization.
|
||||
- Broken Enumerated subtyping fixed.
|
||||
|
||||
Revision 0.2.1, released 05-02-2017
|
||||
-----------------------------------
|
||||
|
||||
- FIX TO A SECURITY WEAKNESS: BER decoder improperly cached long tags.
|
||||
- New "native" codec implemented to transform pyasn1 types to Python built-in types and back.
|
||||
- Switched to new-style classes.
|
||||
- Sphinx documentation added.
|
||||
- BitString improvements:
|
||||
|
||||
* simple string of binary digits is now supported as initializer
|
||||
* default str() yields string of binary digits (used to yield str(tuple())
|
||||
* binValue and hexValue initializers added
|
||||
* .asNumbers(), .asOctets() and asInteger() representation added
|
||||
|
||||
- Components of constructed ASN.1 types can now be populated with
|
||||
uninitialized ASN.1 objects by assigning either noValue sentinel or
|
||||
setupComponent() function return in addition to now-legacy None sentinel.
|
||||
This should improve code readability.
|
||||
- NoValue class improved to become a singleton and catch more kinds
|
||||
of access to it.
|
||||
- Compatibility wrappers str2octs() and oct2strs() fixed to run over
|
||||
iso-8859-1 encoding.
|
||||
- Integer changed to emit Real instance if division produces a float.
|
||||
- True division operation now supported by Integer type.
|
||||
- The __contains__(), __reverse__() methods implemented for container types
|
||||
- Iterator protocol support implemented for all container types.
|
||||
Warning, warning, warning: this change may potentially affect backward
|
||||
compatibility when:
|
||||
|
||||
* user class overrides __getitem__() without overriding __iter__()
|
||||
* when user code iterates over SEQUENCE object to get its components (now keys will be yielded)
|
||||
|
||||
- Almost complete Python list and dict protocols added to SequenceOf/SetOf and
|
||||
Sequence/Set respectively
|
||||
- Fix to divmod operation implementation in Integer type.
|
||||
- Fix to IntegerDecoder's precomputed value map on Python 3.
|
||||
- Fix to base ASN.1 types to run in "unicode_literals" mode.
|
||||
- Fix to composite constraints "+" operands ordering (AbstractConstraintSet.__radd__)
|
||||
- Fix to constraints merge in .subtype() -- on merge existing constraints are
|
||||
expanded to accommodate new constraints, not the other way round. When existing
|
||||
constraints are wrapped in ConstraintsIntersection composite, additional
|
||||
constraints being added on subtyping effectively further narrow the set of
|
||||
allowed values, which aligns well with the notion of subtyping.
|
||||
- Fix to NamedTypes methods to handle .getTagMap() returning None
|
||||
- Fix to Set/Sequence.setDefaultComponents() to return self
|
||||
- Copyright notice added to non-trivial source code files.
|
||||
- Author's email changed, copyright extended to 2017
|
||||
|
||||
Revision 0.1.9, released 28-09-2015
|
||||
-----------------------------------
|
||||
|
||||
- Wheel distribution format now supported.
|
||||
- Extensions added to text files, CVS attic flushed.
|
||||
- Fix to make uninitialized pyasn1 objects failing properly on hash().
|
||||
- Fix to ObjectIdentifier initialization from unicode string.
|
||||
- Fix to CER/DER Boolean decoder - fail on non single-octet payload.
|
||||
|
||||
Revision 0.1.8, released 22-06-2015
|
||||
-----------------------------------
|
||||
|
||||
- ObjectIdentifier codec fixed to work properly with arc 0 and arc 2 values.
|
||||
- Explicit limit on ObjectIdentifier arc value size removed.
|
||||
- Unicode initializer support added to OctetString type and derivatives.
|
||||
- New prettyPrintType() abstract method implemented to base pyasn1 types
|
||||
to facilitate encoding errors analysis.
|
||||
- The __str__() method implemented to Tag, TagSet and TagMap classes to
|
||||
ease encoding errors troubleshooting.
|
||||
easing encoding errors
|
||||
- Fix to SEQUENCE and SET types to give them their private componentTypes
|
||||
collection (which is a NamedTypes object) so that they won't collide in
|
||||
a MT execution environment.
|
||||
- Missing T61String,ISO646String character types and ObjectDescriptor useful
|
||||
type added.
|
||||
- Distribute is gone, switched to setuptools completely.
|
||||
- Missing NamedValues.__repr__() added.
|
||||
- The base.NoValue() class, that indicates uninitialized ASN.1 object,
|
||||
made public.
|
||||
- The base.NoValue() class instances now support __repr__() what makes
|
||||
possible to perform repr() on uninitialized pyasn1 types objects.
|
||||
- When comparing ASN.1 types, by-tag and/or by-constraints matching
|
||||
can now be performed with the isSuperTypeOf()/isSameTypeWith() optional
|
||||
flags.
|
||||
- Constructed types now verify their consistency by invoking
|
||||
isSameTypeWith(matchTags=True, matchConstraints=False) and
|
||||
isSuperTypeOf(matchTags=False, matchConstraints=True) for each of their
|
||||
components rather than isSuperTypeOf() as it used to be. Constriants check
|
||||
could be enforced to isSameTypeWith() with the strictConstraints=True
|
||||
constructed classes attribute.
|
||||
- Constructed types can now be initialized with new .setComponents() method
|
||||
which accepts both var-args and keyword-args. Default repr() modified to
|
||||
reflect this change.
|
||||
- NamedTypes() and NamedValues() made comparable.
|
||||
- Test coverage extended to cover pyasn1 types __repr__() function.
|
||||
- The abs(Integer()) & abs(Real()) operation now returns respective pyasn1
|
||||
type, not a Python type.
|
||||
- More Python magic methods implementations added to Integer & Real classes
|
||||
(e.g. __pos__, __neg__, __round__, __floor__, __ceil__, __trunc__)
|
||||
- The Integer.__invert__ Python magic method implemented.
|
||||
- The OctetString.__int__() and .__float__() magic methods implemented.
|
||||
- Handle the case of null writer at Debug printer.
|
||||
- BitString encoder/decoder performance improved.
|
||||
- Built-in debugging is now based on Python logging module.
|
||||
- Fix to NamedType.__repr__() to work properly.
|
||||
- Fixes to __repr__() implementation of many built-in ASN.1 types to take into
|
||||
account all of their initializers such as tagSet, subtypeSpec etc.
|
||||
- String typed float initializer to REAL type now supported.
|
||||
- Float typed mantissa initializer to REAL type for base 2 added.
|
||||
- Encoding bases 8 and 16 support for REAL type binary encoder added.
|
||||
- More strict CER/DER encoders added for GeneralizedTime and UTCTime types.
|
||||
- Asn1Item.hasValue() added to easily distinguish initalized ASN.1 objects
|
||||
from uninitialized ones (e.g. pure types).
|
||||
- Fix to REAL type binary decoder to handle different bases and scale factor.
|
||||
- Fix to TagSet.repr() to include [obsolete] baseTag information.
|
||||
- Fix to broken REAL type decoding handling.
|
||||
- Fix to BitString and OctetString decoders dealing with constructed
|
||||
encoding -- it used to be possible to embed other types in substrate.
|
||||
- DER codec hardened not to tolerate indefinite length encoding/decoding.
|
||||
- Fix to end-of-octest sentinel handling:
|
||||
|
||||
+ require strict two-zeros sentinel encoding
|
||||
+ recognize EOO sentinel only when explicitly requested by caller
|
||||
of the decoder via allowEoo=True parameter (warning: API change)
|
||||
|
||||
Revision 0.1.7
|
||||
--------------
|
||||
|
||||
- License updated to vanilla BSD 2-Clause to ease package use
|
||||
(http://opensource.org/licenses/BSD-2-Clause).
|
||||
- Test suite made discoverable by unittest/unittest2 discovery feature.
|
||||
- Fix to decoder working on indefinite length substrate -- end-of-octets
|
||||
marker is now detected by both tag and value. Otherwise zero values may
|
||||
interfere with end-of-octets marker.
|
||||
- Fix to decoder to fail in cases where tagFormat indicates inappropriate
|
||||
format for the type (e.g. BOOLEAN is always PRIMITIVE, SET is always
|
||||
CONSTRUCTED and OCTET STRING is either of the two)
|
||||
- Fix to REAL type encoder to force primitive encoding form encoding.
|
||||
- Fix to CHOICE decoder to handle explicitly tagged, indefinite length
|
||||
mode encoding
|
||||
- Fix to REAL type decoder to handle negative REAL values correctly. Test
|
||||
case added.
|
||||
|
||||
Revision 0.1.6
|
||||
--------------
|
||||
|
||||
- The compact (valueless) way of encoding zero INTEGERs introduced in
|
||||
0.1.5 seems to fail miserably as the world is filled with broken
|
||||
BER decoders. So we had to back off the *encoder* for a while.
|
||||
There's still the IntegerEncoder.supportCompactZero flag which
|
||||
enables compact encoding form whenever it evaluates to True.
|
||||
- Report package version on debugging code initialization.
|
||||
|
||||
Revision 0.1.5
|
||||
--------------
|
||||
|
||||
- Documentation updated and split into chapters to better match
|
||||
web-site contents.
|
||||
- Make prettyPrint() working for non-initialized pyasn1 data objects. It
|
||||
used to throw an exception.
|
||||
- Fix to encoder to produce empty-payload INTEGER values for zeros
|
||||
- Fix to decoder to support empty-payload INTEGER and REAL values
|
||||
- Fix to unit test suites imports to be able to run each from
|
||||
their current directory
|
||||
|
||||
Revision 0.1.4
|
||||
--------------
|
||||
|
||||
- Built-in codec debugging facility added
|
||||
- Added some more checks to ObjectIdentifier BER encoder catching
|
||||
posible 2^8 overflow condition by two leading sub-OIDs
|
||||
- Implementations overriding the AbstractDecoder.valueDecoder method
|
||||
changed to return the rest of substrate behind the item being processed
|
||||
rather than the unprocessed substrate within the item (which is usually
|
||||
empty).
|
||||
- Decoder's recursiveFlag feature generalized as a user callback function
|
||||
which is passed an uninitialized object recovered from substrate and
|
||||
its uninterpreted payload.
|
||||
- Catch inappropriate substrate type passed to decoder.
|
||||
- Expose tagMap/typeMap/Decoder objects at DER decoder to uniform API.
|
||||
- Obsolete __init__.MajorVersionId replaced with __init__.__version__
|
||||
which is now in-sync with distutils.
|
||||
- Package classifiers updated.
|
||||
- The __init__.py's made non-empty (rumors are that they may be optimized
|
||||
out by package managers).
|
||||
- Bail out gracefully whenever Python version is older than 2.4.
|
||||
- Fix to Real codec exponent encoding (should be in 2's complement form),
|
||||
some more test cases added.
|
||||
- Fix in Boolean truth testing built-in methods
|
||||
- Fix to substrate underrun error handling at ObjectIdentifier BER decoder
|
||||
- Fix to BER Boolean decoder that allows other pre-computed
|
||||
values besides 0 and 1
|
||||
- Fix to leading 0x80 octet handling in DER/CER/DER ObjectIdentifier decoder.
|
||||
See http://www.cosic.esat.kuleuven.be/publications/article-1432.pdf
|
||||
|
||||
Revision 0.1.3
|
||||
--------------
|
||||
|
||||
- Include class name into asn1 value constraint violation exception.
|
||||
- Fix to OctetString.prettyOut() method that looses leading zero when
|
||||
building hex string.
|
||||
|
||||
Revision 0.1.2
|
||||
--------------
|
||||
|
||||
- Fix to __long__() to actually return longs on py2k
|
||||
- Fix to OctetString.__str__() workings of a non-initialized object.
|
||||
- Fix to quote initializer of OctetString.__repr__()
|
||||
- Minor fix towards ObjectIdentifier.prettyIn() reliability
|
||||
- ObjectIdentifier.__str__() is aliased to prettyPrint()
|
||||
- Exlicit repr() calls replaced with '%r'
|
||||
|
||||
Revision 0.1.1
|
||||
--------------
|
||||
|
||||
- Hex/bin string initializer to OctetString object reworked
|
||||
(in a backward-incompatible manner)
|
||||
- Fixed float() infinity compatibility issue (affects 2.5 and earlier)
|
||||
- Fixed a bug/typo at Boolean CER encoder.
|
||||
- Major overhawl for Python 2.4 -- 3.2 compatibility:
|
||||
+ get rid of old-style types
|
||||
+ drop string module usage
|
||||
+ switch to rich comparation
|
||||
+ drop explicit long integer type use
|
||||
+ map()/filter() replaced with list comprehension
|
||||
+ apply() replaced with \*/\*\*args
|
||||
+ switched to use 'key' sort() callback function
|
||||
+ support both __nonzero__() and __bool__() methods
|
||||
+ modified not to use py3k-incompatible exception syntax
|
||||
+ getslice() operator fully replaced with getitem()
|
||||
+ dictionary operations made 2K/3K compatible
|
||||
+ base type for encoding substrate and OctetString-based types
|
||||
is now 'bytes' when running py3k and 'str' otherwise
|
||||
+ OctetString and derivatives now unicode compliant.
|
||||
+ OctetString now supports two python-neutral getters: asOcts() & asInts()
|
||||
+ print OctetString content in hex whenever it is not printable otherwise
|
||||
+ in test suite, implicit relative import replaced with the absolute one
|
||||
+ in test suite, string constants replaced with numerics
|
||||
|
||||
Revision 0.0.13
|
||||
---------------
|
||||
|
||||
- Fix to base10 normalization function that loops on univ.Real(0)
|
||||
|
||||
Revision 0.0.13b
|
||||
----------------
|
||||
|
||||
- ASN.1 Real type is now supported properly.
|
||||
- Objects of Constructed types now support __setitem__()
|
||||
- Set/Sequence objects can now be addressed by their field names (string index)
|
||||
and position (integer index).
|
||||
- Typo fix to ber.SetDecoder code that prevented with schema decoding
|
||||
operation.
|
||||
- Fix to explicitly tagged items decoding support.
|
||||
- Fix to OctetString.prettyPrint() to better handle non-printable content.
|
||||
- Fix to repr() workings of Choice objects.
|
||||
|
||||
Revision 0.0.13a
|
||||
----------------
|
||||
|
||||
- Major codec re-design.
|
||||
- Documentation significantly improved.
|
||||
- ASN.1 Any type is now supported.
|
||||
- All example ASN.1 modules moved to separate pyasn1-modules package.
|
||||
- Fix to initial sub-OID overflow condition detection an encoder.
|
||||
- BitString initialization value verification improved.
|
||||
- The Set/Sequence.getNameByPosition() method implemented.
|
||||
- Fix to proper behaviour of PermittedAlphabetConstraint object.
|
||||
- Fix to improper Boolean substrate handling at CER/DER decoders.
|
||||
- Changes towards performance improvement:
|
||||
|
||||
+ all dict.has_key() & dict.get() invocations replaced with modern syntax
|
||||
(this breaks compatibility with Python 2.1 and older).
|
||||
+ tag and tagset caches introduced to decoder
|
||||
+ decoder code improved to prevent unnecessary pyasn1 objects creation
|
||||
+ allow disabling components verification when setting components to
|
||||
structured types, this is used by decoder whilst running with schema
|
||||
mode.
|
||||
+ BER decoder for integer values now looks up a small set of pre-computed
|
||||
substrate values to save on decoding.
|
||||
+ a few pre-computed values configured to ObjectIdentifier BER encoder.
|
||||
+ ChoiceDecoder split-off SequenceOf one to save on unnecessary checks.
|
||||
+ replace slow hasattr()/getattr() calls with isinstance() introspection.
|
||||
+ track the number of initialized components of Constructed types to save
|
||||
on default/optional components initialization.
|
||||
+ added a shortcut ObjectIdentifier.asTuple() to be used instead of
|
||||
__getitem__() in hotspots.
|
||||
+ use Tag.asTuple() and pure integers at tag encoder.
|
||||
+ introduce and use in decoder the baseTagSet attribute of the built-in
|
||||
ASN.1 types.
|
||||
|
||||
Revision 0.0.12a
|
||||
----------------
|
||||
|
||||
- The individual tag/length/value processing methods of
|
||||
encoder.AbstractItemEncoder renamed (leading underscore stripped)
|
||||
to promote overloading in cases where partial substrate processing
|
||||
is required.
|
||||
- The ocsp.py, ldap.py example scripts added.
|
||||
- Fix to univ.ObjectIdentifier input value handler to disallow negative
|
||||
sub-IDs.
|
||||
|
||||
Revision 0.0.11a
|
||||
----------------
|
||||
|
||||
- Decoder can now treat values of unknown types as opaque OctetString.
|
||||
- Fix to Set/SetOf type decoder to handle uninitialized scalar SetOf
|
||||
components correctly.
|
||||
|
||||
Revision 0.0.10a
|
||||
----------------
|
||||
|
||||
- API versioning mechanics retired (pyasn1.v1 -> pyasn1) what makes
|
||||
it possible to zip-import pyasn1 sources (used by egg and py2exe).
|
||||
|
||||
Revision 0.0.9a
|
||||
---------------
|
||||
|
||||
- Allow any non-zero values in Boolean type BER decoder, as it's in
|
||||
accordnance with the standard.
|
||||
|
||||
Revision 0.0.8a
|
||||
---------------
|
||||
|
||||
- Integer.__index__() now supported (for Python 2.5+).
|
||||
- Fix to empty value encoding in BitString encoder, test case added.
|
||||
- Fix to SequenceOf decoder that prevents it skipping possible Choice
|
||||
typed inner component.
|
||||
- Choice.getName() method added for getting currently set component
|
||||
name.
|
||||
- OctetsString.prettyPrint() does a single str() against its value
|
||||
eliminating an extra quotes.
|
||||
|
||||
Revision 0.0.7a
|
||||
---------------
|
||||
|
||||
- Large tags (>31) now supported by codecs.
|
||||
- Fix to encoder to properly handle explicitly tagged untagged items.
|
||||
- All possible value lengths (up to 256^126) now supported by encoders.
|
||||
- Fix to Tag class constructor to prevent negative IDs.
|
||||
|
||||
Revision 0.0.6a
|
||||
---------------
|
||||
|
||||
- Make use of setuptools.
|
||||
- Constraints derivation verification (isSuperTypeOf()/isSubTypeOf()) fixed.
|
||||
- Fix to constraints comparation logic -- can't cmp() hash values as it
|
||||
may cause false positives due to hash conflicts.
|
||||
|
||||
Revision 0.0.5a
|
||||
---------------
|
||||
|
||||
- Integer BER codec reworked fixing negative values encoding bug.
|
||||
- clone() and subtype() methods of Constructed ASN.1 classes now
|
||||
accept optional cloneValueFlag flag which controls original value
|
||||
inheritance. The default is *not* to inherit original value for
|
||||
performance reasons (this may affect backward compatibility).
|
||||
Performance penalty may be huge on deeply nested Constructed objects
|
||||
re-creation.
|
||||
- Base ASN.1 types (pyasn1.type.univ.*) do not have default values
|
||||
anymore. They remain uninitialized acting as ASN.1 types. In
|
||||
this model, initialized ASN.1 types represent either types with
|
||||
default value installed or a type instance.
|
||||
- Decoders' prototypes are now class instances rather than classes.
|
||||
This is to simplify initial value installation to decoder's
|
||||
prototype value.
|
||||
- Bugfix to BitString BER decoder (trailing bits not regarded).
|
||||
- Bugfix to Constraints use as mapping keys.
|
||||
- Bugfix to Integer & BitString clone() methods
|
||||
- Bugix to the way to distinguish Set from SetOf at CER/DER SetOfEncoder
|
||||
- Adjustments to make it running on Python 1.5.
|
||||
- In tests, substrate constants converted from hex escaped literals into
|
||||
octals to overcome indefinite hex width issue occuring in young Python.
|
||||
- Minor performance optimization of TagSet.isSuperTagSetOf() method
|
||||
- examples/sshkey.py added
|
||||
|
||||
Revision 0.0.4a
|
||||
---------------
|
||||
|
||||
* Asn1ItemBase.prettyPrinter() -> \*.prettyPrint()
|
||||
|
||||
Revision 0.0.3a
|
||||
---------------
|
||||
|
||||
* Simple ASN1 objects now hash to their Python value and don't
|
||||
depend upon tag/constraints/etc.
|
||||
* prettyIn & prettyOut methods of SimplleAsn1Object become public
|
||||
* many syntax fixes
|
||||
|
||||
Revision 0.0.2a
|
||||
---------------
|
||||
|
||||
* ConstraintsIntersection.isSuperTypeOf() and
|
||||
ConstraintsIntersection.hasConstraint() implemented
|
||||
* Bugfix to NamedValues initialization code
|
||||
* +/- operators added to NamedValues objects
|
||||
* Integer.__abs__() & Integer.subtype() added
|
||||
* ObjectIdentifier.prettyOut() fixes
|
||||
* Allow subclass components at SequenceAndSetBase
|
||||
* AbstractConstraint.__cmp__() dropped
|
||||
* error.Asn1Error replaced with error.PyAsn1Error
|
||||
|
||||
Revision 0.0.1a
|
||||
---------------
|
||||
|
||||
* Initial public alpha release
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2005-2013, Ilya Etingof <ilya@glas.net>
|
||||
Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
8
third_party/python/pyasn1/MANIFEST.in
vendored
8
third_party/python/pyasn1/MANIFEST.in
vendored
@ -1,3 +1,5 @@
|
||||
include CHANGES README LICENSE THANKS TODO
|
||||
recursive-include test *.py
|
||||
recursive-include doc *.html
|
||||
include *.rst *.md
|
||||
recursive-include tests *.py
|
||||
recursive-include doc Makefile *.rst conf.py
|
||||
prune doc/build
|
||||
prune doc/source/.templates
|
23
third_party/python/pyasn1/PKG-INFO
vendored
23
third_party/python/pyasn1/PKG-INFO
vendored
@ -1,26 +1,33 @@
|
||||
Metadata-Version: 1.0
|
||||
Metadata-Version: 1.1
|
||||
Name: pyasn1
|
||||
Version: 0.1.7
|
||||
Version: 0.3.7
|
||||
Summary: ASN.1 types and codecs
|
||||
Home-page: http://sourceforge.net/projects/pyasn1/
|
||||
Author: Ilya Etingof <ilya@glas.net>
|
||||
Author-email: ilya@glas.net
|
||||
Home-page: https://github.com/etingof/pyasn1
|
||||
Author: Ilya Etingof <etingof@gmail.com>
|
||||
Author-email: etingof@gmail.com
|
||||
License: BSD
|
||||
Description: A pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208).
|
||||
Description: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)
|
||||
Platform: any
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Education
|
||||
Classifier: Intended Audience :: Information Technology
|
||||
Classifier: Intended Audience :: Science/Research
|
||||
Classifier: Intended Audience :: System Administrators
|
||||
Classifier: Intended Audience :: Telecommunications Industry
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.4
|
||||
Classifier: Programming Language :: Python :: 2.5
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.2
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Topic :: Communications
|
||||
Classifier: Topic :: Security :: Cryptography
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
|
68
third_party/python/pyasn1/README
vendored
68
third_party/python/pyasn1/README
vendored
@ -1,68 +0,0 @@
|
||||
|
||||
ASN.1 library for Python
|
||||
------------------------
|
||||
|
||||
This is an implementation of ASN.1 types and codecs in Python programming
|
||||
language. It has been first written to support particular protocol (SNMP)
|
||||
but then generalized to be suitable for a wide range of protocols
|
||||
based on ASN.1 specification.
|
||||
|
||||
FEATURES
|
||||
--------
|
||||
|
||||
* Generic implementation of ASN.1 types (X.208)
|
||||
* Fully standard compliant BER/CER/DER codecs
|
||||
* 100% Python, works with Python 2.4 up to Python 3.3 (beta 1)
|
||||
* MT-safe
|
||||
|
||||
MISFEATURES
|
||||
-----------
|
||||
|
||||
* No ASN.1 compiler (by-hand ASN.1 spec compilation into Python code required)
|
||||
* Codecs are not restartable
|
||||
|
||||
INSTALLATION
|
||||
------------
|
||||
|
||||
The pyasn1 package uses setuptools/distutils for installation. Thus do
|
||||
either:
|
||||
|
||||
$ easy_install pyasn1
|
||||
|
||||
or
|
||||
|
||||
$ tar zxf pyasn1-0.1.3.tar.gz
|
||||
$ cd pyasn1-0.1.3
|
||||
$ python setup.py install
|
||||
$ cd test
|
||||
$ python suite.py # run unit tests
|
||||
|
||||
OPERATION
|
||||
---------
|
||||
|
||||
Perhaps a typical use would involve [by-hand] compilation of your ASN.1
|
||||
specification into pyasn1-backed Python code at your application.
|
||||
|
||||
For more information on pyasn1 APIs, please, refer to the
|
||||
doc/pyasn1-tutorial.html file in the distribution.
|
||||
|
||||
Also refer to example modules. Take a look at pyasn1-modules package -- maybe
|
||||
it already holds something useful to you.
|
||||
|
||||
AVAILABILITY
|
||||
------------
|
||||
|
||||
The pyasn1 package is distributed under terms and conditions of BSD-style
|
||||
license. See LICENSE file in the distribution. Source code is freely
|
||||
available from:
|
||||
|
||||
http://pyasn1.sf.net
|
||||
|
||||
|
||||
FEEDBACK
|
||||
--------
|
||||
|
||||
Please, send your comments and fixes to mailing lists at project web site.
|
||||
|
||||
=-=-=
|
||||
mailto: ilya@glas.net
|
184
third_party/python/pyasn1/README.md
vendored
Normal file
184
third_party/python/pyasn1/README.md
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
|
||||
ASN.1 library for Python
|
||||
------------------------
|
||||
[![PyPI](https://img.shields.io/pypi/v/pyasn1.svg?maxAge=2592000)](https://pypi.python.org/pypi/pyasn1)
|
||||
[![Python Versions](https://img.shields.io/pypi/pyversions/pyasn1.svg)](https://pypi.python.org/pypi/pyasn1/)
|
||||
[![Build status](https://travis-ci.org/etingof/pyasn1.svg?branch=master)](https://secure.travis-ci.org/etingof/pyasn1)
|
||||
[![Coverage Status](https://img.shields.io/codecov/c/github/etingof/pyasn1.svg)](https://codecov.io/github/etingof/pyasn1)
|
||||
[![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/etingof/pyasn1/master/LICENSE.txt)
|
||||
|
||||
This is a free and open source implementation of ASN.1 types and codecs
|
||||
as a Python package. It has been first written to support particular
|
||||
protocol (SNMP) but then generalized to be suitable for a wide range
|
||||
of protocols based on
|
||||
[ASN.1 specification](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.208-198811-W!!PDF-E&type=items).
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Generic implementation of ASN.1 types (X.208)
|
||||
* Standards compliant BER/CER/DER codecs
|
||||
* Dumps/loads ASN.1 structures from Python types
|
||||
* 100% Python, works with Python 2.4 up to Python 3.6
|
||||
* MT-safe
|
||||
* Contributed ASN.1 compiler [Asn1ate](https://github.com/kimgr/asn1ate)
|
||||
|
||||
Why using pyasn1
|
||||
----------------
|
||||
|
||||
ASN.1 solves the data serialization problem. This solution was
|
||||
designed long ago by the wise Ancients. Back then, they did not
|
||||
have the luxury of wasting bits. That is why ASN.1 is designed
|
||||
to serialize data structures of unbounded complexity into
|
||||
something compact and efficient when it comes to processing
|
||||
the data.
|
||||
|
||||
That probably explains why many network protocols and file formats
|
||||
still rely on the 30+ years old technology. Including a number of
|
||||
high-profile Internet protocols and file formats.
|
||||
|
||||
Quite a number of books cover the topic of ASN.1.
|
||||
[Communication between heterogeneous systems](http://www.oss.com/asn1/dubuisson.html)
|
||||
by Olivier Dubuisson is one of those high quality books freely
|
||||
available on the Internet.
|
||||
|
||||
The pyasn1 package is designed to help Python programmers tackling
|
||||
network protocols and file formats at the comfort of their Python
|
||||
prompt. The tool struggles to capture all aspects of a rather
|
||||
complicated ASN.1 system and to represent it on the Python terms.
|
||||
|
||||
How to use pyasn1
|
||||
-----------------
|
||||
|
||||
With pyasn1 you can build Python objects from ASN.1 data structures.
|
||||
For example, the following ASN.1 data structure:
|
||||
|
||||
```bash
|
||||
Record ::= SEQUENCE {
|
||||
id INTEGER,
|
||||
room [0] INTEGER OPTIONAL,
|
||||
house [1] INTEGER DEFAULT 0
|
||||
}
|
||||
```
|
||||
|
||||
Could be expressed in pyasn1 like this:
|
||||
|
||||
```python
|
||||
class Record(Sequence):
|
||||
componentType = NamedTypes(
|
||||
NamedType('id', Integer()),
|
||||
OptionalNamedType(
|
||||
'room', Integer().subtype(
|
||||
implicitTag=Tag(tagClassContext, tagFormatSimple, 0)
|
||||
)
|
||||
),
|
||||
DefaultedNamedType(
|
||||
'house', Integer(0).subtype(
|
||||
implicitTag=Tag(tagClassContext, tagFormatSimple, 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
It is in the spirit of ASN.1 to take abstract data description
|
||||
and turn it into a programming language specific form.
|
||||
Once you have your ASN.1 data structure expressed in Python, you
|
||||
can use it along the lines of similar Python type (e.g. ASN.1
|
||||
`SET` is similar to Python `dict`, `SET OF` to `list`):
|
||||
|
||||
```python
|
||||
>>> record = Record()
|
||||
>>> record['id'] = 123
|
||||
>>> record['room'] = 321
|
||||
>>> print(record.prettyPrint())
|
||||
Record:
|
||||
id=123
|
||||
room=321
|
||||
>>>
|
||||
```
|
||||
|
||||
Part of the power of ASN.1 comes from its serialization features. You
|
||||
can serialize your data structure and send it over the network.
|
||||
|
||||
```python
|
||||
>>> from pyasn1.codec.der.encoder import encode
|
||||
>>> substrate = encode(record)
|
||||
>>> hexdump(substrate)
|
||||
00000: 30 07 02 01 7B 80 02 01 41
|
||||
```
|
||||
|
||||
Conversely, you can turn serialized ASN.1 content, as received from
|
||||
network or read from a file, into a Python object which you can
|
||||
introspect, modify, encode and send back.
|
||||
|
||||
```python
|
||||
>>> from pyasn1.codec.der.decoder import decode
|
||||
>>> received_record, rest_of_substrate = decode(substrate, asn1Spec=Record())
|
||||
>>>
|
||||
>>> for field in received_record:
|
||||
>>> print('{} is {}'.format(field, received_record[field]))
|
||||
id is 123
|
||||
room is 321
|
||||
house is 0
|
||||
>>>
|
||||
>>> record == received_record
|
||||
True
|
||||
>>> received_record.update(room=123)
|
||||
>>> substrate = encode(received_record)
|
||||
>>> hexdump(substrate)
|
||||
00000: 30 06 02 01 7B 80 01 7B
|
||||
```
|
||||
|
||||
The pyasn1 classes struggle to emulate their Python prototypes (e.g. int,
|
||||
list, dict etc.). But ASN.1 types exhibit more complicated behaviour.
|
||||
To make life easier for a Pythonista, they can turn their pyasn1
|
||||
classes into Python built-ins:
|
||||
|
||||
```python
|
||||
>>> from pyasn1.codec.native.encoder import encode
|
||||
>>> encode(record)
|
||||
{'id': 123, 'room': 321, 'house': 0}
|
||||
```
|
||||
|
||||
Or vice-versa -- you can initialize an ASN.1 structure from a tree of
|
||||
Python objects:
|
||||
|
||||
```python
|
||||
>>> from pyasn1.codec.native.decoder import decode
|
||||
>>> record = decode({'id': 123, 'room': 321, 'house': 0}, asn1Spec=Record())
|
||||
>>> print(record.prettyPrint())
|
||||
Record:
|
||||
id=123
|
||||
room=321
|
||||
>>>
|
||||
```
|
||||
|
||||
With ASN.1 design, serialization codecs are decoupled from data objects,
|
||||
so you could turn every single ASN.1 object into many different
|
||||
serialized forms. As of this moment, pyasn1 supports BER, DER, CER and
|
||||
Python built-ins codecs. The extremely compact PER encoding is expected
|
||||
to be introduced in the upcoming pyasn1 release.
|
||||
|
||||
More information on pyasn1 APIs can be found in the
|
||||
[documentation](http://pyasn1.sourceforge.net),
|
||||
compiled ASN.1 modules for different protocols and file formats
|
||||
could be found in the pyasn1-modules
|
||||
[repo](https://github.com/etingof/pyasn1-modules).
|
||||
|
||||
How to get pyasn1
|
||||
-----------------
|
||||
|
||||
The pyasn1 package is distributed under terms and conditions of 2-clause
|
||||
BSD [license](http://pyasn1.sourceforge.net/license.html). Source code is freely
|
||||
available as a GitHub [repo](https://github.com/etingof/pyasn1).
|
||||
|
||||
You could `pip install pyasn1` or download it from [PyPI](https://pypi.python.org/pypi/pyasn1).
|
||||
|
||||
If something does not work as expected,
|
||||
[open an issue](https://github.com/etingof/pyasn1/issues) at GitHub or
|
||||
post your question [on Stack Overflow](http://stackoverflow.com/questions/ask)
|
||||
or try browsing pyasn1
|
||||
[mailing list archives](https://sourceforge.net/p/pyasn1/mailman/pyasn1-users/).
|
||||
|
||||
Copyright (c) 2005-2017, [Ilya Etingof](mailto:etingof@gmail.com).
|
||||
All rights reserved.
|
4
third_party/python/pyasn1/THANKS
vendored
4
third_party/python/pyasn1/THANKS
vendored
@ -1,4 +0,0 @@
|
||||
Denis S. Otkidach
|
||||
Gregory Golberg
|
||||
Bud P. Bruegger
|
||||
Jacek Konieczny
|
36
third_party/python/pyasn1/TODO
vendored
36
third_party/python/pyasn1/TODO
vendored
@ -1,36 +0,0 @@
|
||||
* Specialize ASN.1 character and useful types
|
||||
* Come up with simpler API for deeply nested constructed objects
|
||||
addressing
|
||||
|
||||
ber.decoder:
|
||||
* suspend codec on underrun error ?
|
||||
* class-static components map (in simple type classes)
|
||||
* present subtypes ?
|
||||
* component presence check wont work at innertypeconst
|
||||
* add the rest of ASN1 types/codecs
|
||||
* type vs value, defaultValue
|
||||
|
||||
ber.encoder:
|
||||
* Asn1Item.clone() / shallowcopy issue
|
||||
* large length encoder?
|
||||
* codec restart
|
||||
* preserve compatible API whenever stateful codec gets implemented
|
||||
* restartable vs incremental
|
||||
* plan: make a stateless univeral decoder, then convert it to restartable
|
||||
then to incremental
|
||||
|
||||
type.useful:
|
||||
* may need to implement prettyIn/Out
|
||||
|
||||
type.char:
|
||||
* may need to implement constraints
|
||||
|
||||
type.univ:
|
||||
* simpler API to constructed objects: value init, recursive
|
||||
|
||||
type.namedtypes
|
||||
* type vs tagset name convention
|
||||
|
||||
general:
|
||||
|
||||
* how untagged TagSet should be initialized?
|
92
third_party/python/pyasn1/TODO.rst
vendored
Normal file
92
third_party/python/pyasn1/TODO.rst
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
Things to be done
|
||||
=================
|
||||
|
||||
Big things to tackle, anyone interested is welcome to fork pyasn1, work on
|
||||
it and come up with a PR!
|
||||
|
||||
New codecs
|
||||
----------
|
||||
|
||||
* PER
|
||||
* OER
|
||||
* XER
|
||||
* LWER
|
||||
* JSON (alinged with existing experimental schemas)
|
||||
|
||||
Lazy codecs
|
||||
-----------
|
||||
|
||||
Implement a thin layer over base types to cache pieces
|
||||
of substrate being decoded till the very moment of ASN.1
|
||||
object access in the parse tree.
|
||||
|
||||
Codecs generator interface
|
||||
--------------------------
|
||||
|
||||
For indefinite length or chunked encoding mode, make codecs
|
||||
iterable producing/consuming substrate/objects.
|
||||
|
||||
ASN.1 schema compiler
|
||||
---------------------
|
||||
|
||||
Ideally, the compiler should parse modern schema files and be
|
||||
designed to emit code for arbitrary languages (including SQL).
|
||||
|
||||
Base types
|
||||
----------
|
||||
|
||||
Implement X.680 constructs, including information schema.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Add examples, including advanced/obscure use cases.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Document more API, add notes and example snippets.
|
||||
|
||||
More fresh modules
|
||||
------------------
|
||||
|
||||
Compile and ship more Pythonized ASN.1 modules for
|
||||
various ASN.1-based protocols (e.g. Kerberos etc).
|
||||
Refresh outdated modules in pyasn1-packages.
|
||||
|
||||
Minor, housekeeping things
|
||||
--------------------------
|
||||
|
||||
* more PEP8'ing at places
|
||||
* consider simplifying repr(), otherwise it tend to be too hard to grasp
|
||||
* Specialize ASN.1 character and useful types
|
||||
|
||||
* ber.decoder:
|
||||
|
||||
* suspend codec on underrun error ?
|
||||
* present subtypes ?
|
||||
* component presence check wont work at innertypeconst
|
||||
* type vs value, defaultValue
|
||||
|
||||
* ber.encoder:
|
||||
|
||||
* Asn1Item.clone() / shallowcopy issue
|
||||
* large length encoder?
|
||||
* lookup type by tag first to allow custom codecs for non-base types
|
||||
|
||||
* type.useful:
|
||||
|
||||
* may need to implement prettyIn/Out
|
||||
|
||||
* type.char:
|
||||
|
||||
* may need to implement constraints
|
||||
|
||||
* type.namedtypes
|
||||
|
||||
* type vs tagset name convention
|
||||
|
||||
* how untagged TagSet should be initialized?
|
||||
|
||||
* type and codecs for Real needs refactoring
|
192
third_party/python/pyasn1/doc/Makefile
vendored
Normal file
192
third_party/python/pyasn1/doc/Makefile
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " applehelp to make an Apple Help Book"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyASN1.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyASN1.qhc"
|
||||
|
||||
applehelp:
|
||||
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
||||
@echo
|
||||
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
||||
@echo "N.B. You won't be able to view it unless you put it in" \
|
||||
"~/Library/Documentation/Help or install it in your application" \
|
||||
"bundle."
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/PyASN1"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyASN1"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
coverage:
|
||||
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||
@echo "Testing of coverage in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/coverage/python.txt."
|
||||
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
503
third_party/python/pyasn1/doc/codecs.html
vendored
503
third_party/python/pyasn1/doc/codecs.html
vendored
@ -1,503 +0,0 @@
|
||||
<html>
|
||||
<title>
|
||||
PyASN1 codecs
|
||||
</title>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<table width=60%>
|
||||
<tr>
|
||||
<td>
|
||||
<h3>
|
||||
2. PyASN1 Codecs
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
In ASN.1 context,
|
||||
<a href=http://en.wikipedia.org/wiki/Codec>codec</a>
|
||||
is a program that transforms between concrete data structures and a stream
|
||||
of octets, suitable for transmission over the wire. This serialized form of
|
||||
data is sometimes called <i>substrate</i> or <i>essence</i>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In pyasn1 implementation, substrate takes shape of Python 3 bytes or
|
||||
Python 2 string objects.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One of the properties of a codec is its ability to cope with incomplete
|
||||
data and/or substrate what implies codec to be stateful. In other words,
|
||||
when decoder runs out of substrate and data item being recovered is still
|
||||
incomplete, stateful codec would suspend and complete data item recovery
|
||||
whenever the rest of substrate becomes available. Similarly, stateful encoder
|
||||
would encode data items in multiple steps waiting for source data to
|
||||
arrive. Codec restartability is especially important when application deals
|
||||
with large volumes of data and/or runs on low RAM. For an interesting
|
||||
discussion on codecs options and design choices, refer to
|
||||
<a href=http://directory.apache.org/subprojects/asn1/>Apache ASN.1 project</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As of this writing, codecs implemented in pyasn1 are all stateless, mostly
|
||||
to keep the code simple.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The pyasn1 package currently supports
|
||||
<a href=http://en.wikipedia.org/wiki/Basic_encoding_rules>BER</a> codec and
|
||||
its variations --
|
||||
<a href=http://en.wikipedia.org/wiki/Canonical_encoding_rules>CER</a> and
|
||||
<a href=http://en.wikipedia.org/wiki/Distinguished_encoding_rules>DER</a>.
|
||||
More ASN.1 codecs are planned for implementation in the future.
|
||||
</p>
|
||||
|
||||
<a name="2.1"></a>
|
||||
<h4>
|
||||
2.1 Encoders
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
Encoder is used for transforming pyasn1 value objects into substrate. Only
|
||||
pyasn1 value objects could be serialized, attempts to process pyasn1 type
|
||||
objects will cause encoder failure.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following code will create a pyasn1 Integer object and serialize it with
|
||||
BER encoder:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> from pyasn1.codec.ber import encoder
|
||||
>>> encoder.encode(univ.Integer(123456))
|
||||
b'\x02\x03\x01\xe2@'
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
BER standard also defines a so-called <i>indefinite length</i> encoding form
|
||||
which makes large data items processing more memory efficient. It is mostly
|
||||
useful when encoder does not have the whole value all at once and the
|
||||
length of the value can not be determined at the beginning of encoding.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<i>Constructed encoding</i> is another feature of BER closely related to the
|
||||
indefinite length form. In essence, a large scalar value (such as ASN.1
|
||||
character BitString type) could be chopped into smaller chunks by encoder
|
||||
and transmitted incrementally to limit memory consumption. Unlike indefinite
|
||||
length case, the length of the whole value must be known in advance when
|
||||
using constructed, definite length encoding form.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Since pyasn1 codecs are not restartable, pyasn1 encoder may only encode data
|
||||
item all at once. However, even in this case, generating indefinite length
|
||||
encoding may help a low-memory receiver, running a restartable decoder,
|
||||
to process a large data item.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> from pyasn1.codec.ber import encoder
|
||||
>>> encoder.encode(
|
||||
... univ.OctetString('The quick brown fox jumps over the lazy dog'),
|
||||
... defMode=False,
|
||||
... maxChunkSize=8
|
||||
... )
|
||||
b'$\x80\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \
|
||||
t\x04\x08he lazy \x04\x03dog\x00\x00'
|
||||
>>>
|
||||
>>> encoder.encode(
|
||||
... univ.OctetString('The quick brown fox jumps over the lazy dog'),
|
||||
... maxChunkSize=8
|
||||
... )
|
||||
b'$7\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \
|
||||
t\x04\x08he lazy \x04\x03dog'
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The <b>defMode</b> encoder parameter disables definite length encoding mode,
|
||||
while the optional <b>maxChunkSize</b> parameter specifies desired
|
||||
substrate chunk size that influences memory requirements at the decoder's end.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To use CER or DER encoders one needs to explicitly import and call them - the
|
||||
APIs are all compatible.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> from pyasn1.codec.ber import encoder as ber_encoder
|
||||
>>> from pyasn1.codec.cer import encoder as cer_encoder
|
||||
>>> from pyasn1.codec.der import encoder as der_encoder
|
||||
>>> ber_encoder.encode(univ.Boolean(True))
|
||||
b'\x01\x01\x01'
|
||||
>>> cer_encoder.encode(univ.Boolean(True))
|
||||
b'\x01\x01\xff'
|
||||
>>> der_encoder.encode(univ.Boolean(True))
|
||||
b'\x01\x01\xff'
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<a name="2.2"></a>
|
||||
<h4>
|
||||
2.2 Decoders
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
In the process of decoding, pyasn1 value objects are created and linked to
|
||||
each other, based on the information containted in the substrate. Thus,
|
||||
the original pyasn1 value object(s) are recovered.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> from pyasn1.codec.ber import encoder, decoder
|
||||
>>> substrate = encoder.encode(univ.Boolean(True))
|
||||
>>> decoder.decode(substrate)
|
||||
(Boolean('True(1)'), b'')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Commenting on the code snippet above, pyasn1 decoder accepts substrate
|
||||
as an argument and returns a tuple of pyasn1 value object (possibly
|
||||
a top-level one in case of constructed object) and unprocessed part
|
||||
of input substrate.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
All pyasn1 decoders can handle both definite and indefinite length
|
||||
encoding modes automatically, explicit switching into one mode
|
||||
to another is not required.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> from pyasn1.codec.ber import encoder, decoder
|
||||
>>> substrate = encoder.encode(
|
||||
... univ.OctetString('The quick brown fox jumps over the lazy dog'),
|
||||
... defMode=False,
|
||||
... maxChunkSize=8
|
||||
... )
|
||||
>>> decoder.decode(substrate)
|
||||
(OctetString(b'The quick brown fox jumps over the lazy dog'), b'')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Speaking of BER/CER/DER encoding, in many situations substrate may not contain
|
||||
all necessary information needed for complete and accurate ASN.1 values
|
||||
recovery. The most obvious cases include implicitly tagged ASN.1 types
|
||||
and constrained types.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As discussed earlier in this handbook, when an ASN.1 type is implicitly
|
||||
tagged, previous outermost tag is lost and never appears in substrate.
|
||||
If it is the base tag that gets lost, decoder is unable to pick type-specific
|
||||
value decoder at its table of built-in types, and therefore recover
|
||||
the value part, based only on the information contained in substrate. The
|
||||
approach taken by pyasn1 decoder is to use a prototype pyasn1 type object (or
|
||||
a set of them) to <i>guide</i> the decoding process by matching [possibly
|
||||
incomplete] tags recovered from substrate with those found in prototype pyasn1
|
||||
type objects (also called pyasn1 specification object further in this paper).
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.codec.ber import decoder
|
||||
>>> decoder.decode(b'\x02\x01\x0c', asn1Spec=univ.Integer())
|
||||
Integer(12), b''
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Decoder would neither modify pyasn1 specification object nor use
|
||||
its current values (if it's a pyasn1 value object), but rather use it as
|
||||
a hint for choosing proper decoder and as a pattern for creating new objects:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, tag
|
||||
>>> from pyasn1.codec.ber import encoder, decoder
|
||||
>>> i = univ.Integer(12345).subtype(
|
||||
... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)
|
||||
... )
|
||||
>>> substrate = encoder.encode(i)
|
||||
>>> substrate
|
||||
b'\x9f(\x0209'
|
||||
>>> decoder.decode(substrate)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.error.PyAsn1Error:
|
||||
TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not in asn1Spec
|
||||
>>> decoder.decode(substrate, asn1Spec=i)
|
||||
(Integer(12345), b'')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Notice in the example above, that an attempt to run decoder without passing
|
||||
pyasn1 specification object fails because recovered tag does not belong
|
||||
to any of the built-in types.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Another important feature of guided decoder operation is the use of
|
||||
values constraints possibly present in pyasn1 specification object.
|
||||
To explain this, we will decode a random integer object into generic Integer
|
||||
and the constrained one.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, constraint
|
||||
>>> from pyasn1.codec.ber import encoder, decoder
|
||||
>>> class DialDigit(univ.Integer):
|
||||
... subtypeSpec = constraint.ValueRangeConstraint(0,9)
|
||||
>>> substrate = encoder.encode(univ.Integer(13))
|
||||
>>> decoder.decode(substrate)
|
||||
(Integer(13), b'')
|
||||
>>> decoder.decode(substrate, asn1Spec=DialDigit())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
ValueRangeConstraint(0, 9) failed at: 13
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Similarily to encoders, to use CER or DER decoders application has to
|
||||
explicitly import and call them - all APIs are compatible.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> from pyasn1.codec.ber import encoder as ber_encoder
|
||||
>>> substrate = ber_encoder.encode(univ.OctetString('http://pyasn1.sf.net'))
|
||||
>>>
|
||||
>>> from pyasn1.codec.ber import decoder as ber_decoder
|
||||
>>> from pyasn1.codec.cer import decoder as cer_decoder
|
||||
>>> from pyasn1.codec.der import decoder as der_decoder
|
||||
>>>
|
||||
>>> ber_decoder.decode(substrate)
|
||||
(OctetString(b'http://pyasn1.sf.net'), b'')
|
||||
>>> cer_decoder.decode(substrate)
|
||||
(OctetString(b'http://pyasn1.sf.net'), b'')
|
||||
>>> der_decoder.decode(substrate)
|
||||
(OctetString(b'http://pyasn1.sf.net'), b'')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<a name="2.2.1"></a>
|
||||
<h4>
|
||||
2.2.1 Decoding untagged types
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
It has already been mentioned, that ASN.1 has two "special case" types:
|
||||
CHOICE and ANY. They are different from other types in part of
|
||||
tagging - unless these two are additionally tagged, neither of them will
|
||||
have their own tag. Therefore these types become invisible in substrate
|
||||
and can not be recovered without passing pyasn1 specification object to
|
||||
decoder.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To explain the issue, we will first prepare a Choice object to deal with:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, namedtype
|
||||
>>> class CodeOrMessage(univ.Choice):
|
||||
... componentType = namedtype.NamedTypes(
|
||||
... namedtype.NamedType('code', univ.Integer()),
|
||||
... namedtype.NamedType('message', univ.OctetString())
|
||||
... )
|
||||
>>>
|
||||
>>> codeOrMessage = CodeOrMessage()
|
||||
>>> codeOrMessage.setComponentByName('message', 'my string value')
|
||||
>>> print(codeOrMessage.prettyPrint())
|
||||
CodeOrMessage:
|
||||
message=b'my string value'
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Let's now encode this Choice object and then decode its substrate
|
||||
with and without pyasn1 specification object:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.codec.ber import encoder, decoder
|
||||
>>> substrate = encoder.encode(codeOrMessage)
|
||||
>>> substrate
|
||||
b'\x04\x0fmy string value'
|
||||
>>> encoder.encode(univ.OctetString('my string value'))
|
||||
b'\x04\x0fmy string value'
|
||||
>>>
|
||||
>>> decoder.decode(substrate)
|
||||
(OctetString(b'my string value'), b'')
|
||||
>>> codeOrMessage, substrate = decoder.decode(substrate, asn1Spec=CodeOrMessage())
|
||||
>>> print(codeOrMessage.prettyPrint())
|
||||
CodeOrMessage:
|
||||
message=b'my string value'
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
First thing to notice in the listing above is that the substrate produced
|
||||
for our Choice value object is equivalent to the substrate for an OctetString
|
||||
object initialized to the same value. In other words, any information about
|
||||
the Choice component is absent in encoding.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sure enough, that kind of substrate will decode into an OctetString object,
|
||||
unless original Choice type object is passed to decoder to guide the decoding
|
||||
process.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Similarily untagged ANY type behaves differently on decoding phase - when
|
||||
decoder bumps into an Any object in pyasn1 specification, it stops decoding
|
||||
and puts all the substrate into a new Any value object in form of an octet
|
||||
string. Concerned application could then re-run decoder with an additional,
|
||||
more exact pyasn1 specification object to recover the contents of Any
|
||||
object.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As it was mentioned elsewhere in this paper, Any type allows for incomplete
|
||||
or changing ASN.1 specification to be handled gracefully by decoder and
|
||||
applications.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To illustrate the working of Any type, we'll have to make the stage
|
||||
by encoding a pyasn1 object and then putting its substrate into an any
|
||||
object.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> from pyasn1.codec.ber import encoder, decoder
|
||||
>>> innerSubstrate = encoder.encode(univ.Integer(1234))
|
||||
>>> innerSubstrate
|
||||
b'\x02\x02\x04\xd2'
|
||||
>>> any = univ.Any(innerSubstrate)
|
||||
>>> any
|
||||
Any(b'\x02\x02\x04\xd2')
|
||||
>>> substrate = encoder.encode(any)
|
||||
>>> substrate
|
||||
b'\x02\x02\x04\xd2'
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
As with Choice type encoding, there is no traces of Any type in substrate.
|
||||
Obviously, the substrate we are dealing with, will decode into the inner
|
||||
[Integer] component, unless pyasn1 specification is given to guide the
|
||||
decoder. Continuing previous code:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> from pyasn1.codec.ber import encoder, decoder
|
||||
|
||||
>>> decoder.decode(substrate)
|
||||
(Integer(1234), b'')
|
||||
>>> any, substrate = decoder.decode(substrate, asn1Spec=univ.Any())
|
||||
>>> any
|
||||
Any(b'\x02\x02\x04\xd2')
|
||||
>>> decoder.decode(str(any))
|
||||
(Integer(1234), b'')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Both CHOICE and ANY types are widely used in practice. Reader is welcome to
|
||||
take a look at
|
||||
<a href=http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt>
|
||||
ASN.1 specifications of X.509 applications</a> for more information.
|
||||
</p>
|
||||
|
||||
<a name="2.2.2"></a>
|
||||
<h4>
|
||||
2.2.2 Ignoring unknown types
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
When dealing with a loosely specified ASN.1 structure, the receiving
|
||||
end may not be aware of some types present in the substrate. It may be
|
||||
convenient then to turn decoder into a recovery mode. Whilst there, decoder
|
||||
will not bail out when hit an unknown tag but rather treat it as an Any
|
||||
type.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, tag
|
||||
>>> from pyasn1.codec.ber import encoder, decoder
|
||||
>>> taggedInt = univ.Integer(12345).subtype(
|
||||
... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)
|
||||
... )
|
||||
>>> substrate = encoder.encode(taggedInt)
|
||||
>>> decoder.decode(substrate)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.error.PyAsn1Error: TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not in asn1Spec
|
||||
>>>
|
||||
>>> decoder.decode.defaultErrorState = decoder.stDumpRawValue
|
||||
>>> decoder.decode(substrate)
|
||||
(Any(b'\x9f(\x0209'), '')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
It's also possible to configure a custom decoder, to handle unknown tags
|
||||
found in substrate. This can be done by means of <b>defaultRawDecoder</b>
|
||||
attribute holding a reference to type decoder object. Refer to the source
|
||||
for API details.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
436
third_party/python/pyasn1/doc/constraints.html
vendored
436
third_party/python/pyasn1/doc/constraints.html
vendored
@ -1,436 +0,0 @@
|
||||
<html>
|
||||
<title>
|
||||
PyASN1 subtype constraints
|
||||
</title>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<table width=60%>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
<h4>
|
||||
1.4 PyASN1 subtype constraints
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
Most ASN.1 types can correspond to an infinite set of values. To adapt to
|
||||
particular application's data model and needs, ASN.1 provides a mechanism
|
||||
for limiting the infinite set to values, that make sense in particular case.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Imposing value constraints on an ASN.1 type can also be seen as creating
|
||||
a subtype from its base type.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In pyasn1, constraints take shape of immutable objects capable
|
||||
of evaluating given value against constraint-specific requirements.
|
||||
Constraint object is a property of pyasn1 type. Like TagSet property,
|
||||
associated with every pyasn1 type, constraints can never be modified
|
||||
in place. The only way to modify pyasn1 type constraint is to associate
|
||||
new constraint object to a new pyasn1 type object.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A handful of different flavors of <i>constraints</i> are defined in ASN.1.
|
||||
We will discuss them one by one in the following chapters and also explain
|
||||
how to combine and apply them to types.
|
||||
</p>
|
||||
|
||||
<a name="1.4.1"></a>
|
||||
<h4>
|
||||
1.4.1 Single value constraint
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
This kind of constraint allows for limiting type to a finite, specified set
|
||||
of values.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
DialButton ::= OCTET STRING (
|
||||
"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
|
||||
)
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Its pyasn1 implementation would look like:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import constraint
|
||||
>>> c = constraint.SingleValueConstraint(
|
||||
'0','1','2','3','4','5','6','7','8','9'
|
||||
)
|
||||
>>> c
|
||||
SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||
>>> c('0')
|
||||
>>> c('A')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
As can be seen in the snippet above, if a value violates the constraint, an
|
||||
exception will be thrown. A constrainted pyasn1 type object holds a
|
||||
reference to a constraint object (or their combination, as will be explained
|
||||
later) and calls it for value verification.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, constraint
|
||||
>>> class DialButton(univ.OctetString):
|
||||
... subtypeSpec = constraint.SingleValueConstraint(
|
||||
... '0','1','2','3','4','5','6','7','8','9'
|
||||
... )
|
||||
>>> DialButton('0')
|
||||
DialButton(b'0')
|
||||
>>> DialButton('A')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Constrained pyasn1 value object can never hold a violating value.
|
||||
</p>
|
||||
|
||||
<a name="1.4.2"></a>
|
||||
<h4>
|
||||
1.4.2 Value range constraint
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
A pair of values, compliant to a type to be constrained, denote low and upper
|
||||
bounds of allowed range of values of a type.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
Teenagers ::= INTEGER (13..19)
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
And in pyasn1 terms:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, constraint
|
||||
>>> class Teenagers(univ.Integer):
|
||||
... subtypeSpec = constraint.ValueRangeConstraint(13, 19)
|
||||
>>> Teenagers(14)
|
||||
Teenagers(14)
|
||||
>>> Teenagers(20)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
ValueRangeConstraint(13, 19) failed at: 20
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Value range constraint usually applies numeric types.
|
||||
</p>
|
||||
|
||||
<a name="1.4.3"></a>
|
||||
<h4>
|
||||
1.4.3 Size constraint
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
It is sometimes convenient to set or limit the allowed size of a data item
|
||||
to be sent from one application to another to manage bandwidth and memory
|
||||
consumption issues. Size constraint specifies the lower and upper bounds
|
||||
of the size of a valid value.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
TwoBits ::= BIT STRING (SIZE (2))
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Express the same grammar in pyasn1:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, constraint
|
||||
>>> class TwoBits(univ.BitString):
|
||||
... subtypeSpec = constraint.ValueSizeConstraint(2, 2)
|
||||
>>> TwoBits((1,1))
|
||||
TwoBits("'11'B")
|
||||
>>> TwoBits((1,1,0))
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
ValueSizeConstraint(2, 2) failed at: (1, 1, 0)
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Size constraint can be applied to potentially massive values - bit or octet
|
||||
strings, SEQUENCE OF/SET OF values.
|
||||
</p>
|
||||
|
||||
<a name="1.4.4"></a>
|
||||
<h4>
|
||||
1.4.4 Alphabet constraint
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
The permitted alphabet constraint is similar to Single value constraint
|
||||
but constraint applies to individual characters of a value.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
MorseCode ::= PrintableString (FROM ("."|"-"|" "))
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
And in pyasn1:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import char, constraint
|
||||
>>> class MorseCode(char.PrintableString):
|
||||
... subtypeSpec = constraint.PermittedAlphabetConstraint(".", "-", " ")
|
||||
>>> MorseCode("...---...")
|
||||
MorseCode('...---...')
|
||||
>>> MorseCode("?")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
PermittedAlphabetConstraint(".", "-", " ") failed at: "?"
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Current implementation does not handle ranges of characters in constraint
|
||||
(FROM "A".."Z" syntax), one has to list the whole set in a range.
|
||||
</p>
|
||||
|
||||
<a name="1.4.5"></a>
|
||||
<h4>
|
||||
1.4.5 Constraint combinations
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
Up to this moment, we used a single constraint per ASN.1 type. The standard,
|
||||
however, allows for combining multiple individual constraints into
|
||||
intersections, unions and exclusions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In pyasn1 data model, all of these methods of constraint combinations are
|
||||
implemented as constraint-like objects holding individual constraint (or
|
||||
combination) objects. Like terminal constraint objects, combination objects
|
||||
are capable to perform value verification at its set of enclosed constraints
|
||||
according to the logic of particular combination.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Constraints intersection verification succeeds only if a value is
|
||||
compliant to each constraint in a set. To begin with, the following
|
||||
specification will constitute a valid telephone number:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
PhoneNumber ::= NumericString (FROM ("0".."9")) (SIZE 11)
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Constraint intersection object serves the logic above:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import char, constraint
|
||||
>>> class PhoneNumber(char.NumericString):
|
||||
... subtypeSpec = constraint.ConstraintsIntersection(
|
||||
... constraint.PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'),
|
||||
... constraint.ValueSizeConstraint(11, 11)
|
||||
... )
|
||||
>>> PhoneNumber('79039343212')
|
||||
PhoneNumber('79039343212')
|
||||
>>> PhoneNumber('?9039343212')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
ConstraintsIntersection(
|
||||
PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'),
|
||||
ValueSizeConstraint(11, 11)) failed at:
|
||||
PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9') failed at: "?039343212"
|
||||
>>> PhoneNumber('9343212')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
ConstraintsIntersection(
|
||||
PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'),
|
||||
ValueSizeConstraint(11, 11)) failed at:
|
||||
ValueSizeConstraint(10, 10) failed at: "9343212"
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Union of constraints works by making sure that a value is compliant
|
||||
to any of the constraint in a set. For instance:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
CapitalOrSmall ::= IA5String (FROM ('A','B','C') | FROM ('a','b','c'))
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
It's important to note, that a value must fully comply to any single
|
||||
constraint in a set. In the specification above, a value of all small or
|
||||
all capital letters is compliant, but a mix of small&capitals is not.
|
||||
Here's its pyasn1 analogue:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import char, constraint
|
||||
>>> class CapitalOrSmall(char.IA5String):
|
||||
... subtypeSpec = constraint.ConstraintsUnion(
|
||||
... constraint.PermittedAlphabetConstraint('A','B','C'),
|
||||
... constraint.PermittedAlphabetConstraint('a','b','c')
|
||||
... )
|
||||
>>> CapitalOrSmall('ABBA')
|
||||
CapitalOrSmall('ABBA')
|
||||
>>> CapitalOrSmall('abba')
|
||||
CapitalOrSmall('abba')
|
||||
>>> CapitalOrSmall('Abba')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
ConstraintsUnion(PermittedAlphabetConstraint('A', 'B', 'C'),
|
||||
PermittedAlphabetConstraint('a', 'b', 'c')) failed at: failed for "Abba"
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Finally, the exclusion constraint simply negates the logic of value
|
||||
verification at a constraint. In the following example, any integer value
|
||||
is allowed in a type but not zero.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
NoZero ::= INTEGER (ALL EXCEPT 0)
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
In pyasn1 the above definition would read:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, constraint
|
||||
>>> class NoZero(univ.Integer):
|
||||
... subtypeSpec = constraint.ConstraintsExclusion(
|
||||
... constraint.SingleValueConstraint(0)
|
||||
... )
|
||||
>>> NoZero(1)
|
||||
NoZero(1)
|
||||
>>> NoZero(0)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.type.error.ValueConstraintError:
|
||||
ConstraintsExclusion(SingleValueConstraint(0)) failed at: 0
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The depth of such a constraints tree, built with constraint combination objects
|
||||
at its nodes, has not explicit limit. Value verification is performed in a
|
||||
recursive manner till a definite solution is found.
|
||||
</p>
|
||||
|
||||
<a name="1.5"></a>
|
||||
<h4>
|
||||
1.5 Types relationships
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
In the course of data processing in an application, it is sometimes
|
||||
convenient to figure out the type relationships between pyasn1 type or
|
||||
value objects. Formally, two things influence pyasn1 types relationship:
|
||||
<i>tag set</i> and <i>subtype constraints</i>. One pyasn1 type is considered
|
||||
to be a derivative of another if their TagSet and Constraint objects are
|
||||
a derivation of one another.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following example illustrates the concept (we use the same tagset but
|
||||
different constraints for simplicity):
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, constraint
|
||||
>>> i1 = univ.Integer(subtypeSpec=constraint.ValueRangeConstraint(3,8))
|
||||
>>> i2 = univ.Integer(subtypeSpec=constraint.ConstraintsIntersection(
|
||||
... constraint.ValueRangeConstraint(3,8),
|
||||
... constraint.ValueRangeConstraint(4,7)
|
||||
... ) )
|
||||
>>> i1.isSameTypeWith(i2)
|
||||
False
|
||||
>>> i1.isSuperTypeOf(i2)
|
||||
True
|
||||
>>> i1.isSuperTypeOf(i1)
|
||||
True
|
||||
>>> i2.isSuperTypeOf(i1)
|
||||
False
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
As can be seen in the above code snippet, there are two methods of any pyasn1
|
||||
type/value object that test types for their relationship:
|
||||
<b>isSameTypeWith</b>() and <b>isSuperTypeOf</b>(). The former is
|
||||
self-descriptive while the latter yields true if the argument appears
|
||||
to be a pyasn1 object which has tagset and constraints derived from those
|
||||
of the object being called.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
377
third_party/python/pyasn1/doc/constructed.html
vendored
377
third_party/python/pyasn1/doc/constructed.html
vendored
@ -1,377 +0,0 @@
|
||||
<html>
|
||||
<title>
|
||||
PyASN1 Constructed types
|
||||
</title>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<table width=60%>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
<h4>
|
||||
1.3 PyASN1 Constructed types
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
Besides scalar types, ASN.1 specifies so-called constructed ones - these
|
||||
are capable of holding one or more values of other types, both scalar
|
||||
and constructed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In pyasn1 implementation, constructed ASN.1 types behave like
|
||||
Python sequences, and also support additional component addressing methods,
|
||||
specific to particular constructed type.
|
||||
</p>
|
||||
|
||||
<a name="1.3.1"></a>
|
||||
<h4>
|
||||
1.3.1 Sequence and Set types
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
The Sequence and Set types have many similar properties:
|
||||
</p>
|
||||
<ul>
|
||||
<li>they can hold any number of inner components of different types
|
||||
<li>every component has a human-friendly identifier
|
||||
<li>any component can have a default value
|
||||
<li>some components can be absent.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
However, Sequence type guarantees the ordering of Sequence value components
|
||||
to match their declaration order. By contrast, components of the
|
||||
Set type can be ordered to best suite application's needs.
|
||||
<p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
Record ::= SEQUENCE {
|
||||
id INTEGER,
|
||||
room [0] INTEGER OPTIONAL,
|
||||
house [1] INTEGER DEFAULT 0
|
||||
}
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Up to this moment, the only method we used for creating new pyasn1 types
|
||||
is Python sub-classing. With this method, a new, named Python class is created
|
||||
what mimics type derivation in ASN.1 grammar. However, ASN.1 also allows for
|
||||
defining anonymous subtypes (room and house components in the example above).
|
||||
To support anonymous subtyping in pyasn1, a cloning operation on an existing
|
||||
pyasn1 type object can be invoked what creates a new instance of original
|
||||
object with possibly modified properties.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, namedtype, tag
|
||||
>>> class Record(univ.Sequence):
|
||||
... componentType = namedtype.NamedTypes(
|
||||
... namedtype.NamedType('id', univ.Integer()),
|
||||
... namedtype.OptionalNamedType(
|
||||
... 'room',
|
||||
... univ.Integer().subtype(
|
||||
... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)
|
||||
... )
|
||||
... ),
|
||||
... namedtype.DefaultedNamedType(
|
||||
... 'house',
|
||||
... univ.Integer(0).subtype(
|
||||
... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)
|
||||
... )
|
||||
... )
|
||||
... )
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
All pyasn1 constructed type classes have a class attribute <b>componentType</b>
|
||||
that represent default type specification. Its value is a NamedTypes object.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The NamedTypes class instance holds a sequence of NameType, OptionalNamedType
|
||||
or DefaultedNamedType objects which, in turn, refer to pyasn1 type objects that
|
||||
represent inner SEQUENCE components specification.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, invocation of a subtype() method of pyasn1 type objects in the code
|
||||
above returns an implicitly tagged copy of original object.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Once a SEQUENCE or SET type is decleared with pyasn1, it can be instantiated
|
||||
and initialized (continuing the above code):
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> record = Record()
|
||||
>>> record.setComponentByName('id', 123)
|
||||
>>> print(record.prettyPrint())
|
||||
Record:
|
||||
id=123
|
||||
>>>
|
||||
>>> record.setComponentByPosition(1, 321)
|
||||
>>> print(record.prettyPrint())
|
||||
Record:
|
||||
id=123
|
||||
room=321
|
||||
>>>
|
||||
>>> record.setDefaultComponents()
|
||||
>>> print(record.prettyPrint())
|
||||
Record:
|
||||
id=123
|
||||
room=321
|
||||
house=0
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Inner components of pyasn1 Sequence/Set objects could be accessed using the
|
||||
following methods:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> record.getComponentByName('id')
|
||||
Integer(123)
|
||||
>>> record.getComponentByPosition(1)
|
||||
Integer(321)
|
||||
>>> record[2]
|
||||
Integer(0)
|
||||
>>> for idx in range(len(record)):
|
||||
... print(record.getNameByPosition(idx), record.getComponentByPosition(idx))
|
||||
id 123
|
||||
room 321
|
||||
house 0
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The Set type share all the properties of Sequence type, and additionally
|
||||
support by-tag component addressing (as all Set components have distinct
|
||||
types).
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, namedtype, tag
|
||||
>>> class Gamer(univ.Set):
|
||||
... componentType = namedtype.NamedTypes(
|
||||
... namedtype.NamedType('score', univ.Integer()),
|
||||
... namedtype.NamedType('player', univ.OctetString()),
|
||||
... namedtype.NamedType('id', univ.ObjectIdentifier())
|
||||
... )
|
||||
>>> gamer = Gamer()
|
||||
>>> gamer.setComponentByType(univ.Integer().getTagSet(), 121343)
|
||||
>>> gamer.setComponentByType(univ.OctetString().getTagSet(), 'Pascal')
|
||||
>>> gamer.setComponentByType(univ.ObjectIdentifier().getTagSet(), (1,3,7,2))
|
||||
>>> print(gamer.prettyPrint())
|
||||
Gamer:
|
||||
score=121343
|
||||
player=b'Pascal'
|
||||
id=1.3.7.2
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<a name="1.3.2"></a>
|
||||
<h4>
|
||||
1.3.2 SequenceOf and SetOf types
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
Both, SequenceOf and SetOf types resemble an unlimited size list of components.
|
||||
All the components must be of the same type.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
Progression ::= SEQUENCE OF INTEGER
|
||||
|
||||
arithmeticProgression Progression ::= { 1, 3, 5, 7 }
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
SequenceOf and SetOf types are expressed by the very similar pyasn1 type
|
||||
objects. Their components can only be addressed by position and they
|
||||
both have a property of automatic resize.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To specify inner component type, the <b>componentType</b> class attribute
|
||||
should refer to another pyasn1 type object.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> class Progression(univ.SequenceOf):
|
||||
... componentType = univ.Integer()
|
||||
>>> arithmeticProgression = Progression()
|
||||
>>> arithmeticProgression.setComponentByPosition(1, 111)
|
||||
>>> print(arithmeticProgression.prettyPrint())
|
||||
Progression:
|
||||
-empty- 111
|
||||
>>> arithmeticProgression.setComponentByPosition(0, 100)
|
||||
>>> print(arithmeticProgression.prettyPrint())
|
||||
Progression:
|
||||
100 111
|
||||
>>>
|
||||
>>> for idx in range(len(arithmeticProgression)):
|
||||
... arithmeticProgression.getComponentByPosition(idx)
|
||||
Integer(100)
|
||||
Integer(111)
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Any scalar or constructed pyasn1 type object can serve as an inner component.
|
||||
Missing components are prohibited in SequenceOf/SetOf value objects.
|
||||
</p>
|
||||
|
||||
<a name="1.3.3"></a>
|
||||
<h4>
|
||||
1.3.3 Choice type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
Values of ASN.1 CHOICE type can contain only a single value of a type from a
|
||||
list of possible alternatives. Alternatives must be ASN.1 types with
|
||||
distinct tags for the whole structure to remain unambiguous. Unlike most
|
||||
other types, CHOICE is an untagged one, e.g. it has no base tag of its own.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
CodeOrMessage ::= CHOICE {
|
||||
code INTEGER,
|
||||
message OCTET STRING
|
||||
}
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
In pyasn1 implementation, Choice object behaves like Set but accepts only
|
||||
a single inner component at a time. It also offers a few additional methods
|
||||
specific to its behaviour.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, namedtype
|
||||
>>> class CodeOrMessage(univ.Choice):
|
||||
... componentType = namedtype.NamedTypes(
|
||||
... namedtype.NamedType('code', univ.Integer()),
|
||||
... namedtype.NamedType('message', univ.OctetString())
|
||||
... )
|
||||
>>>
|
||||
>>> codeOrMessage = CodeOrMessage()
|
||||
>>> print(codeOrMessage.prettyPrint())
|
||||
CodeOrMessage:
|
||||
>>> codeOrMessage.setComponentByName('code', 123)
|
||||
>>> print(codeOrMessage.prettyPrint())
|
||||
CodeOrMessage:
|
||||
code=123
|
||||
>>> codeOrMessage.setComponentByName('message', 'my string value')
|
||||
>>> print(codeOrMessage.prettyPrint())
|
||||
CodeOrMessage:
|
||||
message=b'my string value'
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Since there could be only a single inner component value in the pyasn1 Choice
|
||||
value object, either of the following methods could be used for fetching it
|
||||
(continuing previous code):
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> codeOrMessage.getName()
|
||||
'message'
|
||||
>>> codeOrMessage.getComponent()
|
||||
OctetString(b'my string value')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<a name="1.3.4"></a>
|
||||
<h4>
|
||||
1.3.4 Any type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
The ASN.1 ANY type is a kind of wildcard or placeholder that matches
|
||||
any other type without knowing it in advance. Like CHOICE type, ANY
|
||||
has no base tag.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
Error ::= SEQUENCE {
|
||||
code INTEGER,
|
||||
parameter ANY DEFINED BY code
|
||||
}
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The ANY type is frequently used in specifications, where exact type is not
|
||||
yet agreed upon between communicating parties or the number of possible
|
||||
alternatives of a type is infinite.
|
||||
Sometimes an auxiliary selector is kept around to help parties indicate
|
||||
the kind of ANY payload in effect ("code" in the example above).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Values of the ANY type contain serialized ASN.1 value(s) in form of
|
||||
an octet string. Therefore pyasn1 Any value object share the properties of
|
||||
pyasn1 OctetString object.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> someValue = univ.Any(b'\x02\x01\x01')
|
||||
>>> someValue
|
||||
Any(b'\x02\x01\x01')
|
||||
>>> str(someValue)
|
||||
'\x02\x01\x01'
|
||||
>>> bytes(someValue)
|
||||
b'\x02\x01\x01'
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Receiving application is supposed to explicitly deserialize the content of Any
|
||||
value object, possibly using auxiliary selector for figuring out its ASN.1
|
||||
type to pick appropriate decoder.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There will be some more talk and code snippets covering Any type in the codecs
|
||||
chapters that follow.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
156
third_party/python/pyasn1/doc/intro.html
vendored
156
third_party/python/pyasn1/doc/intro.html
vendored
@ -1,156 +0,0 @@
|
||||
<html>
|
||||
<title>
|
||||
PyASN1 reference manual
|
||||
</title>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<table width=60%>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
<h3>
|
||||
PyASN1 reference manual
|
||||
</h3>
|
||||
|
||||
<p align=right>
|
||||
<i>written by <a href=mailto:ilya@glas.net>Ilya Etingof</a>, 2011-2012</i>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Free and open-source pyasn1 library makes it easier for programmers and
|
||||
network engineers to develop, debug and experiment with ASN.1-based protocols
|
||||
using Python programming language as a tool.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Abstract Syntax Notation One
|
||||
(<a href=http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_1x>ASN.1</a>)
|
||||
is a set of
|
||||
<a href=http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-X.693-0207w.zip>
|
||||
ITU standards</a> concered with provisioning instrumentation for developing
|
||||
data exchange protocols in a robust, clear and interoperabable way for
|
||||
various IT systems and applications. Most of the efforts are targeting the
|
||||
following areas:
|
||||
<ul>
|
||||
<li>Data structures: the standard introduces a collection of basic data types
|
||||
(similar to integers, bits, strings, arrays and records in a programming
|
||||
language) that can be used for defining complex, possibly nested data
|
||||
structures representing domain-specific data units.
|
||||
<li>Serialization protocols: domain-specific data units expressed in ASN.1
|
||||
types could be converted into a series of octets for storage or transmission
|
||||
over the wire and then recovered back into their structured form on the
|
||||
receiving end. This process is immune to various hardware and software
|
||||
related dependencies.
|
||||
<li>Data description language: could be used to describe particular set of
|
||||
domain-specific data structures and their relationships. Such a description
|
||||
could be passed to an ASN.1 compiler for automated generation of program
|
||||
code that represents ASN.1 data structures in language-native environment
|
||||
and handles data serialization issues.
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This tutorial and algorithms, implemented by pyasn1 library, are
|
||||
largely based on the information read in the book
|
||||
<a href="http://www.oss.com/asn1/dubuisson.html">
|
||||
ASN.1 - Communication between heterogeneous systems</a>
|
||||
by Olivier Dubuisson. Another relevant resource is
|
||||
<a href=ftp://ftp.rsasecurity.com/pub/pkcs/ascii/layman.asc>
|
||||
A Layman's Guide to a Subset of ASN.1, BER, and DER</a> by Burton S. Kaliski.
|
||||
It's advised to refer to these books for more in-depth knowledge on the
|
||||
subject of ASN.1.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As of this writing, pyasn1 library implements most of standard ASN.1 data
|
||||
structures in a rather detailed and feature-rich manner. Another highly
|
||||
important capability of the library is its data serialization facilities.
|
||||
The last component of the standard - ASN.1 compiler is planned for
|
||||
implementation in the future.
|
||||
</p>
|
||||
|
||||
</p>
|
||||
The pyasn1 library was designed to follow the pre-1995 ASN.1 specification
|
||||
(also known as X.208). Later, post 1995, revision (X.680) introduced
|
||||
significant changes most of which have not yet been supported by pyasn1.
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
Table of contents
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li><a href="scalar.html">1. Data model for ASN.1 types</a>
|
||||
<li><a href="scalar.html#1.1">1.1 Scalar types</a>
|
||||
<li><a href="scalar.html#1.1.1">1.1.1 Boolean type</a>
|
||||
<li><a href="scalar.html#1.1.2">1.1.2 Null type</a>
|
||||
<li><a href="scalar.html#1.1.3">1.1.3 Integer type</a>
|
||||
<li><a href="scalar.html#1.1.4">1.1.4 Enumerated type</a>
|
||||
<li><a href="scalar.html#1.1.5">1.1.5 Real type</a>
|
||||
<li><a href="scalar.html#1.1.6">1.1.6 Bit string type</a>
|
||||
<li><a href="scalar.html#1.1.7">1.1.7 OctetString type</a>
|
||||
<li><a href="scalar.html#1.1.8">1.1.8 ObjectIdentifier type</a>
|
||||
<li><a href="scalar.html#1.1.9">1.1.9 Character string types</a>
|
||||
<li><a href="scalar.html#1.1.10">1.1.10 Useful types</a>
|
||||
<li><a href="tagging.html">1.2 Tagging</a>
|
||||
<li><a href="constructed.html">1.3 Constructed types</a>
|
||||
<li><a href="constructed.html#1.3.1">1.3.1 Sequence and Set types</a>
|
||||
<li><a href="constructed.html#1.3.2">1.3.2 SequenceOf and SetOf types</a>
|
||||
<li><a href="constructed.html#1.3.3">1.3.3 Choice type</a>
|
||||
<li><a href="constructed.html#1.3.4">1.3.4 Any type</a>
|
||||
<li><a href="constraints.html">1.4 Subtype constraints</a>
|
||||
<li><a href="constraints.html#1.4.1">1.4.1 Single value constraint</a>
|
||||
<li><a href="constraints.html#1.4.2">1.4.2 Value range constraint</a>
|
||||
<li><a href="constraints.html#1.4.3">1.4.3 Size constraint</a>
|
||||
<li><a href="constraints.html#1.4.4">1.4.4 Alphabet constraint</a>
|
||||
<li><a href="constraints.html#1.4.5">1.4.5 Constraint combinations</a>
|
||||
<li><a href="constraints.html#1.5">1.5 Types relationships</a>
|
||||
<li><a href="codecs.html">2. Codecs</a>
|
||||
<li><a href="codecs.html#2.1">2.1 Encoders</a>
|
||||
<li><a href="codecs.html#2.2">2.2 Decoders</a>
|
||||
<li><a href="codecs.html#2.2.1">2.2.1 Decoding untagged types</a>
|
||||
<li><a href="codecs.html#2.2.2">2.2.2 Ignoring unknown types</a>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Although pyasn1 software is almost a decade old and used in many production
|
||||
environments, it still may have bugs and non-implemented pieces. Anyone
|
||||
who happens to run into such defect is welcome to complain to
|
||||
<a href=mailto:pyasn1-users@lists.sourceforge.net>pyasn1 mailing list</a>
|
||||
or better yet fix the issue and send
|
||||
<a href=mailto:ilya@glas.net>me</a> the patch.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Typically, pyasn1 is used for building arbitrary protocol support into
|
||||
various applications. This involves manual translation of ASN.1 data
|
||||
structures into their pyasn1 implementations. To save time and effort,
|
||||
data structures for some of the popular protocols are pre-programmed
|
||||
and kept for further re-use in form of the
|
||||
<a href=http://sourceforge.net/projects/pyasn1/files/pyasn1-modules/>
|
||||
pyasn1-modules package</a>. For instance, many structures for PKI (X.509,
|
||||
PKCS#*, CRMF, OCSP), LDAP and SNMP are present.
|
||||
Applications authors are advised to import and use relevant modules
|
||||
from that package whenever needed protocol structures are already
|
||||
there. New protocol modules contributions are welcome.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
And finally, the latest pyasn1 package revision is available for free
|
||||
download from
|
||||
<a href=http://sourceforge.net/projects/pyasn1/>project home</a> and
|
||||
also from the
|
||||
<a href=http://pypi.python.org/pypi>Python package repository</a>.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
2405
third_party/python/pyasn1/doc/pyasn1-tutorial.html
vendored
2405
third_party/python/pyasn1/doc/pyasn1-tutorial.html
vendored
File diff suppressed because it is too large
Load Diff
794
third_party/python/pyasn1/doc/scalar.html
vendored
794
third_party/python/pyasn1/doc/scalar.html
vendored
@ -1,794 +0,0 @@
|
||||
<html>
|
||||
<title>
|
||||
PyASN1 data model and scalar types
|
||||
</title>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<table width=60%>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
<h3>
|
||||
1. Data model for ASN.1 types
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
All ASN.1 types could be categorized into two groups: scalar (also called
|
||||
simple or primitive) and constructed. The first group is populated by
|
||||
well-known types like Integer or String. Members of constructed group
|
||||
hold other types (simple or constructed) as their inner components, thus
|
||||
they are semantically close to a programming language records or lists.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In pyasn1, all ASN.1 types and values are implemented as Python objects.
|
||||
The same pyasn1 object can represent either ASN.1 type and/or value
|
||||
depending of the presense of value initializer on object instantiation.
|
||||
We will further refer to these as <i>pyasn1 type object</i> versus <i>pyasn1
|
||||
value object</i>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Primitive ASN.1 types are implemented as immutable scalar objects. There values
|
||||
could be used just like corresponding native Python values (integers,
|
||||
strings/bytes etc) and freely mixed with them in expressions.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> asn1IntegerValue = univ.Integer(12)
|
||||
>>> asn1IntegerValue - 2
|
||||
10
|
||||
>>> univ.OctetString('abc') == 'abc'
|
||||
True # Python 2
|
||||
>>> univ.OctetString(b'abc') == b'abc'
|
||||
True # Python 3
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
It would be an error to perform an operation on a pyasn1 type object
|
||||
as it holds no value to deal with:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> asn1IntegerType = univ.Integer()
|
||||
>>> asn1IntegerType - 2
|
||||
...
|
||||
pyasn1.error.PyAsn1Error: No value for __coerce__()
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<a name="1.1"></a>
|
||||
<h4>
|
||||
1.1 Scalar types
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
In the sub-sections that follow we will explain pyasn1 mapping to those
|
||||
primitive ASN.1 types. Both, ASN.1 notation and corresponding pyasn1
|
||||
syntax will be given in each case.
|
||||
</p>
|
||||
|
||||
<a name="1.1.1"></a>
|
||||
<h4>
|
||||
1.1.1 Boolean type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
This is the simplest type those values could be either True or False.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
;; type specification
|
||||
FunFactorPresent ::= BOOLEAN
|
||||
|
||||
;; values declaration and assignment
|
||||
pythonFunFactor FunFactorPresent ::= TRUE
|
||||
cobolFunFactor FunFactorPresent :: FALSE
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
And here's pyasn1 version of it:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> class FunFactorPresent(univ.Boolean): pass
|
||||
...
|
||||
>>> pythonFunFactor = FunFactorPresent(True)
|
||||
>>> cobolFunFactor = FunFactorPresent(False)
|
||||
>>> pythonFunFactor
|
||||
FunFactorPresent('True(1)')
|
||||
>>> cobolFunFactor
|
||||
FunFactorPresent('False(0)')
|
||||
>>> pythonFunFactor == cobolFunFactor
|
||||
False
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<a name="1.1.2"></a>
|
||||
<h4>
|
||||
1.1.2 Null type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
The NULL type is sometimes used to express the absense of any information.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
;; type specification
|
||||
Vote ::= CHOICE {
|
||||
agreed BOOLEAN,
|
||||
skip NULL
|
||||
}
|
||||
</td></tr></table>
|
||||
|
||||
;; value declaration and assignment
|
||||
myVote Vote ::= skip:NULL
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
We will explain the CHOICE type later in this paper, meanwhile the NULL
|
||||
type:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> skip = univ.Null()
|
||||
>>> skip
|
||||
Null('')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<a name="1.1.3"></a>
|
||||
<h4>
|
||||
1.1.3 Integer type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
ASN.1 defines the values of Integer type as negative or positive of whatever
|
||||
length. This definition plays nicely with Python as the latter places no
|
||||
limit on Integers. However, some ASN.1 implementations may impose certain
|
||||
limits of integer value ranges. Keep that in mind when designing new
|
||||
data structures.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
;; values specification
|
||||
age-of-universe INTEGER ::= 13750000000
|
||||
mean-martian-surface-temperature INTEGER ::= -63
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
A rather strigntforward mapping into pyasn1:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> ageOfUniverse = univ.Integer(13750000000)
|
||||
>>> ageOfUniverse
|
||||
Integer(13750000000)
|
||||
>>>
|
||||
>>> meanMartianSurfaceTemperature = univ.Integer(-63)
|
||||
>>> meanMartianSurfaceTemperature
|
||||
Integer(-63)
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
ASN.1 allows to assign human-friendly names to particular values of
|
||||
an INTEGER type.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
Temperature ::= INTEGER {
|
||||
freezing(0),
|
||||
boiling(100)
|
||||
}
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The Temperature type expressed in pyasn1:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, namedval
|
||||
>>> class Temperature(univ.Integer):
|
||||
... namedValues = namedval.NamedValues(('freezing', 0), ('boiling', 100))
|
||||
...
|
||||
>>> t = Temperature(0)
|
||||
>>> t
|
||||
Temperature('freezing(0)')
|
||||
>>> t + 1
|
||||
Temperature(1)
|
||||
>>> t + 100
|
||||
Temperature('boiling(100)')
|
||||
>>> t = Temperature('boiling')
|
||||
>>> t
|
||||
Temperature('boiling(100)')
|
||||
>>> Temperature('boiling') / 2
|
||||
Temperature(50)
|
||||
>>> -1 < Temperature('freezing')
|
||||
True
|
||||
>>> 47 > Temperature('boiling')
|
||||
False
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
These values labels have no effect on Integer type operations, any value
|
||||
still could be assigned to a type (information on value constraints will
|
||||
follow further in this paper).
|
||||
</p>
|
||||
|
||||
<a name="1.1.4"></a>
|
||||
<h4>
|
||||
1.1.4 Enumerated type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
ASN.1 Enumerated type differs from an Integer type in a number of ways.
|
||||
Most important is that its instance can only hold a value that belongs
|
||||
to a set of values specified on type declaration.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
error-status ::= ENUMERATED {
|
||||
no-error(0),
|
||||
authentication-error(10),
|
||||
authorization-error(20),
|
||||
general-failure(51)
|
||||
}
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
When constructing Enumerated type we will use two pyasn1 features: values
|
||||
labels (as mentioned above) and value constraint (will be described in
|
||||
more details later on).
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, namedval, constraint
|
||||
>>> class ErrorStatus(univ.Enumerated):
|
||||
... namedValues = namedval.NamedValues(
|
||||
... ('no-error', 0),
|
||||
... ('authentication-error', 10),
|
||||
... ('authorization-error', 20),
|
||||
... ('general-failure', 51)
|
||||
... )
|
||||
... subtypeSpec = univ.Enumerated.subtypeSpec + \
|
||||
... constraint.SingleValueConstraint(0, 10, 20, 51)
|
||||
...
|
||||
>>> errorStatus = univ.ErrorStatus('no-error')
|
||||
>>> errorStatus
|
||||
ErrorStatus('no-error(0)')
|
||||
>>> errorStatus == univ.ErrorStatus('general-failure')
|
||||
False
|
||||
>>> univ.ErrorStatus('non-existing-state')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
pyasn1.error.PyAsn1Error: Can't coerce non-existing-state into integer
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Particular integer values associated with Enumerated value states
|
||||
have no meaning. They should not be used as such or in any kind of
|
||||
math operation. Those integer values are only used by codecs to
|
||||
transfer state from one entity to another.
|
||||
</p>
|
||||
|
||||
<a name="1.1.5"></a>
|
||||
<h4>
|
||||
1.1.5 Real type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
Values of the Real type are a three-component tuple of mantissa, base and
|
||||
exponent. All three are integers.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
pi ::= REAL { mantissa 314159, base 10, exponent -5 }
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Corresponding pyasn1 objects can be initialized with either a three-component
|
||||
tuple or a Python float. Infinite values could be expressed in a way,
|
||||
compatible with Python float type.
|
||||
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> pi = univ.Real((314159, 10, -5))
|
||||
>>> pi
|
||||
Real((314159, 10,-5))
|
||||
>>> float(pi)
|
||||
3.14159
|
||||
>>> pi == univ.Real(3.14159)
|
||||
True
|
||||
>>> univ.Real('inf')
|
||||
Real('inf')
|
||||
>>> univ.Real('-inf') == float('-inf')
|
||||
True
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
If a Real object is initialized from a Python float or yielded by a math
|
||||
operation, the base is set to decimal 10 (what affects encoding).
|
||||
</p>
|
||||
|
||||
<a name="1.1.6"></a>
|
||||
<h4>
|
||||
1.1.6 Bit string type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
ASN.1 BIT STRING type holds opaque binary data of an arbitrarily length.
|
||||
A BIT STRING value could be initialized by either a binary (base 2) or
|
||||
hex (base 16) value.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
public-key BIT STRING ::= '1010111011110001010110101101101
|
||||
1011000101010000010110101100010
|
||||
0110101010000111101010111111110'B
|
||||
|
||||
signature BIT STRING ::= 'AF01330CD932093392100B39FF00DE0'H
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The pyasn1 BitString objects can initialize from native ASN.1 notation
|
||||
(base 2 or base 16 strings) or from a Python tuple of binary components.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> publicKey = univ.BitString(
|
||||
... "'1010111011110001010110101101101"
|
||||
... "1011000101010000010110101100010"
|
||||
... "0110101010000111101010111111110'B"
|
||||
)
|
||||
>>> publicKey
|
||||
BitString("'10101110111100010101101011011011011000101010000010110101100010\
|
||||
0110101010000111101010111111110'B")
|
||||
>>> signature = univ.BitString(
|
||||
... "'AF01330CD932093392100B39FF00DE0'H"
|
||||
... )
|
||||
>>> signature
|
||||
BitString("'101011110000000100110011000011001101100100110010000010010011001\
|
||||
1100100100001000000001011001110011111111100000000110111100000'B")
|
||||
>>> fingerprint = univ.BitString(
|
||||
... (1, 0, 1, 1 ,0, 1, 1, 1, 0, 1, 0, 1)
|
||||
... )
|
||||
>>> fingerprint
|
||||
BitString("'101101110101'B")
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Another BIT STRING initialization method supported by ASN.1 notation
|
||||
is to specify only 1-th bits along with their human-friendly label
|
||||
and bit offset relative to the beginning of the bit string. With this
|
||||
method, all not explicitly mentioned bits are doomed to be zeros.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
bit-mask BIT STRING ::= {
|
||||
read-flag(0),
|
||||
write-flag(2),
|
||||
run-flag(4)
|
||||
}
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
To express this in pyasn1, we will employ the named values feature (as with
|
||||
Enumeration type).
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, namedval
|
||||
>>> class BitMask(univ.BitString):
|
||||
... namedValues = namedval.NamedValues(
|
||||
... ('read-flag', 0),
|
||||
... ('write-flag', 2),
|
||||
... ('run-flag', 4)
|
||||
... )
|
||||
>>> bitMask = BitMask('read-flag,run-flag')
|
||||
>>> bitMask
|
||||
BitMask("'10001'B")
|
||||
>>> tuple(bitMask)
|
||||
(1, 0, 0, 0, 1)
|
||||
>>> bitMask[4]
|
||||
1
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The BitString objects mimic the properties of Python tuple type in part
|
||||
of immutable sequence object protocol support.
|
||||
</p>
|
||||
|
||||
<a name="1.1.7"></a>
|
||||
<h4>
|
||||
1.1.7 OctetString type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
The OCTET STRING type is a confusing subject. According to ASN.1
|
||||
specification, this type is similar to BIT STRING, the major difference
|
||||
is that the former operates in 8-bit chunks of data. What is important
|
||||
to note, is that OCTET STRING was NOT designed to handle text strings - the
|
||||
standard provides many other types specialized for text content. For that
|
||||
reason, ASN.1 forbids to initialize OCTET STRING values with "quoted text
|
||||
strings", only binary or hex initializers, similar to BIT STRING ones,
|
||||
are allowed.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
thumbnail OCTET STRING ::= '1000010111101110101111000000111011'B
|
||||
thumbnail OCTET STRING ::= 'FA9823C43E43510DE3422'H
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
However, ASN.1 users (e.g. protocols designers) seem to ignore the original
|
||||
purpose of the OCTET STRING type - they used it for handling all kinds of
|
||||
data, including text strings.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
welcome-message OCTET STRING ::= "Welcome to ASN.1 wilderness!"
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
In pyasn1, we have taken a liberal approach and allowed both BIT STRING
|
||||
style and quoted text initializers for the OctetString objects. To avoid
|
||||
possible collisions, quoted text is the default initialization syntax.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> thumbnail = univ.OctetString(
|
||||
... binValue='1000010111101110101111000000111011'
|
||||
... )
|
||||
>>> thumbnail
|
||||
OctetString(hexValue='85eebcec0')
|
||||
>>> thumbnail = univ.OctetString(
|
||||
... hexValue='FA9823C43E43510DE3422'
|
||||
... )
|
||||
>>> thumbnail
|
||||
OctetString(hexValue='fa9823c43e4351de34220')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Most frequent usage of the OctetString class is to instantiate it with
|
||||
a text string.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> welcomeMessage = univ.OctetString('Welcome to ASN.1 wilderness!')
|
||||
>>> welcomeMessage
|
||||
OctetString(b'Welcome to ASN.1 wilderness!')
|
||||
>>> print('%s' % welcomeMessage)
|
||||
Welcome to ASN.1 wilderness!
|
||||
>>> welcomeMessage[11:16]
|
||||
OctetString(b'ASN.1')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
OctetString objects support the immutable sequence object protocol.
|
||||
In other words, they behave like Python 3 bytes (or Python 2 strings).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When running pyasn1 on Python 3, it's better to use the bytes objects for
|
||||
OctetString instantiation, as it's more reliable and efficient.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Additionally, OctetString's can also be instantiated with a sequence of
|
||||
8-bit integers (ASCII codes).
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> univ.OctetString((77, 101, 101, 103, 111))
|
||||
OctetString(b'Meego')
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
It is sometimes convenient to express OctetString instances as 8-bit
|
||||
characters (Python 3 bytes or Python 2 strings) or 8-bit integers.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> octetString = univ.OctetString('ABCDEF')
|
||||
>>> octetString.asNumbers()
|
||||
(65, 66, 67, 68, 69, 70)
|
||||
>>> octetString.asOctets()
|
||||
b'ABCDEF'
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<a name="1.1.8"></a>
|
||||
<h4>
|
||||
1.1.8 ObjectIdentifier type
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
Values of the OBJECT IDENTIFIER type are sequences of integers that could
|
||||
be used to identify virtually anything in the world. Various ASN.1-based
|
||||
protocols employ OBJECT IDENTIFIERs for their own identification needs.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
internet-id OBJECT IDENTIFIER ::= {
|
||||
iso(1) identified-organization(3) dod(6) internet(1)
|
||||
}
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
One of the natural ways to map OBJECT IDENTIFIER type into a Python
|
||||
one is to use Python tuples of integers. So this approach is taken by
|
||||
pyasn1.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> internetId = univ.ObjectIdentifier((1, 3, 6, 1))
|
||||
>>> internetId
|
||||
ObjectIdentifier('1.3.6.1')
|
||||
>>> internetId[2]
|
||||
6
|
||||
>>> internetId[1:3]
|
||||
ObjectIdentifier('3.6')
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
A more human-friendly "dotted" notation is also supported.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ
|
||||
>>> univ.ObjectIdentifier('1.3.6.1')
|
||||
ObjectIdentifier('1.3.6.1')
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Symbolic names of the arcs of object identifier, sometimes present in
|
||||
ASN.1 specifications, are not preserved and used in pyasn1 objects.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The ObjectIdentifier objects mimic the properties of Python tuple type in
|
||||
part of immutable sequence object protocol support.
|
||||
</p>
|
||||
|
||||
<a name="1.1.9"></a>
|
||||
<h4>
|
||||
1.1.9 Character string types
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
ASN.1 standard introduces a diverse set of text-specific types. All of them
|
||||
were designed to handle various types of characters. Some of these types seem
|
||||
be obsolete nowdays, as their target technologies are gone. Another issue
|
||||
to be aware of is that raw OCTET STRING type is sometimes used in practice
|
||||
by ASN.1 users instead of specialized character string types, despite
|
||||
explicit prohibition imposed by ASN.1 specification.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The two types are specific to ASN.1 are NumericString and PrintableString.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
welcome-message ::= PrintableString {
|
||||
"Welcome to ASN.1 text types"
|
||||
}
|
||||
|
||||
dial-pad-numbers ::= NumericString {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||
}
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Their pyasn1 implementations are:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import char
|
||||
>>> '%s' % char.PrintableString("Welcome to ASN.1 text types")
|
||||
'Welcome to ASN.1 text types'
|
||||
>>> dialPadNumbers = char.NumericString(
|
||||
"0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
|
||||
)
|
||||
>>> dialPadNumbers
|
||||
NumericString(b'0123456789')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The following types came to ASN.1 from ISO standards on character sets.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import char
|
||||
>>> char.VisibleString("abc")
|
||||
VisibleString(b'abc')
|
||||
>>> char.IA5String('abc')
|
||||
IA5String(b'abc')
|
||||
>>> char.TeletexString('abc')
|
||||
TeletexString(b'abc')
|
||||
>>> char.VideotexString('abc')
|
||||
VideotexString(b'abc')
|
||||
>>> char.GraphicString('abc')
|
||||
GraphicString(b'abc')
|
||||
>>> char.GeneralString('abc')
|
||||
GeneralString(b'abc')
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
The last three types are relatively recent addition to the family of
|
||||
character string types: UniversalString, BMPString, UTF8String.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import char
|
||||
>>> char.UniversalString("abc")
|
||||
UniversalString(b'abc')
|
||||
>>> char.BMPString('abc')
|
||||
BMPString(b'abc')
|
||||
>>> char.UTF8String('abc')
|
||||
UTF8String(b'abc')
|
||||
>>> utf8String = char.UTF8String('У попа была собака')
|
||||
>>> utf8String
|
||||
UTF8String(b'\xd0\xa3 \xd0\xbf\xd0\xbe\xd0\xbf\xd0\xb0 \xd0\xb1\xd1\x8b\xd0\xbb\xd0\xb0 \
|
||||
\xd1\x81\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xba\xd0\xb0')
|
||||
>>> print(utf8String)
|
||||
У попа была собака
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
In pyasn1, all character type objects behave like Python strings. None of
|
||||
them is currently constrained in terms of valid alphabet so it's up to
|
||||
the data source to keep an eye on data validation for these types.
|
||||
</p>
|
||||
|
||||
<a name="1.1.10"></a>
|
||||
<h4>
|
||||
1.1.10 Useful types
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
There are three so-called useful types defined in the standard:
|
||||
ObjectDescriptor, GeneralizedTime, UTCTime. They all are subtypes
|
||||
of GraphicString or VisibleString types therefore useful types are
|
||||
character string types.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It's advised by the ASN.1 standard to have an instance of ObjectDescriptor
|
||||
type holding a human-readable description of corresponding instance of
|
||||
OBJECT IDENTIFIER type. There are no formal linkage between these instances
|
||||
and provision for ObjectDescriptor uniqueness in the standard.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import useful
|
||||
>>> descrBER = useful.ObjectDescriptor(
|
||||
"Basic encoding of a single ASN.1 type"
|
||||
)
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
GeneralizedTime and UTCTime types are designed to hold a human-readable
|
||||
timestamp in a universal and unambiguous form. The former provides
|
||||
more flexibility in notation while the latter is more strict but has
|
||||
Y2K issues.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
;; Mar 8 2010 12:00:00 MSK
|
||||
moscow-time GeneralizedTime ::= "20110308120000.0"
|
||||
;; Mar 8 2010 12:00:00 UTC
|
||||
utc-time GeneralizedTime ::= "201103081200Z"
|
||||
;; Mar 8 1999 12:00:00 UTC
|
||||
utc-time UTCTime ::= "9803081200Z"
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import useful
|
||||
>>> moscowTime = useful.GeneralizedTime("20110308120000.0")
|
||||
>>> utcTime = useful.UTCTime("9803081200Z")
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Despite their intended use, these types possess no special, time-related,
|
||||
handling in pyasn1. They are just printable strings.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
6
third_party/python/pyasn1/doc/source/changelog.rst
vendored
Normal file
6
third_party/python/pyasn1/doc/source/changelog.rst
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
.. include:: ../../CHANGES.rst
|
||||
|
323
third_party/python/pyasn1/doc/source/conf.py
vendored
Normal file
323
third_party/python/pyasn1/doc/source/conf.py
vendored
Normal file
@ -0,0 +1,323 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# PyASN1 documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Jun 27 23:15:54 2015.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.todo'
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['.templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
# source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'contents'
|
||||
|
||||
# General information about the project.
|
||||
project = u'PyASN1'
|
||||
# noinspection PyShadowingBuiltins
|
||||
copyright = u'2005-2017, Ilya Etingof <etingof@gmail.com>'
|
||||
author = u'Ilya Etingof <etingof@gmail.com>'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.3'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.3.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
# today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
# today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
# default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
# add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
# add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
# show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
# modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
# keep_warnings = False
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
# html_theme = 'alabaster'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
# html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
# html_title = None
|
||||
html_title = "PyASN1"
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
# html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
# html_logo = ""
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
# html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
if 'PYASN1DEV' in os.environ:
|
||||
html_static_path = ['.static']
|
||||
|
||||
# Custom CSS theme
|
||||
if 'PYASN1DEV' in os.environ:
|
||||
html_style = 'css/rtdimproved.css'
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
# html_extra_path = []
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
# html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
# html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
# html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
# html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
# html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
# html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
# html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
html_show_sourcelink = False
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
html_show_sphinx = False
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
# html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
# html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
# html_file_suffix = None
|
||||
|
||||
# Language to be used for generating the HTML full-text search index.
|
||||
# Sphinx supports the following languages:
|
||||
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
|
||||
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
|
||||
# html_search_language = 'en'
|
||||
|
||||
# A dictionary with options for the search language support, empty by default.
|
||||
# Now only 'ja' uses this config value
|
||||
# html_search_options = {'type': 'default'}
|
||||
|
||||
# The name of a javascript file (relative to the configuration directory) that
|
||||
# implements a search results scorer. If empty, the default will be used.
|
||||
# html_search_scorer = 'scorer.js'
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pyasn1doc'
|
||||
|
||||
html_context = {
|
||||
'include_analytics': 'PYASN1DEV' in os.environ
|
||||
}
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'PyASN1.tex', u'PyASN1 Documentation',
|
||||
u'Ilya Etingof \\textless{}etingof@gmail.com\\textgreater{}', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'pyasn1', u'PyASN1 Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'PyASN1', u'PyASN1 Documentation',
|
||||
author, 'PyASN1', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
# texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3.4/', None)}
|
||||
|
||||
# this merges constructor docstring with class docstring
|
||||
autoclass_content = 'both'
|
||||
# Sort members by type
|
||||
autodoc_member_order = 'bysource'
|
||||
# autodoc_member_order = 'groupwise'
|
||||
|
||||
# Napoleon settings
|
||||
napoleon_google_docstring = False
|
||||
napoleon_numpy_docstring = True
|
||||
napoleon_include_private_with_doc = False
|
||||
napoleon_include_special_with_doc = True
|
||||
napoleon_use_admonition_for_examples = False
|
||||
napoleon_use_admonition_for_notes = False
|
||||
napoleon_use_admonition_for_references = False
|
||||
napoleon_use_ivar = False
|
||||
napoleon_use_param = False
|
||||
napoleon_use_rtype = False
|
194
third_party/python/pyasn1/doc/source/contents.rst
vendored
Normal file
194
third_party/python/pyasn1/doc/source/contents.rst
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
|
||||
ASN.1 library for Python
|
||||
========================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Abstract Syntax Notation One (`ASN.1
|
||||
<http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_1x>`_) is a
|
||||
technology for exchanging structured data in a universally understood,
|
||||
hardware agnostic way. Many industrial, security and telephony
|
||||
applications heavily rely on ASN.1.
|
||||
|
||||
The `pyasn1 <https://pypi.python.org/pypi/pyasn1/>`_ library implements
|
||||
ASN.1 support in pure-Python.
|
||||
|
||||
What is ASN.1
|
||||
-------------
|
||||
|
||||
ASN.1 is a large, arguably over-engineered and extremely old data modelling and
|
||||
serialization tool. It is probably among the first serialization protocols in
|
||||
the history of computer science and technology.
|
||||
|
||||
ASN.1 started its life over 30 years ago as a serialization mechanism for the first
|
||||
electronic mail (known as X.400). Later on if was split off the e-mail application
|
||||
and become a stand-alone tech still being actively supported by its designers
|
||||
and widely used in industry and technology.
|
||||
|
||||
Since then ASN.1 is sort of haunted by its relations with the OSI model -- the
|
||||
first, unsuccessful, version of the Internet. You can read many interesting
|
||||
`discussions <https://news.ycombinator.com/item?id=8871453>`_ on that topic.
|
||||
|
||||
In the following years, generations of software engineers tackled the serialization
|
||||
problem many times. We can see that in Google's `ProtoBuffers <https://developers.google.com/protocol-buffers/>`_
|
||||
or `FlatBuffers <https://google.github.io/flatbuffers/>`_, for example.
|
||||
Interestingly, many new takes on binary protocol design do not depart
|
||||
far from ASN.1 from technical perspective. It's more of a matter of striking
|
||||
a balance between processing overhead, wire format overhead and human
|
||||
readability.
|
||||
|
||||
Looking at what ASN.1 has to offer, it has three loosely coupled parts:
|
||||
|
||||
* Data types: the standard introduces a collection of basic data types
|
||||
(integers, bits, strings, arrays and records) that can be used for describing
|
||||
arbitrarily complex, nested data structures.
|
||||
|
||||
* Serialization protocols: the above data structures could be converted into a
|
||||
series of octets for storage or transmission over the wire as well as
|
||||
recovered back into their structured form. The system is fully agnostic
|
||||
to hardware architectures differences.
|
||||
|
||||
* Schema language: ASN.1 data structures could be described in terms
|
||||
of a schema language for ASN.1 compiler to turn it into platform-specific
|
||||
implementation.
|
||||
|
||||
ASN.1 applications
|
||||
------------------
|
||||
|
||||
Being an old and generally successful standard, ASN.1 is widely
|
||||
adopted for many uses. To give you an example, these technologies
|
||||
use ASN.1 for their data exchange needs:
|
||||
|
||||
* Signaling standards for the public switched telephone network (SS7 family)
|
||||
* Network management standards (SNMP, CMIP)
|
||||
* Directory standards (X.500 family, LDAP)
|
||||
* Public Key Infrastructure standards (X.509, etc.)
|
||||
* PBX control (CSTA)
|
||||
* IP-based Videoconferencing (H.323 family)
|
||||
* Biometrics (BIP, CBEFF, ACBio)
|
||||
* Intelligent transportation (SAE J2735)
|
||||
* Cellular telephony (GSM, GPRS/EDGE, UMTS, LTE)
|
||||
|
||||
ASN.1 gotchas
|
||||
-------------
|
||||
|
||||
Apparently, ASN.1 is hard to implement properly. Quality open-source
|
||||
ASN.1 tools are rare, but ad-hoc implementations are numerous. Judging from the
|
||||
`statistics <http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=ASN.1>`_ on discovered
|
||||
security vulnerabilities, many people have implemented ASN.1 parsers
|
||||
and oftentimes fell victim to its edge cases.
|
||||
|
||||
On the bright side, ASN.1 has been around for a long time, it is well understood
|
||||
and security reviewed.
|
||||
|
||||
Library capabilities
|
||||
--------------------
|
||||
|
||||
As of this moment, pyasn1 library implements all ASN.1 data
|
||||
types as Python objects in accordance with X.208 standard. Later,
|
||||
post-1995, revision (X.680) introduced some changes to the schema
|
||||
language which may not be fully supported by pyasn1. Aside from data
|
||||
types a collection of data transformation codecs comes with pyasn1 package.
|
||||
|
||||
As for ASN.1 schema language, pyasn1 package does
|
||||
not ship any compiler for it. However, there's a tool called
|
||||
`asn1late <https://github.com/kimgr/asn1ate>`_ which is an ASN.1
|
||||
grammar parser paired to code generator capable of generating pyasn1
|
||||
code. So this is an alternative (or at least a good start) to manual
|
||||
implementation of pyasn1 classes from ASN.1 specification.
|
||||
|
||||
Both `pyasn1 <https://github.com/etingof/pyasn1>`_ and
|
||||
`pyasn1-modules <https://github.com/etingof/pyasn1-modules>`_ libraries
|
||||
can be used out-of-the-box with Python versions 2.4 through 3.6.
|
||||
No external dependencies required.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/tutorial
|
||||
/docs/api-reference
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/example-use-case
|
||||
|
||||
Download & Install
|
||||
------------------
|
||||
|
||||
The PyASN1 software is provided under terms and conditions of BSD-style
|
||||
:ref:`license`, and can be freely downloaded from `Github <https://github.com/etingof/pyasn1>`_
|
||||
or `PyPI <http://pypi.python.org/pypi/pyasn1/>`_.
|
||||
|
||||
It is pure-Python and has no dependencies. Considering how much industrial or finance
|
||||
software can be stuck with an old platform (think RHEL 5), we struggle to maintain its
|
||||
compatibility back to the very pre-historic Python (which is 2.4!).
|
||||
|
||||
The best way to obtain PyASN1 is by running `pip`:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install pyasn1
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ easy_install pyasn1
|
||||
|
||||
You may also want to use `pyasn1-modules`:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install pyasn1-modules
|
||||
|
||||
Changes
|
||||
-------
|
||||
|
||||
All changes and release history is maintained in changelog. There you
|
||||
could also download the latest unreleased pyasn1 tarball containing
|
||||
the latest fixes and improvements.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
/changelog
|
||||
|
||||
Getting help
|
||||
------------
|
||||
|
||||
Please, file your `issues <https://github.com/etingof/pyasn1/issues>`_
|
||||
and `PRs <https://github.com/etingof/pyasn1/pulls>`_ at GitHub.
|
||||
Alternatively, you could ask for help at
|
||||
`Stack Overflow <http://stackoverflow.com/questions/tagged/pyasn1>`_
|
||||
or search
|
||||
`pyasn1-users <https://lists.sourceforge.net/lists/listinfo/pyasn1-users>`_
|
||||
mailing list archive.
|
||||
|
||||
Books on ASN.1
|
||||
--------------
|
||||
|
||||
The pyasn1 implementation is largely based on reading up the following awesome
|
||||
books:
|
||||
|
||||
* `ASN.1 - Communication between heterogeneous systems <http://www.oss.com/asn1/dubuisson.html>`_ by Olivier Dubuisson
|
||||
* `ASN.1 Complete <http://www.oss.com/asn1/resources/books-whitepapers-pubs/larmouth-asn1-book.pdf>`_ by Prof John Larmouth
|
||||
|
||||
Here you can get the official standards which is hard to read:
|
||||
|
||||
* `ITU standards <http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-X.693-0207w.zip>`_
|
||||
|
||||
On the other end of the readability spectrum, here is a quick and sweet write up:
|
||||
|
||||
* `A Layman's Guide to a Subset of ASN.1, BER, and DER <ftp://ftp.rsasecurity.com/pub/pkcs/ascii/layman.asc>`_ by Burton S. Kaliski
|
||||
|
||||
If you are working with ASN.1, we'd highly recommend reading a proper
|
||||
book on the subject.
|
||||
|
30
third_party/python/pyasn1/doc/source/docs/api-reference.rst
vendored
Normal file
30
third_party/python/pyasn1/doc/source/docs/api-reference.rst
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
Library reference
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
ASN.1 types
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/type/univ/contents
|
||||
/docs/type/char/contents
|
||||
/docs/type/useful/contents
|
||||
/docs/type/tag/contents
|
||||
/docs/type/namedtype/contents
|
||||
/docs/type/namedval/contents
|
||||
|
||||
Transformation codecs
|
||||
---------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/codec/ber/contents
|
||||
/docs/codec/cer/contents
|
||||
/docs/codec/der/contents
|
||||
/docs/codec/native/contents
|
7
third_party/python/pyasn1/doc/source/docs/codec/ber/contents.rst
vendored
Normal file
7
third_party/python/pyasn1/doc/source/docs/codec/ber/contents.rst
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
Basic Encoding Rules
|
||||
--------------------
|
||||
|
||||
.. autofunction:: pyasn1.codec.ber.encoder.encode(value, defMode=True, maxChunkSize=0)
|
||||
|
||||
.. autofunction:: pyasn1.codec.ber.decoder.decode(substrate, asn1Spec=None)
|
7
third_party/python/pyasn1/doc/source/docs/codec/cer/contents.rst
vendored
Normal file
7
third_party/python/pyasn1/doc/source/docs/codec/cer/contents.rst
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
Canonical Encoding Rules
|
||||
------------------------
|
||||
|
||||
.. autofunction:: pyasn1.codec.cer.encoder.encode(value)
|
||||
|
||||
.. autofunction:: pyasn1.codec.cer.decoder.decode(substrate, asn1Spec=None)
|
7
third_party/python/pyasn1/doc/source/docs/codec/der/contents.rst
vendored
Normal file
7
third_party/python/pyasn1/doc/source/docs/codec/der/contents.rst
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
Distinguished Encoding Rules
|
||||
----------------------------
|
||||
|
||||
.. autofunction:: pyasn1.codec.der.encoder.encode(value)
|
||||
|
||||
.. autofunction:: pyasn1.codec.der.decoder.decode(substrate, asn1Spec=None)
|
7
third_party/python/pyasn1/doc/source/docs/codec/native/contents.rst
vendored
Normal file
7
third_party/python/pyasn1/doc/source/docs/codec/native/contents.rst
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
Native Python types
|
||||
-------------------
|
||||
|
||||
.. autofunction:: pyasn1.codec.native.encoder.encode(asn1Value)
|
||||
|
||||
.. autofunction:: pyasn1.codec.native.decoder.decode(pyObject, asn1Spec)
|
1778
third_party/python/pyasn1/doc/source/docs/tutorial.rst
vendored
Normal file
1778
third_party/python/pyasn1/doc/source/docs/tutorial.rst
vendored
Normal file
File diff suppressed because it is too large
Load Diff
17
third_party/python/pyasn1/doc/source/docs/type/char/bmpstring.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/char/bmpstring.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: BMPString
|
||||
|
||||
.. |encoding| replace:: utf-16-be
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.BMPString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialized into UTF-16 big endian.
|
||||
|
||||
.. automethod:: pyasn1.type.char.BMPString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.BMPString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
20
third_party/python/pyasn1/doc/source/docs/type/char/contents.rst
vendored
Normal file
20
third_party/python/pyasn1/doc/source/docs/type/char/contents.rst
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
Character types
|
||||
---------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/type/char/numericstring
|
||||
/docs/type/char/printablestring
|
||||
/docs/type/char/teletexstring
|
||||
/docs/type/char/t61string
|
||||
/docs/type/char/videotexstring
|
||||
/docs/type/char/ia5string
|
||||
/docs/type/char/graphicstring
|
||||
/docs/type/char/visiblestring
|
||||
/docs/type/char/iso646string
|
||||
/docs/type/char/generalstring
|
||||
/docs/type/char/universalstring
|
||||
/docs/type/char/bmpstring
|
||||
/docs/type/char/utf8string
|
18
third_party/python/pyasn1/doc/source/docs/type/char/generalstring.rst
vendored
Normal file
18
third_party/python/pyasn1/doc/source/docs/type/char/generalstring.rst
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
.. |ASN.1| replace:: GeneralString
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.GeneralString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a character string similar to :py:class:`GraphicString` but additionally
|
||||
including control characters.
|
||||
|
||||
.. automethod:: pyasn1.type.char.GeneralString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.GeneralString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
18
third_party/python/pyasn1/doc/source/docs/type/char/graphicstring.rst
vendored
Normal file
18
third_party/python/pyasn1/doc/source/docs/type/char/graphicstring.rst
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
.. |ASN.1| replace:: GraphicString
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.GraphicString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a character string that can hold any "graphical" characters
|
||||
mixed with control ones to select particular alphabet.
|
||||
|
||||
.. automethod:: pyasn1.type.char.GraphicString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.GraphicString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
17
third_party/python/pyasn1/doc/source/docs/type/char/ia5string.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/char/ia5string.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: IA5String
|
||||
|
||||
.. |encoding| replace:: us-ascii
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.IA5String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a basic character string first published in 1963 as an ISO/ITU standard, then it turned into ASCII.
|
||||
|
||||
.. automethod:: pyasn1.type.char.IA5String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.IA5String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
17
third_party/python/pyasn1/doc/source/docs/type/char/iso646string.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/char/iso646string.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: ISO646String
|
||||
|
||||
.. |encoding| replace:: us-ascii
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.ISO646String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type is an alias to the :py:class:`VisibleString` type
|
||||
|
||||
.. automethod:: pyasn1.type.char.ISO646String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.ISO646String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
17
third_party/python/pyasn1/doc/source/docs/type/char/numericstring.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/char/numericstring.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: NumericString
|
||||
|
||||
.. |encoding| replace:: us-ascii
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.NumericString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| models character string that can be entered from a telephone handset.
|
||||
|
||||
.. automethod:: pyasn1.type.char.NumericString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.NumericString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
18
third_party/python/pyasn1/doc/source/docs/type/char/printablestring.rst
vendored
Normal file
18
third_party/python/pyasn1/doc/source/docs/type/char/printablestring.rst
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
.. |ASN.1| replace:: PrintableString
|
||||
|
||||
.. |encoding| replace:: us-ascii
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.PrintableString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| models character string that can be entered from a very rudimentary terminals featuring letters,
|
||||
digits and punctuation marks.
|
||||
|
||||
.. automethod:: pyasn1.type.char.PrintableString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.PrintableString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
17
third_party/python/pyasn1/doc/source/docs/type/char/t61string.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/char/t61string.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: T61String
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.T61String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type is an alias to :py:class:`TeletexString` type.
|
||||
|
||||
.. automethod:: pyasn1.type.char.T61String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.T61String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
19
third_party/python/pyasn1/doc/source/docs/type/char/teletexstring.rst
vendored
Normal file
19
third_party/python/pyasn1/doc/source/docs/type/char/teletexstring.rst
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
.. |ASN.1| replace:: TeletexString
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.TeletexString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models character string that can be entered from a sophisticated text processing machines
|
||||
(by 20-th century standards) featuring letters from multiple alphabets (308 characters!), digits,
|
||||
punctuation marks and escape sequences.
|
||||
|
||||
.. automethod:: pyasn1.type.char.TeletexString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.TeletexString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
17
third_party/python/pyasn1/doc/source/docs/type/char/universalstring.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/char/universalstring.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: UniversalString
|
||||
|
||||
.. |encoding| replace:: utf-32-be
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.UniversalString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialized into UTF-32 big endian.
|
||||
|
||||
.. automethod:: pyasn1.type.char.UniversalString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.UniversalString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
17
third_party/python/pyasn1/doc/source/docs/type/char/utf8string.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/char/utf8string.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: UTF8String
|
||||
|
||||
.. |encoding| replace:: utf-8
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.UTF8String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialized into UTF-8.
|
||||
|
||||
.. automethod:: pyasn1.type.char.UTF8String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.UTF8String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
18
third_party/python/pyasn1/doc/source/docs/type/char/videotexstring.rst
vendored
Normal file
18
third_party/python/pyasn1/doc/source/docs/type/char/videotexstring.rst
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
.. |ASN.1| replace:: VideotexString
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.VideotexString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models character string that can be consumed by sophisticated video
|
||||
terminals (by 20-th century standards) to render ascii-art style pictures and animations.
|
||||
|
||||
.. automethod:: pyasn1.type.char.VideotexString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.VideotexString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
18
third_party/python/pyasn1/doc/source/docs/type/char/visiblestring.rst
vendored
Normal file
18
third_party/python/pyasn1/doc/source/docs/type/char/visiblestring.rst
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
.. |ASN.1| replace:: VisibleString
|
||||
|
||||
.. |encoding| replace:: us-ascii
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.char.VisibleString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a character string that can hold any "graphical" characters
|
||||
mixed with control ones to select particular alphabet.
|
||||
|
||||
.. automethod:: pyasn1.type.char.VisibleString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.char.VisibleString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
11
third_party/python/pyasn1/doc/source/docs/type/namedtype/contents.rst
vendored
Normal file
11
third_party/python/pyasn1/doc/source/docs/type/namedtype/contents.rst
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
Fields of constructed types
|
||||
---------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/type/namedtype/namedtype
|
||||
/docs/type/namedtype/optionalnamedtype
|
||||
/docs/type/namedtype/defaultednamedtype
|
||||
/docs/type/namedtype/namedtypes
|
12
third_party/python/pyasn1/doc/source/docs/type/namedtype/defaultednamedtype.rst
vendored
Normal file
12
third_party/python/pyasn1/doc/source/docs/type/namedtype/defaultednamedtype.rst
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
.. |NamedType| replace:: DefaultedNamedType
|
||||
|
||||
|NamedType|
|
||||
------------------
|
||||
|
||||
.. autoclass:: pyasn1.type.namedtype.DefaultedNamedType
|
||||
:members:
|
||||
|
||||
.. note::
|
||||
|
||||
The |NamedType| class models named field of a constructed ASN.1 type which has a default value.
|
12
third_party/python/pyasn1/doc/source/docs/type/namedtype/namedtype.rst
vendored
Normal file
12
third_party/python/pyasn1/doc/source/docs/type/namedtype/namedtype.rst
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
.. |NamedType| replace:: NamedType
|
||||
|
||||
|NamedType|
|
||||
-----------
|
||||
|
||||
.. autoclass:: pyasn1.type.namedtype.NamedType
|
||||
:members:
|
||||
|
||||
.. note::
|
||||
|
||||
The |NamedType| class models a mandatory field of a constructed ASN.1 type.
|
6
third_party/python/pyasn1/doc/source/docs/type/namedtype/namedtypes.rst
vendored
Normal file
6
third_party/python/pyasn1/doc/source/docs/type/namedtype/namedtypes.rst
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
NamedTypes
|
||||
----------
|
||||
|
||||
.. autoclass:: pyasn1.type.namedtype.NamedTypes
|
||||
:members:
|
12
third_party/python/pyasn1/doc/source/docs/type/namedtype/optionalnamedtype.rst
vendored
Normal file
12
third_party/python/pyasn1/doc/source/docs/type/namedtype/optionalnamedtype.rst
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
.. |NamedType| replace:: OptionalNamedType
|
||||
|
||||
|NamedType|
|
||||
------------------
|
||||
|
||||
.. autoclass:: pyasn1.type.namedtype.OptionalNamedType
|
||||
:members:
|
||||
|
||||
.. note::
|
||||
|
||||
The |NamedType| class models an optional field of a constructed ASN.1 type.
|
13
third_party/python/pyasn1/doc/source/docs/type/namedval/contents.rst
vendored
Normal file
13
third_party/python/pyasn1/doc/source/docs/type/namedval/contents.rst
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
Enumerating numbers
|
||||
-------------------
|
||||
|
||||
Some ASN.1 types such as :py:class:`~pyasn1.type.univ.Integer`,
|
||||
:py:class:`~pyasn1.type.univ.Enumerated` and
|
||||
:py:class:`~pyasn1.type.univ.BitString` may enumerate their values
|
||||
with human-friendly labels.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/type/namedval/namedval
|
11
third_party/python/pyasn1/doc/source/docs/type/namedval/namedval.rst
vendored
Normal file
11
third_party/python/pyasn1/doc/source/docs/type/namedval/namedval.rst
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
.. |NamedValues| replace:: NamedValues
|
||||
|
||||
|NamedValues|
|
||||
-------------
|
||||
|
||||
The |NamedValues| class associates human-friendly names to a set of numbers
|
||||
or bits.
|
||||
|
||||
.. autoclass:: pyasn1.type.namedval.NamedValues
|
||||
:members:
|
10
third_party/python/pyasn1/doc/source/docs/type/tag/contents.rst
vendored
Normal file
10
third_party/python/pyasn1/doc/source/docs/type/tag/contents.rst
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
Tagging types
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/type/tag/tag
|
||||
/docs/type/tag/tagset
|
||||
/docs/type/tag/tagmap
|
8
third_party/python/pyasn1/doc/source/docs/type/tag/tag.rst
vendored
Normal file
8
third_party/python/pyasn1/doc/source/docs/type/tag/tag.rst
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
Solitary tag
|
||||
------------
|
||||
|
||||
.. automodule:: pyasn1.type.tag
|
||||
:members: Tag, tagClassUniversal, tagClassApplication, tagClassContext,
|
||||
tagClassPrivate, tagFormatSimple, tagFormatConstructed
|
||||
|
6
third_party/python/pyasn1/doc/source/docs/type/tag/tagmap.rst
vendored
Normal file
6
third_party/python/pyasn1/doc/source/docs/type/tag/tagmap.rst
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
Tag->type map
|
||||
-------------
|
||||
|
||||
.. autoclass:: pyasn1.type.tagmap.TagMap
|
||||
:members:
|
6
third_party/python/pyasn1/doc/source/docs/type/tag/tagset.rst
vendored
Normal file
6
third_party/python/pyasn1/doc/source/docs/type/tag/tagset.rst
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
Composition of tags
|
||||
-------------------
|
||||
|
||||
.. autoclass:: pyasn1.type.tag.TagSet
|
||||
:members:
|
20
third_party/python/pyasn1/doc/source/docs/type/univ/any.rst
vendored
Normal file
20
third_party/python/pyasn1/doc/source/docs/type/univ/any.rst
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
.. |ASN.1| replace:: Any
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Any(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1', binValue=NoValue(),hexValue=NoValue())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models an arbitrary value of an arbitrary type. Sometimes
|
||||
type is defined by accompanying object identifier or an integer identifier.
|
||||
Frequently ANY value holds a serialized representation of some other ASN.1
|
||||
object.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Any.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1')
|
||||
.. automethod:: pyasn1.type.univ.Any.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(),encoding='iso-8859-1')
|
15
third_party/python/pyasn1/doc/source/docs/type/univ/bitstring.rst
vendored
Normal file
15
third_party/python/pyasn1/doc/source/docs/type/univ/bitstring.rst
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
.. |ASN.1| replace:: BitString
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.BitString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, asInteger, asNumbers, asOctets, asBinary, fromHexString, fromBinaryString, fromOctetString
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models an arbitrary sequence of bits.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.BitString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue())
|
||||
.. automethod:: pyasn1.type.univ.BitString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), , namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue())
|
15
third_party/python/pyasn1/doc/source/docs/type/univ/boolean.rst
vendored
Normal file
15
third_party/python/pyasn1/doc/source/docs/type/univ/boolean.rst
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
.. |ASN.1| replace:: Boolean
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Boolean(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a BOOLEAN that can be either TRUE or FALSE.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Boolean.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
.. automethod:: pyasn1.type.univ.Boolean.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection())
|
17
third_party/python/pyasn1/doc/source/docs/type/univ/choice.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/univ/choice.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: Choice
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Choice(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec,
|
||||
getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents,
|
||||
getComponentByType, setComponentByType, getName, getComponent
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type can only hold a single component at a time belonging to the list of allowed types.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Choice.clone(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
.. automethod:: pyasn1.type.univ.Choice.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
|
23
third_party/python/pyasn1/doc/source/docs/type/univ/contents.rst
vendored
Normal file
23
third_party/python/pyasn1/doc/source/docs/type/univ/contents.rst
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
Universal types
|
||||
---------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.NoValue()
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/type/univ/integer
|
||||
/docs/type/univ/boolean
|
||||
/docs/type/univ/bitstring
|
||||
/docs/type/univ/octetstring
|
||||
/docs/type/univ/null
|
||||
/docs/type/univ/objectidentifier
|
||||
/docs/type/univ/real
|
||||
/docs/type/univ/enumerated
|
||||
/docs/type/univ/any
|
||||
/docs/type/univ/setof
|
||||
/docs/type/univ/sequenceof
|
||||
/docs/type/univ/set
|
||||
/docs/type/univ/sequence
|
||||
/docs/type/univ/choice
|
16
third_party/python/pyasn1/doc/source/docs/type/univ/enumerated.rst
vendored
Normal file
16
third_party/python/pyasn1/doc/source/docs/type/univ/enumerated.rst
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
.. |ASN.1| replace:: Enumerated
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Enumerated(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, namedValues
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models bounded set of named integer values. Other than that, it is identical to
|
||||
the *Integer* class.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Enumerated.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues())
|
||||
.. automethod:: pyasn1.type.univ.Enumerated.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues())
|
17
third_party/python/pyasn1/doc/source/docs/type/univ/integer.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/univ/integer.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: Integer
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Integer(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap,
|
||||
subtypeSpec, namedValues
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models an arbitrary integer. INTEGER values can be positive, negative,
|
||||
or zero, and can have any magnitude.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Integer.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues())
|
||||
.. automethod:: pyasn1.type.univ.Integer.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues())
|
15
third_party/python/pyasn1/doc/source/docs/type/univ/null.rst
vendored
Normal file
15
third_party/python/pyasn1/doc/source/docs/type/univ/null.rst
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
.. |ASN.1| replace:: Null
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Null(value=NoValue(), tagSet=TagSet())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models ASN.1 NULL.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Null.clone(value=NoValue(), tagSet=TagSet())
|
||||
.. automethod:: pyasn1.type.univ.Null.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag())
|
15
third_party/python/pyasn1/doc/source/docs/type/univ/objectidentifier.rst
vendored
Normal file
15
third_party/python/pyasn1/doc/source/docs/type/univ/objectidentifier.rst
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
.. |ASN.1| replace:: ObjectIdentifier
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.ObjectIdentifier(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, isPrefixOf
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models ASN.1 OBJECT IDENTIFIER as a sequence of integer numbers.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.ObjectIdentifier.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
.. automethod:: pyasn1.type.univ.ObjectIdentifier.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection())
|
17
third_party/python/pyasn1/doc/source/docs/type/univ/octetstring.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/univ/octetstring.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: OctetString
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.OctetString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1', binValue=NoValue(),hexValue=NoValue())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, fromHexString, fromBinaryString
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models an arbitrary string of octets (eight-bit numbers), not printable text string.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.OctetString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1')
|
||||
.. automethod:: pyasn1.type.univ.OctetString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(),encoding='iso-8859-1')
|
15
third_party/python/pyasn1/doc/source/docs/type/univ/real.rst
vendored
Normal file
15
third_party/python/pyasn1/doc/source/docs/type/univ/real.rst
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
.. |ASN.1| replace:: Real
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Real(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, isInf, isPlusInf, isMinusInf
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a rational number of arbitrary precision.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Real.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
.. automethod:: pyasn1.type.univ.Real.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection())
|
17
third_party/python/pyasn1/doc/source/docs/type/univ/sequence.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/univ/sequence.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: Sequence
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Sequence(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec, getComponentByPosition,
|
||||
setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a collection of named ASN.1 components.
|
||||
Ordering of the components **is** preserved upon de/serialization.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Sequence.clone(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
.. automethod:: pyasn1.type.univ.Sequence.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
|
17
third_party/python/pyasn1/doc/source/docs/type/univ/sequenceof.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/univ/sequenceof.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: SequenceOf
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.SequenceOf(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec,
|
||||
getComponentByPosition, setComponentByPosition
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a collection of elements of a single ASN.1 type.
|
||||
Ordering of the components **is** preserved upon de/serialization.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.SequenceOf.clone(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
.. automethod:: pyasn1.type.univ.SequenceOf.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
|
18
third_party/python/pyasn1/doc/source/docs/type/univ/set.rst
vendored
Normal file
18
third_party/python/pyasn1/doc/source/docs/type/univ/set.rst
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
.. |ASN.1| replace:: Set
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.Set(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec,
|
||||
getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents,
|
||||
getComponentByType, setComponentByType
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a collection of named ASN.1 components.
|
||||
Ordering of the components **is not** preserved upon de/serialization.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.Set.clone(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
.. automethod:: pyasn1.type.univ.Set.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
|
17
third_party/python/pyasn1/doc/source/docs/type/univ/setof.rst
vendored
Normal file
17
third_party/python/pyasn1/doc/source/docs/type/univ/setof.rst
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
.. |ASN.1| replace:: SetOf
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.univ.SetOf(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection())
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec,
|
||||
getComponentByPosition, setComponentByPosition
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a collection of elements of a single ASN.1 type.
|
||||
Ordering of the components **is not** preserved upon de/serialization.
|
||||
|
||||
.. automethod:: pyasn1.type.univ.SetOf.clone(componentType=None, tagSet=TagSet(), subtypeSpec=ConstraintsIntersection())
|
||||
.. automethod:: pyasn1.type.univ.SetOf.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection())
|
10
third_party/python/pyasn1/doc/source/docs/type/useful/contents.rst
vendored
Normal file
10
third_party/python/pyasn1/doc/source/docs/type/useful/contents.rst
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
Useful types
|
||||
------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
/docs/type/useful/objectdescriptor
|
||||
/docs/type/useful/generalizedtime
|
||||
/docs/type/useful/utctime
|
35
third_party/python/pyasn1/doc/source/docs/type/useful/generalizedtime.rst
vendored
Normal file
35
third_party/python/pyasn1/doc/source/docs/type/useful/generalizedtime.rst
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
.. |ASN.1| replace:: GeneralizedTime
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.useful.GeneralizedTime(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, asDateTime, fromDateTime
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
The |ASN.1| type models a character string representing date and time
|
||||
in many different formats.
|
||||
|
||||
Formal syntax for the *GeneralizedTime* value is:
|
||||
|
||||
* **YYYYMMDDhh[mm[ss[(.|,)ffff]]]** standing for a local time, four
|
||||
digits for the year, two for the month, two for the day and two
|
||||
for the hour, followed by two digits for the minutes and two
|
||||
for the seconds if required, then a dot (or a comma), and a
|
||||
number for the fractions of second or
|
||||
|
||||
* a string as above followed by the letter “Z” (denoting a UTC
|
||||
time) or
|
||||
|
||||
* a string as above followed by a string **(+|-)hh[mm]** denoting
|
||||
time zone offset relative to UTC
|
||||
|
||||
For example, *20170126120000Z* stands for YYYYMMDDHHMMSSZ.
|
||||
|
||||
.. automethod:: pyasn1.type.useful.GeneralizedTime.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.useful.GeneralizedTime.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
18
third_party/python/pyasn1/doc/source/docs/type/useful/objectdescriptor.rst
vendored
Normal file
18
third_party/python/pyasn1/doc/source/docs/type/useful/objectdescriptor.rst
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
.. |ASN.1| replace:: ObjectDescriptor
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.useful.ObjectDescriptor(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a character string that can accompany the *ObjectIdentifier* type
|
||||
to serve as a human-friendly annotation for an OBJECT IDENTIFIER.
|
||||
|
||||
.. automethod:: pyasn1.type.useful.ObjectDescriptor.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.useful.ObjectDescriptor.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
32
third_party/python/pyasn1/doc/source/docs/type/useful/utctime.rst
vendored
Normal file
32
third_party/python/pyasn1/doc/source/docs/type/useful/utctime.rst
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
.. |ASN.1| replace:: UTCTime
|
||||
|
||||
.. |encoding| replace:: iso-8859-1
|
||||
|
||||
|ASN.1| type
|
||||
------------
|
||||
|
||||
.. autoclass:: pyasn1.type.useful.UTCTime(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
:members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, asDateTime, fromDateTime
|
||||
|
||||
.. note::
|
||||
|
||||
The |ASN.1| type models a character string representing date and time.
|
||||
|
||||
Formal syntax for the *UTCTime* value is:
|
||||
|
||||
* **YYMMDDhhmm[ss]** standing for UTC time, two
|
||||
digits for the year, two for the month, two for the day and two
|
||||
for the hour, followed by two digits for the minutes and two
|
||||
for the seconds if required or
|
||||
|
||||
* a string as above followed by the letter “Z” (denoting a UTC
|
||||
time) or
|
||||
|
||||
* a string as above followed by a string **(+|-)hhmm** denoting
|
||||
time zone offset relative to UTC
|
||||
|
||||
For example, *170126120000Z* which stands for YYMMDDHHMMSSZ.
|
||||
|
||||
.. automethod:: pyasn1.type.useful.UTCTime.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
||||
.. automethod:: pyasn1.type.useful.UTCTime.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii')
|
193
third_party/python/pyasn1/doc/source/example-use-case.rst
vendored
Normal file
193
third_party/python/pyasn1/doc/source/example-use-case.rst
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
|
||||
Example use case
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
To briefly explain how to approach pyasn1, consider a quick workflow example.
|
||||
|
||||
Grab ASN.1 schema for SSH keys
|
||||
------------------------------
|
||||
|
||||
ASN.1 is widely used in many Internet protocols. Frequently, whenever ASN.1 is employed,
|
||||
data structures are described in ASN.1 schema language right in the RFC.
|
||||
Take `RFC2437 <https://www.ietf.org/rfc/rfc2437.txt>`_ for example -- we can look into
|
||||
it and weed out data structures specification into a local file:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# pkcs-1.asn
|
||||
|
||||
PKCS-1 {iso(1) member(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) modules(0) pkcs-1(1)}
|
||||
|
||||
DEFINITIONS EXPLICIT TAGS ::= BEGIN
|
||||
RSAPrivateKey ::= SEQUENCE {
|
||||
version Version,
|
||||
modulus INTEGER,
|
||||
publicExponent INTEGER,
|
||||
privateExponent INTEGER,
|
||||
prime1 INTEGER,
|
||||
prime2 INTEGER,
|
||||
exponent1 INTEGER,
|
||||
exponent2 INTEGER,
|
||||
coefficient INTEGER
|
||||
}
|
||||
Version ::= INTEGER
|
||||
END
|
||||
|
||||
Compile ASN.1 schema into Python
|
||||
--------------------------------
|
||||
|
||||
In the best case, you should be able to automatically compile ASN.1 spec into
|
||||
Python classes. For that purpose we have the `asn1ate <https://github.com/kimgr/asn1ate>`_
|
||||
tool:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pyasn1gen.py pkcs-1.asn > rsakey.py
|
||||
|
||||
Though it may not work out as, as it stands now, asn1ate does not support
|
||||
all ASN.1 language constructs.
|
||||
|
||||
Alternatively, you could check out the `pyasn1-modules <https://github.com/etingof/pyasn1-modules>`_
|
||||
package to see if it already has the ASN.1 spec you are looking for compiled and shipped
|
||||
there. Then just install the package, import the data structure you need and use it:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install pyasn1-modules
|
||||
|
||||
As a last resort, you could express ASN.1 in Python by hand. The end result
|
||||
should be a declarative Python code resembling original ASN.1 syntax like
|
||||
this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# rsakey.py
|
||||
|
||||
class Version(Integer):
|
||||
pass
|
||||
|
||||
class RSAPrivateKey(Sequence):
|
||||
componentType = NamedTypes(
|
||||
NamedType('version', Version()),
|
||||
NamedType('modulus', Integer()),
|
||||
NamedType('publicExponent', Integer()),
|
||||
NamedType('privateExponent', Integer()),
|
||||
NamedType('prime1', Integer()),
|
||||
NamedType('prime2', Integer()),
|
||||
NamedType('exponent1', Integer()),
|
||||
NamedType('exponent2', Integer()),
|
||||
NamedType('coefficient', Integer())
|
||||
)
|
||||
|
||||
Read your ~/.ssh/id_rsa
|
||||
-----------------------
|
||||
|
||||
Given we've put our Python classes into the `rsakey.py` module, we could import
|
||||
the top-level object for SSH keys container and initialize it from our
|
||||
`~/.ssh/id_rsa` file (for sake of simplicity here we assume no passphrase is
|
||||
set on the key file):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from base64 import b64decode
|
||||
from pyasn1.codec.der.decoder import decode as der_decoder
|
||||
from rsakey import RSAPrivateKey
|
||||
|
||||
# Read SSH key from file (assuming no passphrase)
|
||||
with open open('.ssh/id_rsa') as key_file:
|
||||
b64_serialization = ''.join(key_file.readlines()[1:-1])
|
||||
|
||||
# Undo BASE64 serialization
|
||||
der_serialization = b64decode(b64_serialization)
|
||||
|
||||
# Undo DER serialization, reconstruct SSH key structure
|
||||
private_key, rest_of_input = der_decoder(der_serialization, asn1Spec=RSAPrivateKey())
|
||||
|
||||
Once we have Python ASN.1 structures initialized, we could inspect them:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(private_key.prettyPrint())
|
||||
RSAPrivateKey:
|
||||
version=0
|
||||
modulus=280789907761334970323210643584308373...
|
||||
publicExponent=65537
|
||||
privateExponent=1704567874679144879123080924...
|
||||
prime1=1780178536719561265324798296279384073...
|
||||
prime2=1577313184995269616049017780493740138...
|
||||
exponent1=1193974819720845247396384239609024...
|
||||
exponent2=9240965721817961178848297404494811...
|
||||
coefficient=10207364473358910343346707141115...
|
||||
|
||||
Play with the keys
|
||||
------------------
|
||||
|
||||
As well as use them nearly as we do with native Python types:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pk = private_key
|
||||
>>>
|
||||
>>> pk['prime1'] * pk['prime2'] == pk['modulus']
|
||||
True
|
||||
>>> pk['prime1'] == pk['modulus'] // pk['prime2']
|
||||
True
|
||||
>>> pk['exponent1'] == pk['privateExponent'] % (pk['prime1'] - 1)
|
||||
True
|
||||
>>> pk['exponent2'] == pk['privateExponent'] % (pk['prime2'] - 1)
|
||||
True
|
||||
|
||||
Technically, pyasn1 classes `emulate <https://docs.python.org/3/reference/datamodel.html#emulating-container-types>`_
|
||||
Python built-in types.
|
||||
|
||||
Transform to built-ins
|
||||
----------------------
|
||||
|
||||
ASN.1 data structures exhibit a way more complicated behaviour compared to
|
||||
Python types. You may wish to simplify things by turning the whole tree of
|
||||
pyasn1 objects into an analogous tree made of base Python types:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from pyasn1.codec.native.encoder import encode
|
||||
>>> ...
|
||||
>>> py_private_key = encode(private_key)
|
||||
>>> py_private_key
|
||||
{'version': 0, 'modulus': 280789907761334970323210643584308373, 'publicExponent': 65537,
|
||||
'privateExponent': 1704567874679144879123080924, 'prime1': 1780178536719561265324798296279384073,
|
||||
'prime2': 1577313184995269616049017780493740138, 'exponent1': 1193974819720845247396384239609024,
|
||||
'exponent2': 9240965721817961178848297404494811, 'coefficient': 10207364473358910343346707141115}
|
||||
|
||||
You can do vice-versa: initialize ASN.1 structure from a dict:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from pyasn1.codec.native.decoder import decode
|
||||
>>> py_private_key = {'modulus': 280789907761334970323210643584308373}
|
||||
>>> private_key = decode(py_private_key, asn1Spec=RSAPrivateKey())
|
||||
|
||||
Write it back
|
||||
-------------
|
||||
|
||||
Possibly not that applicable to the SSH key example, but you can of course modify
|
||||
any part of the ASN.1 data structure and serialize it back into the same or other
|
||||
wire representation:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pyasn1.codec.der.encoder import encode as der_encoder
|
||||
|
||||
# Serialize SSH key data structure into DER stream
|
||||
der_serialization = der_encoder(private_key)
|
||||
|
||||
# Serialize DER stream into BASE64 stream
|
||||
b64_serialization = '-----BEGIN RSA PRIVATE KEY-----\n'
|
||||
b64_serialization += b64encode(der_serialization)
|
||||
b64_serialization += '-----END RSA PRIVATE KEY-----\n'
|
||||
|
||||
with open('.ssh/id_rsa.new', 'w') as key_file:
|
||||
key_file.write(b64_serialization)
|
||||
|
6
third_party/python/pyasn1/doc/source/license.rst
vendored
Normal file
6
third_party/python/pyasn1/doc/source/license.rst
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.. _license:
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
.. include:: ../../LICENSE.rst
|
233
third_party/python/pyasn1/doc/tagging.html
vendored
233
third_party/python/pyasn1/doc/tagging.html
vendored
@ -1,233 +0,0 @@
|
||||
<html>
|
||||
<title>
|
||||
Tagging in PyASN1
|
||||
</title>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<table width=60%>
|
||||
<tr>
|
||||
<td>
|
||||
<a name="1.2"></a>
|
||||
<h4>
|
||||
1.2 Tagging in PyASN1
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
In order to continue with the Constructed ASN.1 types, we will first have
|
||||
to introduce the concept of tagging (and its pyasn1 implementation), as
|
||||
some of the Constructed types rely upon the tagging feature.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When a value is coming into an ASN.1-based system (received from a network
|
||||
or read from some storage), the receiving entity has to determine the
|
||||
type of the value to interpret and verify it accordingly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Historically, the first data serialization protocol introduced in
|
||||
ASN.1 was BER (Basic Encoding Rules). According to BER, any serialized
|
||||
value is packed into a triplet of (Type, Length, Value) where Type is a
|
||||
code that identifies the value (which is called <i>tag</i> in ASN.1),
|
||||
length is the number of bytes occupied by the value in its serialized form
|
||||
and value is ASN.1 value in a form suitable for serial transmission or storage.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For that reason almost every ASN.1 type has a tag (which is actually a
|
||||
BER type) associated with it by default.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An ASN.1 tag could be viewed as a tuple of three numbers:
|
||||
(Class, Format, Number). While Number identifies a tag, Class component
|
||||
is used to create scopes for Numbers. Four scopes are currently defined:
|
||||
UNIVERSAL, context-specific, APPLICATION and PRIVATE. The Format component
|
||||
is actually a one-bit flag - zero for tags associated with scalar types,
|
||||
and one for constructed types (will be discussed later on).
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
MyIntegerType ::= [12] INTEGER
|
||||
MyOctetString ::= [APPLICATION 0] OCTET STRING
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
In pyasn1, tags are implemented as immutable, tuple-like objects:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import tag
|
||||
>>> myTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
|
||||
>>> myTag
|
||||
Tag(tagClass=128, tagFormat=0, tagId=10)
|
||||
>>> tuple(myTag)
|
||||
(128, 0, 10)
|
||||
>>> myTag[2]
|
||||
10
|
||||
>>> myTag == tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 10)
|
||||
False
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Default tag, associated with any ASN.1 type, could be extended or replaced
|
||||
to make new type distinguishable from its ancestor. The standard provides
|
||||
two modes of tag mangling - IMPLICIT and EXPLICIT.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
EXPLICIT mode works by appending new tag to the existing ones thus creating
|
||||
an ordered set of tags. This set will be considered as a whole for type
|
||||
identification and encoding purposes. Important property of EXPLICIT tagging
|
||||
mode is that it preserves base type information in encoding what makes it
|
||||
possible to completely recover type information from encoding.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When tagging in IMPLICIT mode, the outermost existing tag is dropped and
|
||||
replaced with a new one.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
MyIntegerType ::= [12] IMPLICIT INTEGER
|
||||
MyOctetString ::= [APPLICATION 0] EXPLICIT OCTET STRING
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
To model both modes of tagging, a specialized container TagSet object (holding
|
||||
zero, one or more Tag objects) is used in pyasn1.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import tag
|
||||
>>> tagSet = tag.TagSet(
|
||||
... # base tag
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10),
|
||||
... # effective tag
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
|
||||
... )
|
||||
>>> tagSet
|
||||
TagSet(Tag(tagClass=128, tagFormat=0, tagId=10))
|
||||
>>> tagSet.getBaseTag()
|
||||
Tag(tagClass=128, tagFormat=0, tagId=10)
|
||||
>>> tagSet = tagSet.tagExplicitly(
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)
|
||||
... )
|
||||
>>> tagSet
|
||||
TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
|
||||
Tag(tagClass=128, tagFormat=32, tagId=20))
|
||||
>>> tagSet = tagSet.tagExplicitly(
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 30)
|
||||
... )
|
||||
>>> tagSet
|
||||
TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
|
||||
Tag(tagClass=128, tagFormat=32, tagId=20),
|
||||
Tag(tagClass=128, tagFormat=32, tagId=30))
|
||||
>>> tagSet = tagSet.tagImplicitly(
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)
|
||||
... )
|
||||
>>> tagSet
|
||||
TagSet(Tag(tagClass=128, tagFormat=0, tagId=10),
|
||||
Tag(tagClass=128, tagFormat=32, tagId=20),
|
||||
Tag(tagClass=128, tagFormat=32, tagId=40))
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
As a side note: the "base tag" concept (accessible through the getBaseTag()
|
||||
method) is specific to pyasn1 -- the base tag is used to identify the original
|
||||
ASN.1 type of an object in question. Base tag is never occurs in encoding
|
||||
and is mostly used internally by pyasn1 for choosing type-specific data
|
||||
processing algorithms. The "effective tag" is the one that always appears in
|
||||
encoding and is used on tagSets comparation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Any two TagSet objects could be compared to see if one is a derivative
|
||||
of the other. Figuring this out is also useful in cases when a type-specific
|
||||
data processing algorithms are to be chosen.
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import tag
|
||||
>>> tagSet1 = tag.TagSet(
|
||||
... # base tag
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
|
||||
... # effective tag
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)
|
||||
... )
|
||||
>>> tagSet2 = tagSet1.tagExplicitly(
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)
|
||||
... )
|
||||
>>> tagSet1.isSuperTagSetOf(tagSet2)
|
||||
True
|
||||
>>> tagSet2.isSuperTagSetOf(tagSet1)
|
||||
False
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
We will complete this discussion on tagging with a real-world example. The
|
||||
following ASN.1 tagged type:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
MyIntegerType ::= [12] EXPLICIT INTEGER
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
could be expressed in pyasn1 like this:
|
||||
</p>
|
||||
|
||||
<table bgcolor="lightgray" border=0 width=100%><TR><TD>
|
||||
<pre>
|
||||
>>> from pyasn1.type import univ, tag
|
||||
>>> class MyIntegerType(univ.Integer):
|
||||
... tagSet = univ.Integer.tagSet.tagExplicitly(
|
||||
... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 12)
|
||||
... )
|
||||
>>> myInteger = MyIntegerType(12345)
|
||||
>>> myInteger.getTagSet()
|
||||
TagSet(Tag(tagClass=0, tagFormat=0, tagId=2),
|
||||
Tag(tagClass=128, tagFormat=32, tagId=12))
|
||||
>>>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
|
||||
<p>
|
||||
Referring to the above code, the tagSet class attribute is a property of any
|
||||
pyasn1 type object that assigns default tagSet to a pyasn1 value object. This
|
||||
default tagSet specification can be ignored and effectively replaced by some
|
||||
other tagSet value passed on object instantiation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It's important to understand that the tag set property of pyasn1 type/value
|
||||
object can never be modifed in place. In other words, a pyasn1 type/value
|
||||
object can never change its tags. The only way is to create a new pyasn1
|
||||
type/value object and associate different tag set with it.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
@ -1,26 +1,33 @@
|
||||
Metadata-Version: 1.0
|
||||
Metadata-Version: 1.1
|
||||
Name: pyasn1
|
||||
Version: 0.1.7
|
||||
Version: 0.3.7
|
||||
Summary: ASN.1 types and codecs
|
||||
Home-page: http://sourceforge.net/projects/pyasn1/
|
||||
Author: Ilya Etingof <ilya@glas.net>
|
||||
Author-email: ilya@glas.net
|
||||
Home-page: https://github.com/etingof/pyasn1
|
||||
Author: Ilya Etingof <etingof@gmail.com>
|
||||
Author-email: etingof@gmail.com
|
||||
License: BSD
|
||||
Description: A pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208).
|
||||
Description: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)
|
||||
Platform: any
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Environment :: Console
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Intended Audience :: Education
|
||||
Classifier: Intended Audience :: Information Technology
|
||||
Classifier: Intended Audience :: Science/Research
|
||||
Classifier: Intended Audience :: System Administrators
|
||||
Classifier: Intended Audience :: Telecommunications Industry
|
||||
Classifier: License :: OSI Approved :: BSD License
|
||||
Classifier: Natural Language :: English
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.4
|
||||
Classifier: Programming Language :: Python :: 2.5
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.2
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Topic :: Communications
|
||||
Classifier: Topic :: Security :: Cryptography
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
|
@ -1,17 +1,66 @@
|
||||
CHANGES
|
||||
LICENSE
|
||||
CHANGES.rst
|
||||
LICENSE.rst
|
||||
MANIFEST.in
|
||||
README
|
||||
THANKS
|
||||
TODO
|
||||
README.md
|
||||
TODO.rst
|
||||
setup.cfg
|
||||
setup.py
|
||||
doc/codecs.html
|
||||
doc/constraints.html
|
||||
doc/constructed.html
|
||||
doc/intro.html
|
||||
doc/pyasn1-tutorial.html
|
||||
doc/scalar.html
|
||||
doc/tagging.html
|
||||
doc/Makefile
|
||||
doc/source/changelog.rst
|
||||
doc/source/conf.py
|
||||
doc/source/contents.rst
|
||||
doc/source/example-use-case.rst
|
||||
doc/source/license.rst
|
||||
doc/source/docs/api-reference.rst
|
||||
doc/source/docs/tutorial.rst
|
||||
doc/source/docs/codec/ber/contents.rst
|
||||
doc/source/docs/codec/cer/contents.rst
|
||||
doc/source/docs/codec/der/contents.rst
|
||||
doc/source/docs/codec/native/contents.rst
|
||||
doc/source/docs/type/char/bmpstring.rst
|
||||
doc/source/docs/type/char/contents.rst
|
||||
doc/source/docs/type/char/generalstring.rst
|
||||
doc/source/docs/type/char/graphicstring.rst
|
||||
doc/source/docs/type/char/ia5string.rst
|
||||
doc/source/docs/type/char/iso646string.rst
|
||||
doc/source/docs/type/char/numericstring.rst
|
||||
doc/source/docs/type/char/printablestring.rst
|
||||
doc/source/docs/type/char/t61string.rst
|
||||
doc/source/docs/type/char/teletexstring.rst
|
||||
doc/source/docs/type/char/universalstring.rst
|
||||
doc/source/docs/type/char/utf8string.rst
|
||||
doc/source/docs/type/char/videotexstring.rst
|
||||
doc/source/docs/type/char/visiblestring.rst
|
||||
doc/source/docs/type/namedtype/contents.rst
|
||||
doc/source/docs/type/namedtype/defaultednamedtype.rst
|
||||
doc/source/docs/type/namedtype/namedtype.rst
|
||||
doc/source/docs/type/namedtype/namedtypes.rst
|
||||
doc/source/docs/type/namedtype/optionalnamedtype.rst
|
||||
doc/source/docs/type/namedval/contents.rst
|
||||
doc/source/docs/type/namedval/namedval.rst
|
||||
doc/source/docs/type/tag/contents.rst
|
||||
doc/source/docs/type/tag/tag.rst
|
||||
doc/source/docs/type/tag/tagmap.rst
|
||||
doc/source/docs/type/tag/tagset.rst
|
||||
doc/source/docs/type/univ/any.rst
|
||||
doc/source/docs/type/univ/bitstring.rst
|
||||
doc/source/docs/type/univ/boolean.rst
|
||||
doc/source/docs/type/univ/choice.rst
|
||||
doc/source/docs/type/univ/contents.rst
|
||||
doc/source/docs/type/univ/enumerated.rst
|
||||
doc/source/docs/type/univ/integer.rst
|
||||
doc/source/docs/type/univ/null.rst
|
||||
doc/source/docs/type/univ/objectidentifier.rst
|
||||
doc/source/docs/type/univ/octetstring.rst
|
||||
doc/source/docs/type/univ/real.rst
|
||||
doc/source/docs/type/univ/sequence.rst
|
||||
doc/source/docs/type/univ/sequenceof.rst
|
||||
doc/source/docs/type/univ/set.rst
|
||||
doc/source/docs/type/univ/setof.rst
|
||||
doc/source/docs/type/useful/contents.rst
|
||||
doc/source/docs/type/useful/generalizedtime.rst
|
||||
doc/source/docs/type/useful/objectdescriptor.rst
|
||||
doc/source/docs/type/useful/utctime.rst
|
||||
pyasn1/__init__.py
|
||||
pyasn1/debug.py
|
||||
pyasn1/error.py
|
||||
@ -31,8 +80,16 @@ pyasn1/codec/cer/encoder.py
|
||||
pyasn1/codec/der/__init__.py
|
||||
pyasn1/codec/der/decoder.py
|
||||
pyasn1/codec/der/encoder.py
|
||||
pyasn1/codec/native/__init__.py
|
||||
pyasn1/codec/native/decoder.py
|
||||
pyasn1/codec/native/encoder.py
|
||||
pyasn1/compat/__init__.py
|
||||
pyasn1/compat/binary.py
|
||||
pyasn1/compat/calling.py
|
||||
pyasn1/compat/dateandtime.py
|
||||
pyasn1/compat/integer.py
|
||||
pyasn1/compat/octets.py
|
||||
pyasn1/compat/string.py
|
||||
pyasn1/type/__init__.py
|
||||
pyasn1/type/base.py
|
||||
pyasn1/type/char.py
|
||||
@ -44,25 +101,39 @@ pyasn1/type/tag.py
|
||||
pyasn1/type/tagmap.py
|
||||
pyasn1/type/univ.py
|
||||
pyasn1/type/useful.py
|
||||
test/__init__.py
|
||||
test/suite.py
|
||||
test/codec/__init__.py
|
||||
test/codec/suite.py
|
||||
test/codec/ber/__init__.py
|
||||
test/codec/ber/suite.py
|
||||
test/codec/ber/test_decoder.py
|
||||
test/codec/ber/test_encoder.py
|
||||
test/codec/cer/__init__.py
|
||||
test/codec/cer/suite.py
|
||||
test/codec/cer/test_decoder.py
|
||||
test/codec/cer/test_encoder.py
|
||||
test/codec/der/__init__.py
|
||||
test/codec/der/suite.py
|
||||
test/codec/der/test_decoder.py
|
||||
test/codec/der/test_encoder.py
|
||||
test/type/__init__.py
|
||||
test/type/suite.py
|
||||
test/type/test_constraint.py
|
||||
test/type/test_namedtype.py
|
||||
test/type/test_tag.py
|
||||
test/type/test_univ.py
|
||||
tests/__init__.py
|
||||
tests/__main__.py
|
||||
tests/base.py
|
||||
tests/test_debug.py
|
||||
tests/codec/__init__.py
|
||||
tests/codec/__main__.py
|
||||
tests/codec/ber/__init__.py
|
||||
tests/codec/ber/__main__.py
|
||||
tests/codec/ber/test_decoder.py
|
||||
tests/codec/ber/test_encoder.py
|
||||
tests/codec/cer/__init__.py
|
||||
tests/codec/cer/__main__.py
|
||||
tests/codec/cer/test_decoder.py
|
||||
tests/codec/cer/test_encoder.py
|
||||
tests/codec/der/__init__.py
|
||||
tests/codec/der/__main__.py
|
||||
tests/codec/der/test_decoder.py
|
||||
tests/codec/der/test_encoder.py
|
||||
tests/codec/native/__init__.py
|
||||
tests/codec/native/__main__.py
|
||||
tests/codec/native/test_decoder.py
|
||||
tests/codec/native/test_encoder.py
|
||||
tests/compat/__init__.py
|
||||
tests/compat/__main__.py
|
||||
tests/compat/test_binary.py
|
||||
tests/compat/test_integer.py
|
||||
tests/compat/test_octets.py
|
||||
tests/type/__init__.py
|
||||
tests/type/__main__.py
|
||||
tests/type/test_char.py
|
||||
tests/type/test_constraint.py
|
||||
tests/type/test_namedtype.py
|
||||
tests/type/test_namedval.py
|
||||
tests/type/test_tag.py
|
||||
tests/type/test_univ.py
|
||||
tests/type/test_useful.py
|
5
third_party/python/pyasn1/pyasn1/__init__.py
vendored
5
third_party/python/pyasn1/pyasn1/__init__.py
vendored
@ -1,8 +1,7 @@
|
||||
import sys
|
||||
|
||||
# http://www.python.org/dev/peps/pep-0396/
|
||||
__version__ = '0.1.7'
|
||||
__version__ = '0.3.7'
|
||||
|
||||
if sys.version_info[:2] < (2, 4):
|
||||
raise RuntimeError('PyASN1 requires Python 2.4 or later')
|
||||
|
||||
raise RuntimeError('PyASN1 requires Python 2.4 or later')
|
||||
|
1386
third_party/python/pyasn1/pyasn1/codec/ber/decoder.py
vendored
1386
third_party/python/pyasn1/pyasn1/codec/ber/decoder.py
vendored
File diff suppressed because it is too large
Load Diff
@ -1,229 +1,344 @@
|
||||
# BER encoder
|
||||
from pyasn1.type import base, tag, univ, char, useful
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from pyasn1.type import tag, univ, char, useful
|
||||
from pyasn1.codec.ber import eoo
|
||||
from pyasn1.compat.octets import int2oct, oct2int, ints2octs, null, str2octs
|
||||
from pyasn1.compat.integer import to_bytes
|
||||
from pyasn1 import debug, error
|
||||
|
||||
class Error(Exception): pass
|
||||
__all__ = ['encode']
|
||||
|
||||
class AbstractItemEncoder:
|
||||
|
||||
class AbstractItemEncoder(object):
|
||||
supportIndefLenMode = 1
|
||||
def encodeTag(self, t, isConstructed):
|
||||
tagClass, tagFormat, tagId = t.asTuple() # this is a hotspot
|
||||
v = tagClass | tagFormat
|
||||
|
||||
# An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)`
|
||||
eooIntegerSubstrate = (0, 0)
|
||||
eooOctetsSubstrate = ints2octs(eooIntegerSubstrate)
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
def encodeTag(self, singleTag, isConstructed):
|
||||
tagClass, tagFormat, tagId = singleTag
|
||||
encodedTag = tagClass | tagFormat
|
||||
if isConstructed:
|
||||
v = v|tag.tagFormatConstructed
|
||||
encodedTag |= tag.tagFormatConstructed
|
||||
if tagId < 31:
|
||||
return int2oct(v|tagId)
|
||||
return encodedTag | tagId,
|
||||
else:
|
||||
s = int2oct(tagId&0x7f)
|
||||
tagId = tagId >> 7
|
||||
substrate = tagId & 0x7f,
|
||||
tagId >>= 7
|
||||
while tagId:
|
||||
s = int2oct(0x80|(tagId&0x7f)) + s
|
||||
tagId = tagId >> 7
|
||||
return int2oct(v|0x1F) + s
|
||||
substrate = (0x80 | (tagId & 0x7f),) + substrate
|
||||
tagId >>= 7
|
||||
return (encodedTag | 0x1F,) + substrate
|
||||
|
||||
def encodeLength(self, length, defMode):
|
||||
if not defMode and self.supportIndefLenMode:
|
||||
return int2oct(0x80)
|
||||
return (0x80,)
|
||||
if length < 0x80:
|
||||
return int2oct(length)
|
||||
return length,
|
||||
else:
|
||||
substrate = null
|
||||
substrate = ()
|
||||
while length:
|
||||
substrate = int2oct(length&0xff) + substrate
|
||||
length = length >> 8
|
||||
substrate = (length & 0xff,) + substrate
|
||||
length >>= 8
|
||||
substrateLen = len(substrate)
|
||||
if substrateLen > 126:
|
||||
raise Error('Length octets overflow (%d)' % substrateLen)
|
||||
return int2oct(0x80 | substrateLen) + substrate
|
||||
raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen)
|
||||
return (0x80 | substrateLen,) + substrate
|
||||
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
raise Error('Not implemented')
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
raise error.PyAsn1Error('Not implemented')
|
||||
|
||||
def _encodeEndOfOctets(self, encodeFun, defMode):
|
||||
if defMode or not self.supportIndefLenMode:
|
||||
return null
|
||||
else:
|
||||
return encodeFun(eoo.endOfOctets, defMode)
|
||||
|
||||
def encode(self, encodeFun, value, defMode, maxChunkSize):
|
||||
substrate, isConstructed = self.encodeValue(
|
||||
encodeFun, value, defMode, maxChunkSize
|
||||
def encode(self, value, encodeFun, **options):
|
||||
|
||||
tagSet = value.tagSet
|
||||
|
||||
# untagged item?
|
||||
if not tagSet:
|
||||
substrate, isConstructed, isOctets = self.encodeValue(
|
||||
value, encodeFun, **options
|
||||
)
|
||||
tagSet = value.getTagSet()
|
||||
if tagSet:
|
||||
if not isConstructed: # primitive form implies definite mode
|
||||
defMode = 1
|
||||
return self.encodeTag(
|
||||
tagSet[-1], isConstructed
|
||||
) + self.encodeLength(
|
||||
len(substrate), defMode
|
||||
) + substrate + self._encodeEndOfOctets(encodeFun, defMode)
|
||||
else:
|
||||
return substrate # untagged value
|
||||
return substrate
|
||||
|
||||
defMode = options.get('defMode', True)
|
||||
|
||||
for idx, singleTag in enumerate(tagSet.superTags):
|
||||
|
||||
defModeOverride = defMode
|
||||
|
||||
# base tag?
|
||||
if not idx:
|
||||
substrate, isConstructed, isOctets = self.encodeValue(
|
||||
value, encodeFun, **options
|
||||
)
|
||||
|
||||
if options.get('ifNotEmpty', False) and not substrate:
|
||||
return substrate
|
||||
|
||||
# primitive form implies definite mode
|
||||
if not isConstructed:
|
||||
defModeOverride = True
|
||||
|
||||
header = self.encodeTag(singleTag, isConstructed)
|
||||
header += self.encodeLength(len(substrate), defModeOverride)
|
||||
|
||||
if isOctets:
|
||||
substrate = ints2octs(header) + substrate
|
||||
|
||||
if not defModeOverride:
|
||||
substrate += self.eooOctetsSubstrate
|
||||
|
||||
else:
|
||||
substrate = header + substrate
|
||||
|
||||
if not defModeOverride:
|
||||
substrate += self.eooIntegerSubstrate
|
||||
|
||||
if not isOctets:
|
||||
substrate = ints2octs(substrate)
|
||||
|
||||
return substrate
|
||||
|
||||
|
||||
class EndOfOctetsEncoder(AbstractItemEncoder):
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
return null, 0
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
return null, False, True
|
||||
|
||||
class ExplicitlyTaggedItemEncoder(AbstractItemEncoder):
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
if isinstance(value, base.AbstractConstructedAsn1Item):
|
||||
value = value.clone(tagSet=value.getTagSet()[:-1],
|
||||
cloneValueFlag=1)
|
||||
else:
|
||||
value = value.clone(tagSet=value.getTagSet()[:-1])
|
||||
return encodeFun(value, defMode, maxChunkSize), 1
|
||||
|
||||
explicitlyTaggedItemEncoder = ExplicitlyTaggedItemEncoder()
|
||||
|
||||
class BooleanEncoder(AbstractItemEncoder):
|
||||
supportIndefLenMode = 0
|
||||
_true = ints2octs((1,))
|
||||
_false = ints2octs((0,))
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
return value and self._true or self._false, 0
|
||||
supportIndefLenMode = False
|
||||
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
return value and (1,) or (0,), False, False
|
||||
|
||||
|
||||
class IntegerEncoder(AbstractItemEncoder):
|
||||
supportIndefLenMode = 0
|
||||
supportIndefLenMode = False
|
||||
supportCompactZero = False
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
if value == 0: # shortcut for zero value
|
||||
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
if value == 0:
|
||||
# de-facto way to encode zero
|
||||
if self.supportCompactZero:
|
||||
# this seems to be a correct way for encoding zeros
|
||||
return null, 0
|
||||
return (), False, False
|
||||
else:
|
||||
# this seems to be a widespread way for encoding zeros
|
||||
return ints2octs((0,)), 0
|
||||
octets = []
|
||||
value = int(value) # to save on ops on asn1 type
|
||||
while 1:
|
||||
octets.insert(0, value & 0xff)
|
||||
if value == 0 or value == -1:
|
||||
break
|
||||
value = value >> 8
|
||||
if value == 0 and octets[0] & 0x80:
|
||||
octets.insert(0, 0)
|
||||
while len(octets) > 1 and \
|
||||
(octets[0] == 0 and octets[1] & 0x80 == 0 or \
|
||||
octets[0] == 0xff and octets[1] & 0x80 != 0):
|
||||
del octets[0]
|
||||
return ints2octs(octets), 0
|
||||
return (0,), False, False
|
||||
|
||||
return to_bytes(int(value), signed=True), False, True
|
||||
|
||||
|
||||
class BitStringEncoder(AbstractItemEncoder):
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
if not maxChunkSize or len(value) <= maxChunkSize*8:
|
||||
r = {}; l = len(value); p = 0; j = 7
|
||||
while p < l:
|
||||
i, j = divmod(p, 8)
|
||||
r[i] = r.get(i,0) | value[p]<<(7-j)
|
||||
p = p + 1
|
||||
keys = list(r); keys.sort()
|
||||
return int2oct(7-j) + ints2octs([r[k] for k in keys]), 0
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
valueLength = len(value)
|
||||
if valueLength % 8:
|
||||
alignedValue = value << (8 - valueLength % 8)
|
||||
else:
|
||||
pos = 0; substrate = null
|
||||
while 1:
|
||||
# count in octets
|
||||
v = value.clone(value[pos*8:pos*8+maxChunkSize*8])
|
||||
if not v:
|
||||
break
|
||||
substrate = substrate + encodeFun(v, defMode, maxChunkSize)
|
||||
pos = pos + maxChunkSize
|
||||
return substrate, 1
|
||||
alignedValue = value
|
||||
|
||||
maxChunkSize = options.get('maxChunkSize', 0)
|
||||
if not maxChunkSize or len(alignedValue) <= maxChunkSize * 8:
|
||||
substrate = alignedValue.asOctets()
|
||||
return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True
|
||||
|
||||
# strip off explicit tags
|
||||
alignedValue = alignedValue.clone(
|
||||
tagSet=tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
|
||||
)
|
||||
|
||||
stop = 0
|
||||
substrate = null
|
||||
while stop < valueLength:
|
||||
start = stop
|
||||
stop = min(start + maxChunkSize * 8, valueLength)
|
||||
substrate += encodeFun(alignedValue[start:stop], **options)
|
||||
|
||||
return substrate, True, True
|
||||
|
||||
|
||||
class OctetStringEncoder(AbstractItemEncoder):
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
maxChunkSize = options.get('maxChunkSize', 0)
|
||||
if not maxChunkSize or len(value) <= maxChunkSize:
|
||||
return value.asOctets(), 0
|
||||
return value.asOctets(), False, True
|
||||
|
||||
else:
|
||||
pos = 0; substrate = null
|
||||
while 1:
|
||||
v = value.clone(value[pos:pos+maxChunkSize])
|
||||
if not v:
|
||||
# will strip off explicit tags
|
||||
baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
|
||||
|
||||
pos = 0
|
||||
substrate = null
|
||||
while True:
|
||||
chunk = value.clone(value[pos:pos + maxChunkSize],
|
||||
tagSet=baseTagSet)
|
||||
if not chunk:
|
||||
break
|
||||
substrate = substrate + encodeFun(v, defMode, maxChunkSize)
|
||||
pos = pos + maxChunkSize
|
||||
return substrate, 1
|
||||
substrate += encodeFun(chunk, **options)
|
||||
pos += maxChunkSize
|
||||
|
||||
return substrate, True, True
|
||||
|
||||
|
||||
class NullEncoder(AbstractItemEncoder):
|
||||
supportIndefLenMode = 0
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
return null, 0
|
||||
supportIndefLenMode = False
|
||||
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
return null, False, True
|
||||
|
||||
|
||||
class ObjectIdentifierEncoder(AbstractItemEncoder):
|
||||
supportIndefLenMode = 0
|
||||
precomputedValues = {
|
||||
(1, 3, 6, 1, 2): (43, 6, 1, 2),
|
||||
(1, 3, 6, 1, 4): (43, 6, 1, 4)
|
||||
}
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
supportIndefLenMode = False
|
||||
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
oid = value.asTuple()
|
||||
if oid[:5] in self.precomputedValues:
|
||||
octets = self.precomputedValues[oid[:5]]
|
||||
index = 5
|
||||
else:
|
||||
if len(oid) < 2:
|
||||
raise error.PyAsn1Error('Short OID %s' % (value,))
|
||||
|
||||
# Build the first twos
|
||||
if oid[0] > 6 or oid[1] > 39 or oid[0] == 6 and oid[1] > 15:
|
||||
raise error.PyAsn1Error(
|
||||
'Initial sub-ID overflow %s in OID %s' % (oid[:2], value)
|
||||
)
|
||||
octets = (oid[0] * 40 + oid[1],)
|
||||
index = 2
|
||||
# Build the first pair
|
||||
try:
|
||||
first = oid[0]
|
||||
second = oid[1]
|
||||
|
||||
# Cycle through subids
|
||||
for subid in oid[index:]:
|
||||
if subid > -1 and subid < 128:
|
||||
# Optimize for the common case
|
||||
octets = octets + (subid & 0x7f,)
|
||||
elif subid < 0 or subid > 0xFFFFFFFF:
|
||||
raise error.PyAsn1Error(
|
||||
'SubId overflow %s in %s' % (subid, value)
|
||||
)
|
||||
except IndexError:
|
||||
raise error.PyAsn1Error('Short OID %s' % (value,))
|
||||
|
||||
if 0 <= second <= 39:
|
||||
if first == 1:
|
||||
oid = (second + 40,) + oid[2:]
|
||||
elif first == 0:
|
||||
oid = (second,) + oid[2:]
|
||||
elif first == 2:
|
||||
oid = (second + 80,) + oid[2:]
|
||||
else:
|
||||
raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,))
|
||||
elif first == 2:
|
||||
oid = (second + 80,) + oid[2:]
|
||||
else:
|
||||
raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,))
|
||||
|
||||
octets = ()
|
||||
|
||||
# Cycle through subIds
|
||||
for subOid in oid:
|
||||
if 0 <= subOid <= 127:
|
||||
# Optimize for the common case
|
||||
octets += (subOid,)
|
||||
elif subOid > 127:
|
||||
# Pack large Sub-Object IDs
|
||||
res = (subid & 0x7f,)
|
||||
subid = subid >> 7
|
||||
while subid > 0:
|
||||
res = (0x80 | (subid & 0x7f),) + res
|
||||
subid = subid >> 7
|
||||
res = (subOid & 0x7f,)
|
||||
subOid >>= 7
|
||||
while subOid:
|
||||
res = (0x80 | (subOid & 0x7f),) + res
|
||||
subOid >>= 7
|
||||
# Add packed Sub-Object ID to resulted Object ID
|
||||
octets += res
|
||||
|
||||
return ints2octs(octets), 0
|
||||
else:
|
||||
raise error.PyAsn1Error('Negative OID arc %s at %s' % (subOid, value))
|
||||
|
||||
return octets, False, False
|
||||
|
||||
|
||||
class RealEncoder(AbstractItemEncoder):
|
||||
supportIndefLenMode = 0
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
if value.isPlusInfinity():
|
||||
return int2oct(0x40), 0
|
||||
if value.isMinusInfinity():
|
||||
return int2oct(0x41), 0
|
||||
binEncBase = 2 # set to None to choose encoding base automatically
|
||||
|
||||
@staticmethod
|
||||
def _dropFloatingPoint(m, encbase, e):
|
||||
ms, es = 1, 1
|
||||
if m < 0:
|
||||
ms = -1 # mantissa sign
|
||||
if e < 0:
|
||||
es = -1 # exponenta sign
|
||||
m *= ms
|
||||
if encbase == 8:
|
||||
m *= 2 ** (abs(e) % 3 * es)
|
||||
e = abs(e) // 3 * es
|
||||
elif encbase == 16:
|
||||
m *= 2 ** (abs(e) % 4 * es)
|
||||
e = abs(e) // 4 * es
|
||||
|
||||
while True:
|
||||
if int(m) != m:
|
||||
m *= encbase
|
||||
e -= 1
|
||||
continue
|
||||
break
|
||||
return ms, int(m), encbase, e
|
||||
|
||||
def _chooseEncBase(self, value):
|
||||
m, b, e = value
|
||||
encBase = [2, 8, 16]
|
||||
if value.binEncBase in encBase:
|
||||
return self._dropFloatingPoint(m, value.binEncBase, e)
|
||||
elif self.binEncBase in encBase:
|
||||
return self._dropFloatingPoint(m, self.binEncBase, e)
|
||||
# auto choosing base 2/8/16
|
||||
mantissa = [m, m, m]
|
||||
exponenta = [e, e, e]
|
||||
sign = 1
|
||||
encbase = 2
|
||||
e = float('inf')
|
||||
for i in range(3):
|
||||
(sign,
|
||||
mantissa[i],
|
||||
encBase[i],
|
||||
exponenta[i]) = self._dropFloatingPoint(mantissa[i], encBase[i], exponenta[i])
|
||||
if abs(exponenta[i]) < abs(e) or (abs(exponenta[i]) == abs(e) and mantissa[i] < m):
|
||||
e = exponenta[i]
|
||||
m = int(mantissa[i])
|
||||
encbase = encBase[i]
|
||||
return sign, m, encbase, e
|
||||
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
if value.isPlusInf:
|
||||
return (0x40,), False, False
|
||||
if value.isMinusInf:
|
||||
return (0x41,), False, False
|
||||
m, b, e = value
|
||||
if not m:
|
||||
return null, 0
|
||||
return null, False, True
|
||||
if b == 10:
|
||||
return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0
|
||||
return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), False, True
|
||||
elif b == 2:
|
||||
fo = 0x80 # binary enoding
|
||||
if m < 0:
|
||||
fo = fo | 0x40 # sign bit
|
||||
m = -m
|
||||
while int(m) != m: # drop floating point
|
||||
m *= 2
|
||||
e -= 1
|
||||
while m & 0x1 == 0: # mantissa normalization
|
||||
fo = 0x80 # binary encoding
|
||||
ms, m, encbase, e = self._chooseEncBase(value)
|
||||
if ms < 0: # mantissa sign
|
||||
fo |= 0x40 # sign bit
|
||||
# exponenta & mantissa normalization
|
||||
if encbase == 2:
|
||||
while m & 0x1 == 0:
|
||||
m >>= 1
|
||||
e += 1
|
||||
elif encbase == 8:
|
||||
while m & 0x7 == 0:
|
||||
m >>= 3
|
||||
e += 1
|
||||
fo |= 0x10
|
||||
else: # encbase = 16
|
||||
while m & 0xf == 0:
|
||||
m >>= 4
|
||||
e += 1
|
||||
fo |= 0x20
|
||||
sf = 0 # scale factor
|
||||
while m & 0x1 == 0:
|
||||
m >>= 1
|
||||
e += 1
|
||||
sf += 1
|
||||
if sf > 3:
|
||||
raise error.PyAsn1Error('Scale factor overflow') # bug if raised
|
||||
fo |= sf << 2
|
||||
eo = null
|
||||
while e not in (0, -1):
|
||||
eo = int2oct(e&0xff) + eo
|
||||
e >>= 8
|
||||
if e == 0 and eo and oct2int(eo[0]) & 0x80:
|
||||
eo = int2oct(0) + eo
|
||||
if e == 0 or e == -1:
|
||||
eo = int2oct(e & 0xff)
|
||||
else:
|
||||
while e not in (0, -1):
|
||||
eo = int2oct(e & 0xff) + eo
|
||||
e >>= 8
|
||||
if e == 0 and eo and oct2int(eo[0]) & 0x80:
|
||||
eo = int2oct(0) + eo
|
||||
if e == -1 and eo and not (oct2int(eo[0]) & 0x80):
|
||||
eo = int2oct(0xff) + eo
|
||||
n = len(eo)
|
||||
if n > 0xff:
|
||||
raise error.PyAsn1Error('Real exponent overflow')
|
||||
@ -235,51 +350,57 @@ class RealEncoder(AbstractItemEncoder):
|
||||
fo |= 2
|
||||
else:
|
||||
fo |= 3
|
||||
eo = int2oct(n//0xff+1) + eo
|
||||
eo = int2oct(n & 0xff) + eo
|
||||
po = null
|
||||
while m:
|
||||
po = int2oct(m&0xff) + po
|
||||
po = int2oct(m & 0xff) + po
|
||||
m >>= 8
|
||||
substrate = int2oct(fo) + eo + po
|
||||
return substrate, 0
|
||||
return substrate, False, True
|
||||
else:
|
||||
raise error.PyAsn1Error('Prohibited Real base %s' % b)
|
||||
|
||||
|
||||
class SequenceEncoder(AbstractItemEncoder):
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
value.setDefaultComponents()
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
value.verifySizeSpec()
|
||||
substrate = null; idx = len(value)
|
||||
|
||||
namedTypes = value.componentType
|
||||
substrate = null
|
||||
|
||||
idx = len(value)
|
||||
while idx > 0:
|
||||
idx = idx - 1
|
||||
if value[idx] is None: # Optional component
|
||||
continue
|
||||
component = value.getDefaultComponentByPosition(idx)
|
||||
if component is not None and component == value[idx]:
|
||||
continue
|
||||
substrate = encodeFun(
|
||||
value[idx], defMode, maxChunkSize
|
||||
) + substrate
|
||||
return substrate, 1
|
||||
idx -= 1
|
||||
if namedTypes:
|
||||
if namedTypes[idx].isOptional and not value[idx].isValue:
|
||||
continue
|
||||
if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object:
|
||||
continue
|
||||
substrate = encodeFun(value[idx], **options) + substrate
|
||||
|
||||
return substrate, True, True
|
||||
|
||||
|
||||
class SequenceOfEncoder(AbstractItemEncoder):
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
value.verifySizeSpec()
|
||||
substrate = null; idx = len(value)
|
||||
substrate = null
|
||||
idx = len(value)
|
||||
while idx > 0:
|
||||
idx = idx - 1
|
||||
substrate = encodeFun(
|
||||
value[idx], defMode, maxChunkSize
|
||||
) + substrate
|
||||
return substrate, 1
|
||||
idx -= 1
|
||||
substrate = encodeFun(value[idx], **options) + substrate
|
||||
return substrate, True, True
|
||||
|
||||
|
||||
class ChoiceEncoder(AbstractItemEncoder):
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
return encodeFun(value.getComponent(), defMode, maxChunkSize), 1
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
return encodeFun(value.getComponent(), **options), True, True
|
||||
|
||||
|
||||
class AnyEncoder(OctetStringEncoder):
|
||||
def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
|
||||
return value.asOctets(), defMode == 0
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
return value.asOctets(), not options.get('defMode', True), True
|
||||
|
||||
|
||||
tagMap = {
|
||||
eoo.endOfOctets.tagSet: EndOfOctetsEncoder(),
|
||||
@ -308,46 +429,120 @@ tagMap = {
|
||||
char.UniversalString.tagSet: OctetStringEncoder(),
|
||||
char.BMPString.tagSet: OctetStringEncoder(),
|
||||
# useful types
|
||||
useful.ObjectDescriptor.tagSet: OctetStringEncoder(),
|
||||
useful.GeneralizedTime.tagSet: OctetStringEncoder(),
|
||||
useful.UTCTime.tagSet: OctetStringEncoder()
|
||||
}
|
||||
useful.UTCTime.tagSet: OctetStringEncoder()
|
||||
}
|
||||
|
||||
# Type-to-codec map for ambiguous ASN.1 types
|
||||
# Put in ambiguous & non-ambiguous types for faster codec lookup
|
||||
typeMap = {
|
||||
univ.Boolean.typeId: BooleanEncoder(),
|
||||
univ.Integer.typeId: IntegerEncoder(),
|
||||
univ.BitString.typeId: BitStringEncoder(),
|
||||
univ.OctetString.typeId: OctetStringEncoder(),
|
||||
univ.Null.typeId: NullEncoder(),
|
||||
univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(),
|
||||
univ.Enumerated.typeId: IntegerEncoder(),
|
||||
univ.Real.typeId: RealEncoder(),
|
||||
# Sequence & Set have same tags as SequenceOf & SetOf
|
||||
univ.Set.typeId: SequenceEncoder(),
|
||||
univ.SetOf.typeId: SequenceOfEncoder(),
|
||||
univ.Sequence.typeId: SequenceEncoder(),
|
||||
univ.SequenceOf.typeId: SequenceOfEncoder(),
|
||||
univ.Choice.typeId: ChoiceEncoder(),
|
||||
univ.Any.typeId: AnyEncoder()
|
||||
}
|
||||
univ.Any.typeId: AnyEncoder(),
|
||||
# character string types
|
||||
char.UTF8String.typeId: OctetStringEncoder(),
|
||||
char.NumericString.typeId: OctetStringEncoder(),
|
||||
char.PrintableString.typeId: OctetStringEncoder(),
|
||||
char.TeletexString.typeId: OctetStringEncoder(),
|
||||
char.VideotexString.typeId: OctetStringEncoder(),
|
||||
char.IA5String.typeId: OctetStringEncoder(),
|
||||
char.GraphicString.typeId: OctetStringEncoder(),
|
||||
char.VisibleString.typeId: OctetStringEncoder(),
|
||||
char.GeneralString.typeId: OctetStringEncoder(),
|
||||
char.UniversalString.typeId: OctetStringEncoder(),
|
||||
char.BMPString.typeId: OctetStringEncoder(),
|
||||
# useful types
|
||||
useful.ObjectDescriptor.typeId: OctetStringEncoder(),
|
||||
useful.GeneralizedTime.typeId: OctetStringEncoder(),
|
||||
useful.UTCTime.typeId: OctetStringEncoder()
|
||||
}
|
||||
|
||||
class Encoder:
|
||||
|
||||
class Encoder(object):
|
||||
fixedDefLengthMode = None
|
||||
fixedChunkSize = None
|
||||
|
||||
# noinspection PyDefaultArgument
|
||||
def __init__(self, tagMap, typeMap={}):
|
||||
self.__tagMap = tagMap
|
||||
self.__typeMap = typeMap
|
||||
|
||||
def __call__(self, value, defMode=1, maxChunkSize=0):
|
||||
debug.logger & debug.flagEncoder and debug.logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.__class__.__name__, value.prettyPrint()))
|
||||
tagSet = value.getTagSet()
|
||||
if len(tagSet) > 1:
|
||||
concreteEncoder = explicitlyTaggedItemEncoder
|
||||
def __call__(self, value, **options):
|
||||
|
||||
if debug.logger & debug.flagEncoder:
|
||||
logger = debug.logger
|
||||
else:
|
||||
if value.typeId is not None and value.typeId in self.__typeMap:
|
||||
concreteEncoder = self.__typeMap[value.typeId]
|
||||
elif tagSet in self.__tagMap:
|
||||
concreteEncoder = self.__tagMap[tagSet]
|
||||
else:
|
||||
tagSet = value.baseTagSet
|
||||
if tagSet in self.__tagMap:
|
||||
concreteEncoder = self.__tagMap[tagSet]
|
||||
else:
|
||||
raise Error('No encoder for %s' % (value,))
|
||||
debug.logger & debug.flagEncoder and debug.logger('using value codec %s chosen by %r' % (concreteEncoder.__class__.__name__, tagSet))
|
||||
substrate = concreteEncoder.encode(
|
||||
self, value, defMode, maxChunkSize
|
||||
)
|
||||
debug.logger & debug.flagEncoder and debug.logger('built %s octets of substrate: %s\nencoder completed' % (len(substrate), debug.hexdump(substrate)))
|
||||
logger = None
|
||||
|
||||
if logger:
|
||||
logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), value.prettyPrintType(), value.prettyPrint()))
|
||||
|
||||
if self.fixedDefLengthMode is not None:
|
||||
options.update(defMode=self.fixedDefLengthMode)
|
||||
|
||||
if self.fixedChunkSize is not None:
|
||||
options.update(maxChunkSize=self.fixedChunkSize)
|
||||
|
||||
tagSet = value.tagSet
|
||||
|
||||
try:
|
||||
concreteEncoder = self.__typeMap[value.typeId]
|
||||
|
||||
except KeyError:
|
||||
# use base type for codec lookup to recover untagged types
|
||||
baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
|
||||
|
||||
try:
|
||||
concreteEncoder = self.__tagMap[baseTagSet]
|
||||
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('No encoder for %s' % (value,))
|
||||
|
||||
if logger:
|
||||
logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
|
||||
|
||||
substrate = concreteEncoder.encode(value, self, **options)
|
||||
|
||||
if logger:
|
||||
logger('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate)))
|
||||
|
||||
return substrate
|
||||
|
||||
#: Turns ASN.1 object into BER octet stream.
|
||||
#:
|
||||
#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: walks all its components recursively and produces a BER octet stream.
|
||||
#:
|
||||
#: Parameters
|
||||
#: ----------
|
||||
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: A pyasn1 object to encode
|
||||
#:
|
||||
#: defMode: :py:class:`bool`
|
||||
#: If `False`, produces indefinite length encoding
|
||||
#:
|
||||
#: maxChunkSize: :py:class:`int`
|
||||
#: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
|
||||
#:
|
||||
#: Returns
|
||||
#: -------
|
||||
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
||||
#: Given ASN.1 object encoded into BER octetstream
|
||||
#:
|
||||
#: Raises
|
||||
#: ------
|
||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
||||
#: On encoding errors
|
||||
encode = Encoder(tagMap, typeMap)
|
||||
|
@ -1,8 +1,25 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from pyasn1.type import base, tag
|
||||
|
||||
|
||||
class EndOfOctets(base.AbstractSimpleAsn1Item):
|
||||
defaultValue = 0
|
||||
tagSet = tag.initTagSet(
|
||||
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x00)
|
||||
)
|
||||
)
|
||||
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if cls._instance is None:
|
||||
cls._instance = object.__new__(cls, *args, **kwargs)
|
||||
|
||||
return cls._instance
|
||||
|
||||
|
||||
endOfOctets = EndOfOctets()
|
||||
|
@ -1,16 +1,27 @@
|
||||
# CER decoder
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from pyasn1.type import univ
|
||||
from pyasn1.codec.ber import decoder
|
||||
from pyasn1.compat.octets import oct2int
|
||||
from pyasn1 import error
|
||||
|
||||
__all__ = ['decode']
|
||||
|
||||
|
||||
class BooleanDecoder(decoder.AbstractSimpleDecoder):
|
||||
protoComponent = univ.Boolean(0)
|
||||
def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
|
||||
state, decodeFun, substrateFun):
|
||||
|
||||
def valueDecoder(self, substrate, asn1Spec,
|
||||
tagSet=None, length=None, state=None,
|
||||
decodeFun=None, substrateFun=None,
|
||||
**options):
|
||||
head, tail = substrate[:length], substrate[length:]
|
||||
if not head:
|
||||
raise error.PyAsn1Error('Empty substrate')
|
||||
if not head or length != 1:
|
||||
raise error.PyAsn1Error('Not single-octet Boolean payload')
|
||||
byte = oct2int(head[0])
|
||||
# CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while
|
||||
# BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1
|
||||
@ -20,16 +31,60 @@ class BooleanDecoder(decoder.AbstractSimpleDecoder):
|
||||
elif byte == 0x00:
|
||||
value = 0
|
||||
else:
|
||||
raise error.PyAsn1Error('Boolean CER violation: %s' % byte)
|
||||
raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte)
|
||||
return self._createComponent(asn1Spec, tagSet, value), tail
|
||||
|
||||
# TODO: prohibit non-canonical encoding
|
||||
BitStringDecoder = decoder.BitStringDecoder
|
||||
OctetStringDecoder = decoder.OctetStringDecoder
|
||||
RealDecoder = decoder.RealDecoder
|
||||
|
||||
tagMap = decoder.tagMap.copy()
|
||||
tagMap.update({
|
||||
univ.Boolean.tagSet: BooleanDecoder()
|
||||
})
|
||||
tagMap.update(
|
||||
{univ.Boolean.tagSet: BooleanDecoder(),
|
||||
univ.BitString.tagSet: BitStringDecoder(),
|
||||
univ.OctetString.tagSet: OctetStringDecoder(),
|
||||
univ.Real.tagSet: RealDecoder()}
|
||||
)
|
||||
|
||||
typeMap = decoder.typeMap
|
||||
typeMap = decoder.typeMap.copy()
|
||||
|
||||
class Decoder(decoder.Decoder): pass
|
||||
# Put in non-ambiguous types for faster codec lookup
|
||||
for typeDecoder in tagMap.values():
|
||||
if typeDecoder.protoComponent is not None:
|
||||
typeId = typeDecoder.protoComponent.__class__.typeId
|
||||
if typeId is not None and typeId not in typeMap:
|
||||
typeMap[typeId] = typeDecoder
|
||||
|
||||
|
||||
class Decoder(decoder.Decoder):
|
||||
pass
|
||||
|
||||
|
||||
#: Turns CER octet stream into an ASN.1 object.
|
||||
#:
|
||||
#: Takes CER octetstream and decode it into an ASN.1 object
|
||||
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
|
||||
#: may be a scalar or an arbitrary nested structure.
|
||||
#:
|
||||
#: Parameters
|
||||
#: ----------
|
||||
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
||||
#: CER octetstream
|
||||
#:
|
||||
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
|
||||
#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure
|
||||
#: being decoded, *asn1Spec* may or may not be required. Most common reason for
|
||||
#: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode.
|
||||
#:
|
||||
#: Returns
|
||||
#: -------
|
||||
#: : :py:class:`tuple`
|
||||
#: A tuple of pyasn1 object recovered from CER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: and the unprocessed trailing portion of the *substrate* (may be empty)
|
||||
#:
|
||||
#: Raises
|
||||
#: ------
|
||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
||||
#: On decoding errors
|
||||
decode = Decoder(tagMap, decoder.typeMap)
|
||||
|
@ -1,87 +1,221 @@
|
||||
# CER encoder
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from pyasn1.type import univ
|
||||
from pyasn1.type import useful
|
||||
from pyasn1.codec.ber import encoder
|
||||
from pyasn1.compat.octets import int2oct, null
|
||||
from pyasn1.compat.octets import str2octs, null
|
||||
from pyasn1 import error
|
||||
|
||||
__all__ = ['encode']
|
||||
|
||||
|
||||
class BooleanEncoder(encoder.IntegerEncoder):
|
||||
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
|
||||
if client == 0:
|
||||
substrate = int2oct(0)
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
if value == 0:
|
||||
substrate = (0,)
|
||||
else:
|
||||
substrate = int2oct(255)
|
||||
return substrate, 0
|
||||
substrate = (255,)
|
||||
return substrate, False, False
|
||||
|
||||
class BitStringEncoder(encoder.BitStringEncoder):
|
||||
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
|
||||
return encoder.BitStringEncoder.encodeValue(
|
||||
self, encodeFun, client, defMode, 1000
|
||||
)
|
||||
|
||||
class OctetStringEncoder(encoder.OctetStringEncoder):
|
||||
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
|
||||
return encoder.OctetStringEncoder.encodeValue(
|
||||
self, encodeFun, client, defMode, 1000
|
||||
)
|
||||
class RealEncoder(encoder.RealEncoder):
|
||||
def _chooseEncBase(self, value):
|
||||
m, b, e = value
|
||||
return self._dropFloatingPoint(m, b, e)
|
||||
|
||||
|
||||
# specialized RealEncoder here
|
||||
# specialized GeneralStringEncoder here
|
||||
# specialized GeneralizedTimeEncoder here
|
||||
# specialized UTCTimeEncoder here
|
||||
|
||||
class TimeEncoderMixIn(object):
|
||||
zchar, = str2octs('Z')
|
||||
pluschar, = str2octs('+')
|
||||
minuschar, = str2octs('-')
|
||||
commachar, = str2octs(',')
|
||||
minLength = 12
|
||||
maxLength = 19
|
||||
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
# Encoding constraints:
|
||||
# - minutes are mandatory, seconds are optional
|
||||
# - subseconds must NOT be zero
|
||||
# - no hanging fraction dot
|
||||
# - time in UTC (Z)
|
||||
# - only dot is allowed for fractions
|
||||
|
||||
octets = value.asOctets()
|
||||
|
||||
if not self.minLength < len(octets) < self.maxLength:
|
||||
raise error.PyAsn1Error('Length constraint violated: %r' % value)
|
||||
|
||||
if self.pluschar in octets or self.minuschar in octets:
|
||||
raise error.PyAsn1Error('Must be UTC time: %r' % octets)
|
||||
|
||||
if octets[-1] != self.zchar:
|
||||
raise error.PyAsn1Error('Missing "Z" time zone specifier: %r' % octets)
|
||||
|
||||
if self.commachar in octets:
|
||||
raise error.PyAsn1Error('Comma in fractions disallowed: %r' % value)
|
||||
|
||||
options.update(maxChunkSize=1000)
|
||||
|
||||
return encoder.OctetStringEncoder.encodeValue(
|
||||
self, value, encodeFun, **options
|
||||
)
|
||||
|
||||
|
||||
class GeneralizedTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder):
|
||||
minLength = 12
|
||||
maxLength = 19
|
||||
|
||||
|
||||
class UTCTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder):
|
||||
minLength = 10
|
||||
maxLength = 14
|
||||
|
||||
|
||||
class SetOfEncoder(encoder.SequenceOfEncoder):
|
||||
def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
|
||||
if isinstance(client, univ.SequenceAndSetBase):
|
||||
client.setDefaultComponents()
|
||||
client.verifySizeSpec()
|
||||
substrate = null; idx = len(client)
|
||||
# This is certainly a hack but how else do I distinguish SetOf
|
||||
# from Set if they have the same tags&constraints?
|
||||
if isinstance(client, univ.SequenceAndSetBase):
|
||||
# Set
|
||||
@staticmethod
|
||||
def _sortComponents(components):
|
||||
# sort by tags regardless of the Choice value (static sort)
|
||||
return sorted(components, key=lambda x: isinstance(x, univ.Choice) and x.minTagSet or x.tagSet)
|
||||
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
value.verifySizeSpec()
|
||||
substrate = null
|
||||
idx = len(value)
|
||||
if value.typeId == univ.Set.typeId:
|
||||
namedTypes = value.componentType
|
||||
comps = []
|
||||
compsMap = {}
|
||||
while idx > 0:
|
||||
idx = idx - 1
|
||||
if client[idx] is None: # Optional component
|
||||
continue
|
||||
if client.getDefaultComponentByPosition(idx) == client[idx]:
|
||||
continue
|
||||
comps.append(client[idx])
|
||||
comps.sort(key=lambda x: isinstance(x, univ.Choice) and \
|
||||
x.getMinTagSet() or x.getTagSet())
|
||||
for c in comps:
|
||||
substrate += encodeFun(c, defMode, maxChunkSize)
|
||||
idx -= 1
|
||||
if namedTypes:
|
||||
if namedTypes[idx].isOptional and not value[idx].isValue:
|
||||
continue
|
||||
if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object:
|
||||
continue
|
||||
|
||||
comps.append(value[idx])
|
||||
compsMap[id(value[idx])] = namedTypes and namedTypes[idx].isOptional
|
||||
|
||||
for comp in self._sortComponents(comps):
|
||||
options.update(ifNotEmpty=compsMap[id(comp)])
|
||||
substrate += encodeFun(comp, **options)
|
||||
else:
|
||||
# SetOf
|
||||
compSubs = []
|
||||
while idx > 0:
|
||||
idx = idx - 1
|
||||
compSubs.append(
|
||||
encodeFun(client[idx], defMode, maxChunkSize)
|
||||
)
|
||||
compSubs.sort() # perhaps padding's not needed
|
||||
substrate = null
|
||||
for compSub in compSubs:
|
||||
substrate += compSub
|
||||
return substrate, 1
|
||||
components = [encodeFun(x, **options) for x in value]
|
||||
|
||||
# sort by serialized and padded components
|
||||
if len(components) > 1:
|
||||
zero = str2octs('\x00')
|
||||
maxLen = max(map(len, components))
|
||||
paddedComponents = [
|
||||
(x.ljust(maxLen, zero), x) for x in components
|
||||
]
|
||||
paddedComponents.sort(key=lambda x: x[0])
|
||||
|
||||
components = [x[1] for x in paddedComponents]
|
||||
|
||||
substrate = null.join(components)
|
||||
|
||||
return substrate, True, True
|
||||
|
||||
|
||||
class SequenceEncoder(encoder.SequenceEncoder):
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
value.verifySizeSpec()
|
||||
|
||||
namedTypes = value.componentType
|
||||
substrate = null
|
||||
|
||||
idx = len(value)
|
||||
while idx > 0:
|
||||
idx -= 1
|
||||
if namedTypes:
|
||||
if namedTypes[idx].isOptional and not value[idx].isValue:
|
||||
continue
|
||||
if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object:
|
||||
continue
|
||||
|
||||
options.update(ifNotEmpty=namedTypes and namedTypes[idx].isOptional)
|
||||
|
||||
substrate = encodeFun(value[idx], **options) + substrate
|
||||
|
||||
return substrate, True, True
|
||||
|
||||
|
||||
class SequenceOfEncoder(encoder.SequenceOfEncoder):
|
||||
def encodeValue(self, value, encodeFun, **options):
|
||||
substrate = null
|
||||
idx = len(value)
|
||||
|
||||
if options.get('ifNotEmpty', False) and not idx:
|
||||
return substrate, True, True
|
||||
|
||||
value.verifySizeSpec()
|
||||
while idx > 0:
|
||||
idx -= 1
|
||||
substrate = encodeFun(value[idx], **options) + substrate
|
||||
return substrate, True, True
|
||||
|
||||
|
||||
tagMap = encoder.tagMap.copy()
|
||||
tagMap.update({
|
||||
univ.Boolean.tagSet: BooleanEncoder(),
|
||||
univ.BitString.tagSet: BitStringEncoder(),
|
||||
univ.OctetString.tagSet: OctetStringEncoder(),
|
||||
univ.SetOf().tagSet: SetOfEncoder() # conflcts with Set
|
||||
})
|
||||
univ.Real.tagSet: RealEncoder(),
|
||||
useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(),
|
||||
useful.UTCTime.tagSet: UTCTimeEncoder(),
|
||||
# Sequence & Set have same tags as SequenceOf & SetOf
|
||||
univ.SetOf.tagSet: SetOfEncoder(),
|
||||
univ.Sequence.typeId: SequenceEncoder()
|
||||
})
|
||||
|
||||
typeMap = encoder.typeMap.copy()
|
||||
typeMap.update({
|
||||
univ.Boolean.typeId: BooleanEncoder(),
|
||||
univ.Real.typeId: RealEncoder(),
|
||||
useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(),
|
||||
useful.UTCTime.typeId: UTCTimeEncoder(),
|
||||
# Sequence & Set have same tags as SequenceOf & SetOf
|
||||
univ.Set.typeId: SetOfEncoder(),
|
||||
univ.SetOf.typeId: SetOfEncoder()
|
||||
})
|
||||
univ.SetOf.typeId: SetOfEncoder(),
|
||||
univ.Sequence.typeId: SequenceEncoder(),
|
||||
univ.SequenceOf.typeId: SequenceOfEncoder()
|
||||
})
|
||||
|
||||
|
||||
class Encoder(encoder.Encoder):
|
||||
def __call__(self, client, defMode=0, maxChunkSize=0):
|
||||
return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
|
||||
fixedDefLengthMode = False
|
||||
fixedChunkSize = 1000
|
||||
|
||||
#: Turns ASN.1 object into CER octet stream.
|
||||
#:
|
||||
#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: walks all its components recursively and produces a CER octet stream.
|
||||
#:
|
||||
#: Parameters
|
||||
#: ----------
|
||||
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: A pyasn1 object to encode
|
||||
#:
|
||||
#: defMode: :py:class:`bool`
|
||||
#: If `False`, produces indefinite length encoding
|
||||
#:
|
||||
#: maxChunkSize: :py:class:`int`
|
||||
#: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
|
||||
#:
|
||||
#: Returns
|
||||
#: -------
|
||||
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
||||
#: Given ASN.1 object encoded into BER octetstream
|
||||
#:
|
||||
#: Raises
|
||||
#: ------
|
||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
||||
#: On encoding errors
|
||||
encode = Encoder(tagMap, typeMap)
|
||||
|
||||
# EncoderFactory queries class instance and builds a map of tags -> encoders
|
||||
|
@ -1,9 +1,70 @@
|
||||
# DER decoder
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from pyasn1.type import univ
|
||||
from pyasn1.codec.cer import decoder
|
||||
|
||||
tagMap = decoder.tagMap
|
||||
typeMap = decoder.typeMap
|
||||
Decoder = decoder.Decoder
|
||||
__all__ = ['decode']
|
||||
|
||||
|
||||
class BitStringDecoder(decoder.BitStringDecoder):
|
||||
supportConstructedForm = False
|
||||
|
||||
|
||||
class OctetStringDecoder(decoder.OctetStringDecoder):
|
||||
supportConstructedForm = False
|
||||
|
||||
# TODO: prohibit non-canonical encoding
|
||||
RealDecoder = decoder.RealDecoder
|
||||
|
||||
tagMap = decoder.tagMap.copy()
|
||||
tagMap.update(
|
||||
{univ.BitString.tagSet: BitStringDecoder(),
|
||||
univ.OctetString.tagSet: OctetStringDecoder(),
|
||||
univ.Real.tagSet: RealDecoder()}
|
||||
)
|
||||
|
||||
typeMap = decoder.typeMap.copy()
|
||||
|
||||
# Put in non-ambiguous types for faster codec lookup
|
||||
for typeDecoder in tagMap.values():
|
||||
if typeDecoder.protoComponent is not None:
|
||||
typeId = typeDecoder.protoComponent.__class__.typeId
|
||||
if typeId is not None and typeId not in typeMap:
|
||||
typeMap[typeId] = typeDecoder
|
||||
|
||||
|
||||
class Decoder(decoder.Decoder):
|
||||
supportIndefLength = False
|
||||
|
||||
|
||||
#: Turns DER octet stream into an ASN.1 object.
|
||||
#:
|
||||
#: Takes DER octetstream and decode it into an ASN.1 object
|
||||
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
|
||||
#: may be a scalar or an arbitrary nested structure.
|
||||
#:
|
||||
#: Parameters
|
||||
#: ----------
|
||||
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
||||
#: DER octetstream
|
||||
#:
|
||||
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
|
||||
#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure
|
||||
#: being decoded, *asn1Spec* may or may not be required. Most common reason for
|
||||
#: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode.
|
||||
#:
|
||||
#: Returns
|
||||
#: -------
|
||||
#: : :py:class:`tuple`
|
||||
#: A tuple of pyasn1 object recovered from DER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: and the unprocessed trailing portion of the *substrate* (may be empty)
|
||||
#:
|
||||
#: Raises
|
||||
#: ------
|
||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
||||
#: On decoding errors
|
||||
decode = Decoder(tagMap, typeMap)
|
||||
|
@ -1,28 +1,62 @@
|
||||
# DER encoder
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from pyasn1.type import univ
|
||||
from pyasn1.codec.cer import encoder
|
||||
|
||||
__all__ = ['encode']
|
||||
|
||||
|
||||
class SetOfEncoder(encoder.SetOfEncoder):
|
||||
def _cmpSetComponents(self, c1, c2):
|
||||
tagSet1 = isinstance(c1, univ.Choice) and \
|
||||
c1.getEffectiveTagSet() or c1.getTagSet()
|
||||
tagSet2 = isinstance(c2, univ.Choice) and \
|
||||
c2.getEffectiveTagSet() or c2.getTagSet()
|
||||
return cmp(tagSet1, tagSet2)
|
||||
@staticmethod
|
||||
def _sortComponents(components):
|
||||
# sort by tags depending on the actual Choice value (dynamic sort)
|
||||
return sorted(components, key=lambda x: isinstance(x, univ.Choice) and x.getComponent().tagSet or x.tagSet)
|
||||
|
||||
tagMap = encoder.tagMap.copy()
|
||||
tagMap.update({
|
||||
# Overload CER encodrs with BER ones (a bit hackerish XXX)
|
||||
univ.BitString.tagSet: encoder.encoder.BitStringEncoder(),
|
||||
univ.OctetString.tagSet: encoder.encoder.OctetStringEncoder(),
|
||||
# Set & SetOf have same tags
|
||||
univ.SetOf().tagSet: SetOfEncoder()
|
||||
})
|
||||
univ.SetOf.tagSet: SetOfEncoder()
|
||||
})
|
||||
|
||||
typeMap = encoder.typeMap.copy()
|
||||
typeMap.update({
|
||||
# Set & SetOf have same tags
|
||||
univ.Set.typeId: SetOfEncoder(),
|
||||
univ.SetOf.typeId: SetOfEncoder()
|
||||
})
|
||||
|
||||
typeMap = encoder.typeMap
|
||||
|
||||
class Encoder(encoder.Encoder):
|
||||
def __call__(self, client, defMode=1, maxChunkSize=0):
|
||||
return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
|
||||
|
||||
fixedDefLengthMode = True
|
||||
fixedChunkSize = 0
|
||||
|
||||
#: Turns ASN.1 object into DER octet stream.
|
||||
#:
|
||||
#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: walks all its components recursively and produces a DER octet stream.
|
||||
#:
|
||||
#: Parameters
|
||||
#: ----------
|
||||
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: A pyasn1 object to encode
|
||||
#:
|
||||
#: defMode: :py:class:`bool`
|
||||
#: If `False`, produces indefinite length encoding
|
||||
#:
|
||||
#: maxChunkSize: :py:class:`int`
|
||||
#: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
|
||||
#:
|
||||
#: Returns
|
||||
#: -------
|
||||
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
||||
#: Given ASN.1 object encoded into BER octetstream
|
||||
#:
|
||||
#: Raises
|
||||
#: ------
|
||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
||||
#: On encoding errors
|
||||
encode = Encoder(tagMap, typeMap)
|
||||
|
194
third_party/python/pyasn1/pyasn1/codec/native/decoder.py
vendored
Normal file
194
third_party/python/pyasn1/pyasn1/codec/native/decoder.py
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from pyasn1.type import base, univ, char, useful, tag
|
||||
from pyasn1 import debug, error
|
||||
|
||||
__all__ = ['decode']
|
||||
|
||||
|
||||
class AbstractScalarDecoder(object):
|
||||
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
|
||||
return asn1Spec.clone(pyObject)
|
||||
|
||||
|
||||
class BitStringDecoder(AbstractScalarDecoder):
|
||||
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
|
||||
return asn1Spec.clone(univ.BitString.fromBinaryString(pyObject))
|
||||
|
||||
|
||||
class SequenceOrSetDecoder(object):
|
||||
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
|
||||
asn1Value = asn1Spec.clone()
|
||||
|
||||
componentsTypes = asn1Spec.componentType
|
||||
|
||||
for field in asn1Value:
|
||||
if field in pyObject:
|
||||
asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options)
|
||||
|
||||
return asn1Value
|
||||
|
||||
|
||||
class SequenceOfOrSetOfDecoder(object):
|
||||
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
|
||||
asn1Value = asn1Spec.clone()
|
||||
|
||||
for pyValue in pyObject:
|
||||
asn1Value.append(decodeFun(pyValue, asn1Spec.componentType), **options)
|
||||
|
||||
return asn1Value
|
||||
|
||||
|
||||
class ChoiceDecoder(object):
|
||||
def __call__(self, pyObject, asn1Spec, decodeFun=None, **options):
|
||||
asn1Value = asn1Spec.clone()
|
||||
|
||||
componentsTypes = asn1Spec.componentType
|
||||
|
||||
for field in pyObject:
|
||||
if field in componentsTypes:
|
||||
asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options)
|
||||
break
|
||||
|
||||
return asn1Value
|
||||
|
||||
|
||||
tagMap = {
|
||||
univ.Integer.tagSet: AbstractScalarDecoder(),
|
||||
univ.Boolean.tagSet: AbstractScalarDecoder(),
|
||||
univ.BitString.tagSet: BitStringDecoder(),
|
||||
univ.OctetString.tagSet: AbstractScalarDecoder(),
|
||||
univ.Null.tagSet: AbstractScalarDecoder(),
|
||||
univ.ObjectIdentifier.tagSet: AbstractScalarDecoder(),
|
||||
univ.Enumerated.tagSet: AbstractScalarDecoder(),
|
||||
univ.Real.tagSet: AbstractScalarDecoder(),
|
||||
univ.Sequence.tagSet: SequenceOrSetDecoder(), # conflicts with SequenceOf
|
||||
univ.Set.tagSet: SequenceOrSetDecoder(), # conflicts with SetOf
|
||||
univ.Choice.tagSet: ChoiceDecoder(), # conflicts with Any
|
||||
# character string types
|
||||
char.UTF8String.tagSet: AbstractScalarDecoder(),
|
||||
char.NumericString.tagSet: AbstractScalarDecoder(),
|
||||
char.PrintableString.tagSet: AbstractScalarDecoder(),
|
||||
char.TeletexString.tagSet: AbstractScalarDecoder(),
|
||||
char.VideotexString.tagSet: AbstractScalarDecoder(),
|
||||
char.IA5String.tagSet: AbstractScalarDecoder(),
|
||||
char.GraphicString.tagSet: AbstractScalarDecoder(),
|
||||
char.VisibleString.tagSet: AbstractScalarDecoder(),
|
||||
char.GeneralString.tagSet: AbstractScalarDecoder(),
|
||||
char.UniversalString.tagSet: AbstractScalarDecoder(),
|
||||
char.BMPString.tagSet: AbstractScalarDecoder(),
|
||||
# useful types
|
||||
useful.ObjectDescriptor.tagSet: AbstractScalarDecoder(),
|
||||
useful.GeneralizedTime.tagSet: AbstractScalarDecoder(),
|
||||
useful.UTCTime.tagSet: AbstractScalarDecoder()
|
||||
}
|
||||
|
||||
# Put in ambiguous & non-ambiguous types for faster codec lookup
|
||||
typeMap = {
|
||||
univ.Integer.typeId: AbstractScalarDecoder(),
|
||||
univ.Boolean.typeId: AbstractScalarDecoder(),
|
||||
univ.BitString.typeId: BitStringDecoder(),
|
||||
univ.OctetString.typeId: AbstractScalarDecoder(),
|
||||
univ.Null.typeId: AbstractScalarDecoder(),
|
||||
univ.ObjectIdentifier.typeId: AbstractScalarDecoder(),
|
||||
univ.Enumerated.typeId: AbstractScalarDecoder(),
|
||||
univ.Real.typeId: AbstractScalarDecoder(),
|
||||
# ambiguous base types
|
||||
univ.Set.typeId: SequenceOrSetDecoder(),
|
||||
univ.SetOf.typeId: SequenceOfOrSetOfDecoder(),
|
||||
univ.Sequence.typeId: SequenceOrSetDecoder(),
|
||||
univ.SequenceOf.typeId: SequenceOfOrSetOfDecoder(),
|
||||
univ.Choice.typeId: ChoiceDecoder(),
|
||||
univ.Any.typeId: AbstractScalarDecoder(),
|
||||
# character string types
|
||||
char.UTF8String.typeId: AbstractScalarDecoder(),
|
||||
char.NumericString.typeId: AbstractScalarDecoder(),
|
||||
char.PrintableString.typeId: AbstractScalarDecoder(),
|
||||
char.TeletexString.typeId: AbstractScalarDecoder(),
|
||||
char.VideotexString.typeId: AbstractScalarDecoder(),
|
||||
char.IA5String.typeId: AbstractScalarDecoder(),
|
||||
char.GraphicString.typeId: AbstractScalarDecoder(),
|
||||
char.VisibleString.typeId: AbstractScalarDecoder(),
|
||||
char.GeneralString.typeId: AbstractScalarDecoder(),
|
||||
char.UniversalString.typeId: AbstractScalarDecoder(),
|
||||
char.BMPString.typeId: AbstractScalarDecoder(),
|
||||
# useful types
|
||||
useful.ObjectDescriptor.typeId: AbstractScalarDecoder(),
|
||||
useful.GeneralizedTime.typeId: AbstractScalarDecoder(),
|
||||
useful.UTCTime.typeId: AbstractScalarDecoder()
|
||||
}
|
||||
|
||||
|
||||
class Decoder(object):
|
||||
|
||||
# noinspection PyDefaultArgument
|
||||
def __init__(self, tagMap, typeMap):
|
||||
self.__tagMap = tagMap
|
||||
self.__typeMap = typeMap
|
||||
|
||||
def __call__(self, pyObject, asn1Spec, **options):
|
||||
if debug.logger & debug.flagDecoder:
|
||||
logger = debug.logger
|
||||
else:
|
||||
logger = None
|
||||
if logger:
|
||||
debug.scope.push(type(pyObject).__name__)
|
||||
logger('decoder called at scope %s, working with type %s' % (debug.scope, type(pyObject).__name__))
|
||||
|
||||
if asn1Spec is None or not isinstance(asn1Spec, base.Asn1Item):
|
||||
raise error.PyAsn1Error('asn1Spec is not valid (should be an instance of an ASN.1 Item, not %s)' % asn1Spec.__class__.__name__)
|
||||
|
||||
try:
|
||||
valueDecoder = self.__typeMap[asn1Spec.typeId]
|
||||
|
||||
except KeyError:
|
||||
# use base type for codec lookup to recover untagged types
|
||||
baseTagSet = tag.TagSet(asn1Spec.tagSet.baseTag, asn1Spec.tagSet.baseTag)
|
||||
|
||||
try:
|
||||
valueDecoder = self.__tagMap[baseTagSet]
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('Unknown ASN.1 tag %s' % asn1Spec.tagSet)
|
||||
|
||||
if logger:
|
||||
logger('calling decoder %s on Python type %s <%s>' % (type(valueDecoder).__name__, type(pyObject).__name__, repr(pyObject)))
|
||||
|
||||
value = valueDecoder(pyObject, asn1Spec, self, **options)
|
||||
|
||||
if logger:
|
||||
logger('decoder %s produced ASN.1 type %s <%s>' % (type(valueDecoder).__name__, type(value).__name__, repr(value)))
|
||||
debug.scope.pop()
|
||||
|
||||
return value
|
||||
|
||||
|
||||
#: Turns Python objects of built-in types into ASN.1 objects.
|
||||
#:
|
||||
#: Takes Python objects of built-in types and turns them into a tree of
|
||||
#: ASN.1 objects (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
|
||||
#: may be a scalar or an arbitrary nested structure.
|
||||
#:
|
||||
#: Parameters
|
||||
#: ----------
|
||||
#: pyObject: :py:class:`object`
|
||||
#: A scalar or nested Python objects
|
||||
#:
|
||||
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
|
||||
#: A pyasn1 type object to act as a template guiding the decoder. It is required
|
||||
#: for successful interpretation of Python objects mapping into their ASN.1
|
||||
#: representations.
|
||||
#:
|
||||
#: Returns
|
||||
#: -------
|
||||
#: : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
|
||||
#: A scalar or constructed pyasn1 object
|
||||
#:
|
||||
#: Raises
|
||||
#: ------
|
||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
||||
#: On decoding errors
|
||||
decode = Decoder(tagMap, typeMap)
|
212
third_party/python/pyasn1/pyasn1/codec/native/encoder.py
vendored
Normal file
212
third_party/python/pyasn1/pyasn1/codec/native/encoder.py
vendored
Normal file
@ -0,0 +1,212 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
|
||||
except ImportError:
|
||||
OrderedDict = dict
|
||||
|
||||
from pyasn1.type import base, univ, tag, char, useful
|
||||
from pyasn1 import debug, error
|
||||
|
||||
__all__ = ['encode']
|
||||
|
||||
|
||||
class AbstractItemEncoder(object):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
raise error.PyAsn1Error('Not implemented')
|
||||
|
||||
|
||||
class BooleanEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return bool(value)
|
||||
|
||||
|
||||
class IntegerEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return int(value)
|
||||
|
||||
|
||||
class BitStringEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return str(value)
|
||||
|
||||
|
||||
class OctetStringEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return value.asOctets()
|
||||
|
||||
|
||||
class TextStringEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return value.prettyPrint()
|
||||
|
||||
|
||||
class NullEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return None
|
||||
|
||||
|
||||
class ObjectIdentifierEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return str(value)
|
||||
|
||||
|
||||
class RealEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return float(value)
|
||||
|
||||
|
||||
class SetEncoder(AbstractItemEncoder):
|
||||
protoDict = dict
|
||||
|
||||
def encode(self, value, encodeFun, **options):
|
||||
value.verifySizeSpec()
|
||||
|
||||
namedTypes = value.componentType
|
||||
substrate = self.protoDict()
|
||||
|
||||
for idx, (key, subValue) in enumerate(value.items()):
|
||||
if namedTypes and namedTypes[idx].isOptional and not value[idx].isValue:
|
||||
continue
|
||||
substrate[key] = encodeFun(subValue, **options)
|
||||
return substrate
|
||||
|
||||
|
||||
class SequenceEncoder(SetEncoder):
|
||||
protoDict = OrderedDict
|
||||
|
||||
|
||||
class SequenceOfEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
value.verifySizeSpec()
|
||||
return [encodeFun(x, **options) for x in value]
|
||||
|
||||
|
||||
class ChoiceEncoder(SequenceEncoder):
|
||||
pass
|
||||
|
||||
|
||||
class AnyEncoder(AbstractItemEncoder):
|
||||
def encode(self, value, encodeFun, **options):
|
||||
return value.asOctets()
|
||||
|
||||
|
||||
tagMap = {
|
||||
univ.Boolean.tagSet: BooleanEncoder(),
|
||||
univ.Integer.tagSet: IntegerEncoder(),
|
||||
univ.BitString.tagSet: BitStringEncoder(),
|
||||
univ.OctetString.tagSet: OctetStringEncoder(),
|
||||
univ.Null.tagSet: NullEncoder(),
|
||||
univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(),
|
||||
univ.Enumerated.tagSet: IntegerEncoder(),
|
||||
univ.Real.tagSet: RealEncoder(),
|
||||
# Sequence & Set have same tags as SequenceOf & SetOf
|
||||
univ.SequenceOf.tagSet: SequenceOfEncoder(),
|
||||
univ.SetOf.tagSet: SequenceOfEncoder(),
|
||||
univ.Choice.tagSet: ChoiceEncoder(),
|
||||
# character string types
|
||||
char.UTF8String.tagSet: TextStringEncoder(),
|
||||
char.NumericString.tagSet: TextStringEncoder(),
|
||||
char.PrintableString.tagSet: TextStringEncoder(),
|
||||
char.TeletexString.tagSet: TextStringEncoder(),
|
||||
char.VideotexString.tagSet: TextStringEncoder(),
|
||||
char.IA5String.tagSet: TextStringEncoder(),
|
||||
char.GraphicString.tagSet: TextStringEncoder(),
|
||||
char.VisibleString.tagSet: TextStringEncoder(),
|
||||
char.GeneralString.tagSet: TextStringEncoder(),
|
||||
char.UniversalString.tagSet: TextStringEncoder(),
|
||||
char.BMPString.tagSet: TextStringEncoder(),
|
||||
# useful types
|
||||
useful.ObjectDescriptor.tagSet: OctetStringEncoder(),
|
||||
useful.GeneralizedTime.tagSet: OctetStringEncoder(),
|
||||
useful.UTCTime.tagSet: OctetStringEncoder()
|
||||
}
|
||||
|
||||
# Type-to-codec map for ambiguous ASN.1 types
|
||||
typeMap = {
|
||||
univ.Set.typeId: SetEncoder(),
|
||||
univ.SetOf.typeId: SequenceOfEncoder(),
|
||||
univ.Sequence.typeId: SequenceEncoder(),
|
||||
univ.SequenceOf.typeId: SequenceOfEncoder(),
|
||||
univ.Choice.typeId: ChoiceEncoder(),
|
||||
univ.Any.typeId: AnyEncoder()
|
||||
}
|
||||
|
||||
|
||||
class Encoder(object):
|
||||
|
||||
# noinspection PyDefaultArgument
|
||||
def __init__(self, tagMap, typeMap={}):
|
||||
self.__tagMap = tagMap
|
||||
self.__typeMap = typeMap
|
||||
|
||||
def __call__(self, value, **options):
|
||||
if not isinstance(value, base.Asn1Item):
|
||||
raise error.PyAsn1Error('value is not valid (should be an instance of an ASN.1 Item)')
|
||||
|
||||
if debug.logger & debug.flagEncoder:
|
||||
logger = debug.logger
|
||||
else:
|
||||
logger = None
|
||||
|
||||
if logger:
|
||||
debug.scope.push(type(value).__name__)
|
||||
logger('encoder called for type %s <%s>' % (type(value).__name__, value.prettyPrint()))
|
||||
|
||||
tagSet = value.tagSet
|
||||
|
||||
try:
|
||||
concreteEncoder = self.__typeMap[value.typeId]
|
||||
|
||||
except KeyError:
|
||||
# use base type for codec lookup to recover untagged types
|
||||
baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
|
||||
|
||||
try:
|
||||
concreteEncoder = self.__tagMap[baseTagSet]
|
||||
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('No encoder for %s' % (value,))
|
||||
|
||||
if logger:
|
||||
logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
|
||||
|
||||
pyObject = concreteEncoder.encode(value, self, **options)
|
||||
|
||||
if logger:
|
||||
logger('encoder %s produced: %s' % (type(concreteEncoder).__name__, repr(pyObject)))
|
||||
debug.scope.pop()
|
||||
|
||||
return pyObject
|
||||
|
||||
|
||||
#: Turns ASN.1 object into a Python built-in type object(s).
|
||||
#:
|
||||
#: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: walks all its components recursively and produces a Python built-in type or a tree
|
||||
#: of those.
|
||||
#:
|
||||
#: One exception is that instead of :py:class:`dict`, the :py:class:`OrderedDict`
|
||||
#: can be produced (whenever available) to preserve ordering of the components
|
||||
#: in ASN.1 SEQUENCE.
|
||||
#:
|
||||
#: Parameters
|
||||
#: ----------
|
||||
# asn1Value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||
#: pyasn1 object to encode (or a tree of them)
|
||||
#:
|
||||
#: Returns
|
||||
#: -------
|
||||
#: : :py:class:`object`
|
||||
#: Python built-in type instance (or a tree of them)
|
||||
#:
|
||||
#: Raises
|
||||
#: ------
|
||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
||||
#: On encoding errors
|
||||
encode = Encoder(tagMap, typeMap)
|
33
third_party/python/pyasn1/pyasn1/compat/binary.py
vendored
Normal file
33
third_party/python/pyasn1/pyasn1/compat/binary.py
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from sys import version_info
|
||||
|
||||
if version_info[0:2] < (2, 6):
|
||||
def bin(value):
|
||||
bitstring = []
|
||||
|
||||
if value > 0:
|
||||
prefix = '0b'
|
||||
elif value < 0:
|
||||
prefix = '-0b'
|
||||
value = abs(value)
|
||||
else:
|
||||
prefix = '0b0'
|
||||
|
||||
while value:
|
||||
if value & 1 == 1:
|
||||
bitstring.append('1')
|
||||
else:
|
||||
bitstring.append('0')
|
||||
|
||||
value >>= 1
|
||||
|
||||
bitstring.reverse()
|
||||
|
||||
return prefix + ''.join(bitstring)
|
||||
else:
|
||||
bin = bin
|
20
third_party/python/pyasn1/pyasn1/compat/calling.py
vendored
Normal file
20
third_party/python/pyasn1/pyasn1/compat/calling.py
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from sys import version_info
|
||||
|
||||
__all__ = ['callable']
|
||||
|
||||
|
||||
if (2, 7) < version_info[:2] < (3, 2):
|
||||
import collections
|
||||
|
||||
def callable(x):
|
||||
return isinstance(x, collections.Callable)
|
||||
|
||||
else:
|
||||
|
||||
callable = callable
|
22
third_party/python/pyasn1/pyasn1/compat/dateandtime.py
vendored
Normal file
22
third_party/python/pyasn1/pyasn1/compat/dateandtime.py
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from sys import version_info
|
||||
from datetime import datetime
|
||||
import time
|
||||
|
||||
__all__ = ['strptime']
|
||||
|
||||
|
||||
if version_info[:2] <= (2, 4):
|
||||
|
||||
def strptime(text, dateFormat):
|
||||
return datetime(*(time.strptime(text, dateFormat)[0:6]))
|
||||
|
||||
else:
|
||||
|
||||
def strptime(text, dateFormat):
|
||||
return datetime.strptime(text, dateFormat)
|
108
third_party/python/pyasn1/pyasn1/compat/integer.py
vendored
Normal file
108
third_party/python/pyasn1/pyasn1/compat/integer.py
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
import sys
|
||||
try:
|
||||
import platform
|
||||
implementation = platform.python_implementation()
|
||||
|
||||
except (ImportError, AttributeError):
|
||||
implementation = 'CPython'
|
||||
|
||||
from pyasn1.compat.octets import oct2int, null, ensureString
|
||||
|
||||
if sys.version_info[0:2] < (3, 2) or implementation != 'CPython':
|
||||
from binascii import a2b_hex, b2a_hex
|
||||
|
||||
if sys.version_info[0] > 2:
|
||||
long = int
|
||||
|
||||
def from_bytes(octets, signed=False):
|
||||
if not octets:
|
||||
return 0
|
||||
|
||||
value = long(b2a_hex(ensureString(octets)), 16)
|
||||
|
||||
if signed and oct2int(octets[0]) & 0x80:
|
||||
return value - (1 << len(octets) * 8)
|
||||
|
||||
return value
|
||||
|
||||
def to_bytes(value, signed=False, length=0):
|
||||
if value < 0:
|
||||
if signed:
|
||||
bits = bitLength(value)
|
||||
|
||||
# two's complement form
|
||||
maxValue = 1 << bits
|
||||
valueToEncode = (value + maxValue) % maxValue
|
||||
|
||||
else:
|
||||
raise OverflowError('can\'t convert negative int to unsigned')
|
||||
elif value == 0 and length == 0:
|
||||
return null
|
||||
else:
|
||||
bits = 0
|
||||
valueToEncode = value
|
||||
|
||||
hexValue = hex(valueToEncode)[2:]
|
||||
if hexValue.endswith('L'):
|
||||
hexValue = hexValue[:-1]
|
||||
|
||||
if len(hexValue) & 1:
|
||||
hexValue = '0' + hexValue
|
||||
|
||||
# padding may be needed for two's complement encoding
|
||||
if value != valueToEncode or length:
|
||||
hexLength = len(hexValue) * 4
|
||||
|
||||
padLength = max(length, bits)
|
||||
|
||||
if padLength > hexLength:
|
||||
hexValue = '00' * ((padLength - hexLength - 1) // 8 + 1) + hexValue
|
||||
elif length and hexLength - length > 7:
|
||||
raise OverflowError('int too big to convert')
|
||||
|
||||
firstOctet = int(hexValue[:2], 16)
|
||||
|
||||
if signed:
|
||||
if firstOctet & 0x80:
|
||||
if value >= 0:
|
||||
hexValue = '00' + hexValue
|
||||
elif value < 0:
|
||||
hexValue = 'ff' + hexValue
|
||||
|
||||
octets_value = a2b_hex(hexValue)
|
||||
|
||||
return octets_value
|
||||
|
||||
def bitLength(number):
|
||||
# bits in unsigned number
|
||||
hexValue = hex(abs(number))
|
||||
bits = len(hexValue) - 2
|
||||
if hexValue.endswith('L'):
|
||||
bits -= 1
|
||||
if bits & 1:
|
||||
bits += 1
|
||||
bits *= 4
|
||||
# TODO: strip lhs zeros
|
||||
return bits
|
||||
|
||||
else:
|
||||
|
||||
def from_bytes(octets, signed=False):
|
||||
return int.from_bytes(bytes(octets), 'big', signed=signed)
|
||||
|
||||
def to_bytes(value, signed=False, length=0):
|
||||
length = max(value.bit_length(), length)
|
||||
|
||||
if signed and length % 8 == 0:
|
||||
length += 1
|
||||
|
||||
return value.to_bytes(length // 8 + (length % 8 and 1 or 0), 'big', signed=signed)
|
||||
|
||||
def bitLength(number):
|
||||
return int(number).bit_length()
|
@ -1,20 +1,46 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from sys import version_info
|
||||
|
||||
if version_info[0] <= 2:
|
||||
int2oct = chr
|
||||
ints2octs = lambda s: ''.join([ int2oct(x) for x in s ])
|
||||
# noinspection PyPep8
|
||||
ints2octs = lambda s: ''.join([int2oct(x) for x in s])
|
||||
null = ''
|
||||
oct2int = ord
|
||||
octs2ints = lambda s: [ oct2int(x) for x in s ]
|
||||
# TODO: refactor to return a sequence of ints
|
||||
# noinspection PyPep8
|
||||
octs2ints = lambda s: [oct2int(x) for x in s]
|
||||
# noinspection PyPep8
|
||||
str2octs = lambda x: x
|
||||
# noinspection PyPep8
|
||||
octs2str = lambda x: x
|
||||
# noinspection PyPep8
|
||||
isOctetsType = lambda s: isinstance(s, str)
|
||||
# noinspection PyPep8
|
||||
isStringType = lambda s: isinstance(s, (str, unicode))
|
||||
# noinspection PyPep8
|
||||
ensureString = str
|
||||
else:
|
||||
ints2octs = bytes
|
||||
# noinspection PyPep8
|
||||
int2oct = lambda x: ints2octs((x,))
|
||||
null = ints2octs()
|
||||
# noinspection PyPep8
|
||||
oct2int = lambda x: x
|
||||
octs2ints = lambda s: [ x for x in s ]
|
||||
str2octs = lambda x: x.encode()
|
||||
octs2str = lambda x: x.decode()
|
||||
# noinspection PyPep8
|
||||
octs2ints = lambda x: x
|
||||
# noinspection PyPep8
|
||||
str2octs = lambda x: x.encode('iso-8859-1')
|
||||
# noinspection PyPep8
|
||||
octs2str = lambda x: x.decode('iso-8859-1')
|
||||
# noinspection PyPep8
|
||||
isOctetsType = lambda s: isinstance(s, bytes)
|
||||
# noinspection PyPep8
|
||||
isStringType = lambda s: isinstance(s, str)
|
||||
# noinspection PyPep8
|
||||
ensureString = bytes
|
||||
|
26
third_party/python/pyasn1/pyasn1/compat/string.py
vendored
Normal file
26
third_party/python/pyasn1/pyasn1/compat/string.py
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from sys import version_info
|
||||
|
||||
if version_info[:2] <= (2, 5):
|
||||
|
||||
def partition(string, sep):
|
||||
try:
|
||||
a, c = string.split(sep, 1)
|
||||
|
||||
except ValueError:
|
||||
a, b, c = string, '', ''
|
||||
|
||||
else:
|
||||
b = sep
|
||||
|
||||
return a, b, c
|
||||
|
||||
else:
|
||||
|
||||
def partition(string, sep):
|
||||
return string.partition(sep)
|
128
third_party/python/pyasn1/pyasn1/debug.py
vendored
128
third_party/python/pyasn1/pyasn1/debug.py
vendored
@ -1,36 +1,105 @@
|
||||
import sys
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
import logging
|
||||
from pyasn1.compat.octets import octs2ints
|
||||
from pyasn1 import error
|
||||
from pyasn1 import __version__
|
||||
|
||||
flagNone = 0x0000
|
||||
flagEncoder = 0x0001
|
||||
flagDecoder = 0x0002
|
||||
flagAll = 0xffff
|
||||
__all__ = ['Debug', 'setLogger', 'hexdump']
|
||||
|
||||
flagNone = 0x0000
|
||||
flagEncoder = 0x0001
|
||||
flagDecoder = 0x0002
|
||||
flagAll = 0xffff
|
||||
|
||||
flagMap = {
|
||||
'encoder': flagEncoder,
|
||||
'decoder': flagDecoder,
|
||||
'all': flagAll
|
||||
}
|
||||
}
|
||||
|
||||
class Debug:
|
||||
defaultPrinter = sys.stderr.write
|
||||
def __init__(self, *flags):
|
||||
|
||||
class Printer(object):
|
||||
# noinspection PyShadowingNames
|
||||
def __init__(self, logger=None, handler=None, formatter=None):
|
||||
if logger is None:
|
||||
logger = logging.getLogger('pyasn1')
|
||||
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
if handler is None:
|
||||
handler = logging.StreamHandler()
|
||||
|
||||
if formatter is None:
|
||||
formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s')
|
||||
|
||||
handler.setFormatter(formatter)
|
||||
handler.setLevel(logging.DEBUG)
|
||||
logger.addHandler(handler)
|
||||
|
||||
self.__logger = logger
|
||||
|
||||
def __call__(self, msg):
|
||||
self.__logger.debug(msg)
|
||||
|
||||
def __str__(self):
|
||||
return '<python logging>'
|
||||
|
||||
|
||||
if hasattr(logging, 'NullHandler'):
|
||||
NullHandler = logging.NullHandler
|
||||
|
||||
else:
|
||||
# Python 2.6 and older
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
|
||||
class Debug(object):
|
||||
defaultPrinter = Printer()
|
||||
|
||||
def __init__(self, *flags, **options):
|
||||
self._flags = flagNone
|
||||
self._printer = self.defaultPrinter
|
||||
self('running pyasn1 version %s' % __version__)
|
||||
for f in flags:
|
||||
if f not in flagMap:
|
||||
raise error.PyAsn1Error('bad debug flag %s' % (f,))
|
||||
self._flags = self._flags | flagMap[f]
|
||||
self('debug category \'%s\' enabled' % f)
|
||||
|
||||
|
||||
if 'loggerName' in options:
|
||||
# route our logs to parent logger
|
||||
self._printer = Printer(
|
||||
logger=logging.getLogger(options['loggerName']),
|
||||
handler=NullHandler()
|
||||
)
|
||||
|
||||
elif 'printer' in options:
|
||||
self._printer = options.get('printer')
|
||||
|
||||
else:
|
||||
self._printer = self.defaultPrinter
|
||||
|
||||
self._printer('running pyasn1 %s, debug flags %s' % (__version__, ', '.join(flags)))
|
||||
|
||||
for flag in flags:
|
||||
inverse = flag and flag[0] in ('!', '~')
|
||||
if inverse:
|
||||
flag = flag[1:]
|
||||
try:
|
||||
if inverse:
|
||||
self._flags &= ~flagMap[flag]
|
||||
else:
|
||||
self._flags |= flagMap[flag]
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('bad debug flag %s' % flag)
|
||||
|
||||
self._printer("debug category '%s' %s" % (flag, inverse and 'disabled' or 'enabled'))
|
||||
|
||||
def __str__(self):
|
||||
return 'logger %s, flags %x' % (self._printer, self._flags)
|
||||
|
||||
|
||||
def __call__(self, msg):
|
||||
self._printer('DBG: %s\n' % msg)
|
||||
self._printer(msg)
|
||||
|
||||
def __and__(self, flag):
|
||||
return self._flags & flag
|
||||
@ -38,19 +107,27 @@ class Debug:
|
||||
def __rand__(self, flag):
|
||||
return flag & self._flags
|
||||
|
||||
|
||||
logger = 0
|
||||
|
||||
def setLogger(l):
|
||||
|
||||
def setLogger(userLogger):
|
||||
global logger
|
||||
logger = l
|
||||
|
||||
if userLogger:
|
||||
logger = userLogger
|
||||
else:
|
||||
logger = 0
|
||||
|
||||
|
||||
def hexdump(octets):
|
||||
return ' '.join(
|
||||
[ '%s%.2X' % (n%16 == 0 and ('\n%.5d: ' % n) or '', x)
|
||||
for n,x in zip(range(len(octets)), octs2ints(octets)) ]
|
||||
)
|
||||
['%s%.2X' % (n % 16 == 0 and ('\n%.5d: ' % n) or '', x)
|
||||
for n, x in zip(range(len(octets)), octs2ints(octets))]
|
||||
)
|
||||
|
||||
class Scope:
|
||||
|
||||
class Scope(object):
|
||||
def __init__(self):
|
||||
self._list = []
|
||||
|
||||
@ -62,4 +139,5 @@ class Scope:
|
||||
def pop(self):
|
||||
return self._list.pop()
|
||||
|
||||
|
||||
scope = Scope()
|
||||
|
21
third_party/python/pyasn1/pyasn1/error.py
vendored
21
third_party/python/pyasn1/pyasn1/error.py
vendored
@ -1,3 +1,18 @@
|
||||
class PyAsn1Error(Exception): pass
|
||||
class ValueConstraintError(PyAsn1Error): pass
|
||||
class SubstrateUnderrunError(PyAsn1Error): pass
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
|
||||
|
||||
class PyAsn1Error(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ValueConstraintError(PyAsn1Error):
|
||||
pass
|
||||
|
||||
|
||||
class SubstrateUnderrunError(PyAsn1Error):
|
||||
pass
|
||||
|
684
third_party/python/pyasn1/pyasn1/type/base.py
vendored
684
third_party/python/pyasn1/pyasn1/type/base.py
vendored
@ -1,134 +1,394 @@
|
||||
# Base classes for ASN.1 types
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
import sys
|
||||
from pyasn1.type import constraint, tagmap
|
||||
from pyasn1.type import constraint, tagmap, tag
|
||||
from pyasn1.compat import calling
|
||||
from pyasn1 import error
|
||||
|
||||
class Asn1Item: pass
|
||||
__all__ = ['Asn1Item', 'Asn1ItemBase', 'AbstractSimpleAsn1Item', 'AbstractConstructedAsn1Item']
|
||||
|
||||
|
||||
class Asn1Item(object):
|
||||
@classmethod
|
||||
def getTypeId(cls, increment=1):
|
||||
try:
|
||||
Asn1Item._typeCounter += increment
|
||||
except AttributeError:
|
||||
Asn1Item._typeCounter = increment
|
||||
return Asn1Item._typeCounter
|
||||
|
||||
|
||||
class Asn1ItemBase(Asn1Item):
|
||||
# Set of tags for this ASN.1 type
|
||||
tagSet = ()
|
||||
|
||||
# A list of constraint.Constraint instances for checking values
|
||||
#: Set or return a :py:class:`~pyasn1.type.tag.TagSet` object representing
|
||||
#: ASN.1 tag(s) associated with |ASN.1| type.
|
||||
tagSet = tag.TagSet()
|
||||
|
||||
#: Default :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
||||
#: object imposing constraints on initialization values.
|
||||
subtypeSpec = constraint.ConstraintsIntersection()
|
||||
|
||||
# Used for ambiguous ASN.1 types identification
|
||||
# Disambiguation ASN.1 types identification
|
||||
typeId = None
|
||||
|
||||
def __init__(self, tagSet=None, subtypeSpec=None):
|
||||
if tagSet is None:
|
||||
self._tagSet = self.tagSet
|
||||
else:
|
||||
self._tagSet = tagSet
|
||||
if subtypeSpec is None:
|
||||
self._subtypeSpec = self.subtypeSpec
|
||||
else:
|
||||
self._subtypeSpec = subtypeSpec
|
||||
|
||||
def _verifySubtypeSpec(self, value, idx=None):
|
||||
try:
|
||||
self._subtypeSpec(value, idx)
|
||||
except error.PyAsn1Error:
|
||||
c, i, t = sys.exc_info()
|
||||
raise c('%s at %s' % (i, self.__class__.__name__))
|
||||
def __init__(self, **kwargs):
|
||||
readOnly = {
|
||||
'tagSet': self.tagSet,
|
||||
'subtypeSpec': self.subtypeSpec
|
||||
}
|
||||
|
||||
readOnly.update(kwargs)
|
||||
|
||||
self.__dict__.update(readOnly)
|
||||
|
||||
self._readOnly = readOnly
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name[0] != '_' and name in self._readOnly:
|
||||
raise error.PyAsn1Error('read-only instance attribute "%s"' % name)
|
||||
|
||||
self.__dict__[name] = value
|
||||
|
||||
@property
|
||||
def readOnly(self):
|
||||
return self._readOnly
|
||||
|
||||
@property
|
||||
def effectiveTagSet(self):
|
||||
"""For |ASN.1| type is equivalent to *tagSet*
|
||||
"""
|
||||
return self.tagSet # used by untagged types
|
||||
|
||||
@property
|
||||
def tagMap(self):
|
||||
"""Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping ASN.1 tags to ASN.1 objects within callee object.
|
||||
"""
|
||||
return tagmap.TagMap({self.tagSet: self})
|
||||
|
||||
def isSameTypeWith(self, other, matchTags=True, matchConstraints=True):
|
||||
"""Examine |ASN.1| type for equality with other ASN.1 type.
|
||||
|
||||
ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
|
||||
(:py:mod:`~pyasn1.type.constraint`) are examined when carrying
|
||||
out ASN.1 types comparison.
|
||||
|
||||
No Python inheritance relationship between PyASN1 objects is considered.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other: a pyasn1 type object
|
||||
Class instance representing ASN.1 type.
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :class:`bool`
|
||||
:class:`True` if *other* is |ASN.1| type,
|
||||
:class:`False` otherwise.
|
||||
"""
|
||||
return (self is other or
|
||||
(not matchTags or self.tagSet == other.tagSet) and
|
||||
(not matchConstraints or self.subtypeSpec == other.subtypeSpec))
|
||||
|
||||
def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
|
||||
"""Examine |ASN.1| type for subtype relationship with other ASN.1 type.
|
||||
|
||||
def getSubtypeSpec(self): return self._subtypeSpec
|
||||
|
||||
def getTagSet(self): return self._tagSet
|
||||
def getEffectiveTagSet(self): return self._tagSet # used by untagged types
|
||||
def getTagMap(self): return tagmap.TagMap({self._tagSet: self})
|
||||
|
||||
def isSameTypeWith(self, other):
|
||||
return self is other or \
|
||||
self._tagSet == other.getTagSet() and \
|
||||
self._subtypeSpec == other.getSubtypeSpec()
|
||||
def isSuperTypeOf(self, other):
|
||||
"""Returns true if argument is a ASN1 subtype of ourselves"""
|
||||
return self._tagSet.isSuperTagSetOf(other.getTagSet()) and \
|
||||
self._subtypeSpec.isSuperTypeOf(other.getSubtypeSpec())
|
||||
ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
|
||||
(:py:mod:`~pyasn1.type.constraint`) are examined when carrying
|
||||
out ASN.1 types comparison.
|
||||
|
||||
No Python inheritance relationship between PyASN1 objects is considered.
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other: a pyasn1 type object
|
||||
Class instance representing ASN.1 type.
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :class:`bool`
|
||||
:class:`True` if *other* is a subtype of |ASN.1| type,
|
||||
:class:`False` otherwise.
|
||||
"""
|
||||
return (not matchTags or
|
||||
(self.tagSet.isSuperTagSetOf(other.tagSet)) and
|
||||
(not matchConstraints or self.subtypeSpec.isSuperTypeOf(other.subtypeSpec)))
|
||||
|
||||
@staticmethod
|
||||
def isNoValue(*values):
|
||||
for value in values:
|
||||
if value is not None and value is not noValue:
|
||||
return False
|
||||
return True
|
||||
|
||||
# backward compatibility
|
||||
|
||||
def getTagSet(self):
|
||||
return self.tagSet
|
||||
|
||||
def getEffectiveTagSet(self):
|
||||
return self.effectiveTagSet
|
||||
|
||||
def getTagMap(self):
|
||||
return self.tagMap
|
||||
|
||||
def getSubtypeSpec(self):
|
||||
return self.subtypeSpec
|
||||
|
||||
def hasValue(self):
|
||||
return self.isValue
|
||||
|
||||
|
||||
class NoValue(object):
|
||||
"""Create a singleton instance of NoValue class.
|
||||
|
||||
NoValue object can be used as an initializer on PyASN1 type class
|
||||
instantiation to represent ASN.1 type rather than ASN.1 data value.
|
||||
|
||||
No operations other than type comparison can be performed on
|
||||
a PyASN1 type object.
|
||||
"""
|
||||
skipMethods = ('__getattribute__', '__getattr__', '__setattr__', '__delattr__',
|
||||
'__class__', '__init__', '__del__', '__new__', '__repr__',
|
||||
'__qualname__', '__objclass__', 'im_class', '__sizeof__')
|
||||
|
||||
_instance = None
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
def getPlug(name):
|
||||
def plug(self, *args, **kw):
|
||||
raise error.PyAsn1Error('Uninitialized ASN.1 value ("%s" attribute looked up)' % name)
|
||||
return plug
|
||||
|
||||
op_names = [name
|
||||
for typ in (str, int, list, dict)
|
||||
for name in dir(typ)
|
||||
if (name not in cls.skipMethods and
|
||||
name.startswith('__') and
|
||||
name.endswith('__') and
|
||||
calling.callable(getattr(typ, name)))]
|
||||
|
||||
for name in set(op_names):
|
||||
setattr(cls, name, getPlug(name))
|
||||
|
||||
cls._instance = object.__new__(cls)
|
||||
|
||||
return cls._instance
|
||||
|
||||
class __NoValue:
|
||||
def __getattr__(self, attr):
|
||||
raise error.PyAsn1Error('No value for %s()' % attr)
|
||||
def __getitem__(self, i):
|
||||
raise error.PyAsn1Error('No value')
|
||||
|
||||
noValue = __NoValue()
|
||||
if attr in self.skipMethods:
|
||||
raise AttributeError('attribute %s not present' % attr)
|
||||
raise error.PyAsn1Error('No value for "%s"' % attr)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s()' % self.__class__.__name__
|
||||
|
||||
noValue = NoValue()
|
||||
|
||||
|
||||
# Base class for "simple" ASN.1 objects. These are immutable.
|
||||
class AbstractSimpleAsn1Item(Asn1ItemBase):
|
||||
class AbstractSimpleAsn1Item(Asn1ItemBase):
|
||||
#: Default payload value
|
||||
defaultValue = noValue
|
||||
def __init__(self, value=None, tagSet=None, subtypeSpec=None):
|
||||
Asn1ItemBase.__init__(self, tagSet, subtypeSpec)
|
||||
if value is None or value is noValue:
|
||||
|
||||
def __init__(self, value=noValue, **kwargs):
|
||||
Asn1ItemBase.__init__(self, **kwargs)
|
||||
if value is noValue or value is None:
|
||||
value = self.defaultValue
|
||||
if value is None or value is noValue:
|
||||
self.__hashedValue = value = noValue
|
||||
else:
|
||||
value = self.prettyIn(value)
|
||||
self._verifySubtypeSpec(value)
|
||||
self.__hashedValue = hash(value)
|
||||
try:
|
||||
self.subtypeSpec(value)
|
||||
|
||||
except error.PyAsn1Error:
|
||||
exType, exValue, exTb = sys.exc_info()
|
||||
raise exType('%s at %s' % (exValue, self.__class__.__name__))
|
||||
|
||||
self._value = value
|
||||
self._len = None
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
if self._value is noValue:
|
||||
return self.__class__.__name__ + '()'
|
||||
else:
|
||||
return self.__class__.__name__ + '(%s)' % (self.prettyOut(self._value),)
|
||||
def __str__(self): return str(self._value)
|
||||
representation = []
|
||||
if self._value is not self.defaultValue:
|
||||
representation.append(self.prettyOut(self._value))
|
||||
if self.tagSet is not self.__class__.tagSet:
|
||||
representation.append('tagSet=%r' % (self.tagSet,))
|
||||
if self.subtypeSpec is not self.__class__.subtypeSpec:
|
||||
representation.append('subtypeSpec=%r' % (self.subtypeSpec,))
|
||||
return '%s(%s)' % (self.__class__.__name__, ', '.join(representation))
|
||||
|
||||
def __str__(self):
|
||||
return str(self._value)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self is other and True or self._value == other
|
||||
def __ne__(self, other): return self._value != other
|
||||
def __lt__(self, other): return self._value < other
|
||||
def __le__(self, other): return self._value <= other
|
||||
def __gt__(self, other): return self._value > other
|
||||
def __ge__(self, other): return self._value >= other
|
||||
|
||||
def __ne__(self, other):
|
||||
return self._value != other
|
||||
|
||||
def __lt__(self, other):
|
||||
return self._value < other
|
||||
|
||||
def __le__(self, other):
|
||||
return self._value <= other
|
||||
|
||||
def __gt__(self, other):
|
||||
return self._value > other
|
||||
|
||||
def __ge__(self, other):
|
||||
return self._value >= other
|
||||
|
||||
if sys.version_info[0] <= 2:
|
||||
def __nonzero__(self): return bool(self._value)
|
||||
def __nonzero__(self):
|
||||
return self._value and True or False
|
||||
else:
|
||||
def __bool__(self): return bool(self._value)
|
||||
def __hash__(self): return self.__hashedValue
|
||||
def __bool__(self):
|
||||
return self._value and True or False
|
||||
|
||||
def clone(self, value=None, tagSet=None, subtypeSpec=None):
|
||||
if value is None and tagSet is None and subtypeSpec is None:
|
||||
return self
|
||||
if value is None:
|
||||
value = self._value
|
||||
if tagSet is None:
|
||||
tagSet = self._tagSet
|
||||
if subtypeSpec is None:
|
||||
subtypeSpec = self._subtypeSpec
|
||||
return self.__class__(value, tagSet, subtypeSpec)
|
||||
def __hash__(self):
|
||||
return hash(self._value)
|
||||
|
||||
@property
|
||||
def isValue(self):
|
||||
"""Indicate if |ASN.1| object represents ASN.1 type or ASN.1 value.
|
||||
|
||||
In other words, if *isValue* is `True`, then the ASN.1 object is
|
||||
initialized.
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :class:`bool`
|
||||
:class:`True` if object represents ASN.1 value and type,
|
||||
:class:`False` if object represents just ASN.1 type.
|
||||
|
||||
Note
|
||||
----
|
||||
There is an important distinction between PyASN1 type and value objects.
|
||||
The PyASN1 type objects can only participate in ASN.1 type
|
||||
operations (subtyping, comparison etc) and serve as a
|
||||
blueprint for serialization codecs to resolve ambiguous types.
|
||||
|
||||
The PyASN1 value objects can additionally participate in most
|
||||
of built-in Python operations.
|
||||
"""
|
||||
return self._value is not noValue
|
||||
|
||||
def clone(self, value=noValue, **kwargs):
|
||||
"""Create a copy of a |ASN.1| type or object.
|
||||
|
||||
Any parameters to the *clone()* method will replace corresponding
|
||||
properties of the |ASN.1| object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value: :class:`tuple`, :class:`str` or |ASN.1| object
|
||||
Initialization value to pass to new ASN.1 object instead of
|
||||
inheriting one from the caller.
|
||||
|
||||
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
|
||||
Object representing ASN.1 tag(s) to use in new object instead of inheriting from the caller
|
||||
|
||||
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
||||
Object representing ASN.1 subtype constraint(s) to use in new object instead of inheriting from the caller
|
||||
|
||||
Returns
|
||||
-------
|
||||
:
|
||||
new instance of |ASN.1| type/value
|
||||
"""
|
||||
if value is noValue or value is None:
|
||||
if not kwargs:
|
||||
return self
|
||||
|
||||
def subtype(self, value=None, implicitTag=None, explicitTag=None,
|
||||
subtypeSpec=None):
|
||||
if value is None:
|
||||
value = self._value
|
||||
|
||||
initilaizers = self.readOnly.copy()
|
||||
initilaizers.update(kwargs)
|
||||
|
||||
return self.__class__(value, **initilaizers)
|
||||
|
||||
def subtype(self, value=noValue, **kwargs):
|
||||
"""Create a copy of a |ASN.1| type or object.
|
||||
|
||||
Any parameters to the *subtype()* method will be added to the corresponding
|
||||
properties of the |ASN.1| object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value: :class:`tuple`, :class:`str` or |ASN.1| object
|
||||
Initialization value to pass to new ASN.1 object instead of
|
||||
inheriting one from the caller.
|
||||
|
||||
implicitTag: :py:class:`~pyasn1.type.tag.Tag`
|
||||
Implicitly apply given ASN.1 tag object to caller's
|
||||
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
|
||||
new object's ASN.1 tag(s).
|
||||
|
||||
explicitTag: :py:class:`~pyasn1.type.tag.Tag`
|
||||
Explicitly apply given ASN.1 tag object to caller's
|
||||
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
|
||||
new object's ASN.1 tag(s).
|
||||
|
||||
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
||||
Add ASN.1 constraints object to one of the caller, then
|
||||
use the result as new object's ASN.1 constraints.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:
|
||||
new instance of |ASN.1| type/value
|
||||
"""
|
||||
if value is noValue or value is None:
|
||||
if not kwargs:
|
||||
return self
|
||||
|
||||
value = self._value
|
||||
|
||||
initializers = self.readOnly.copy()
|
||||
|
||||
implicitTag = kwargs.pop('implicitTag', None)
|
||||
if implicitTag is not None:
|
||||
tagSet = self._tagSet.tagImplicitly(implicitTag)
|
||||
elif explicitTag is not None:
|
||||
tagSet = self._tagSet.tagExplicitly(explicitTag)
|
||||
else:
|
||||
tagSet = self._tagSet
|
||||
if subtypeSpec is None:
|
||||
subtypeSpec = self._subtypeSpec
|
||||
else:
|
||||
subtypeSpec = subtypeSpec + self._subtypeSpec
|
||||
return self.__class__(value, tagSet, subtypeSpec)
|
||||
initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag)
|
||||
|
||||
def prettyIn(self, value): return value
|
||||
def prettyOut(self, value): return str(value)
|
||||
explicitTag = kwargs.pop('explicitTag', None)
|
||||
if explicitTag is not None:
|
||||
initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag)
|
||||
|
||||
for arg, option in kwargs.items():
|
||||
initializers[arg] += option
|
||||
|
||||
return self.__class__(value, **initializers)
|
||||
|
||||
def prettyIn(self, value):
|
||||
return value
|
||||
|
||||
def prettyOut(self, value):
|
||||
return str(value)
|
||||
|
||||
def prettyPrint(self, scope=0):
|
||||
if self._value is noValue:
|
||||
return '<no value>'
|
||||
else:
|
||||
"""Provide human-friendly printable object representation.
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :class:`str`
|
||||
human-friendly type and/or value representation.
|
||||
"""
|
||||
if self.isValue:
|
||||
return self.prettyOut(self._value)
|
||||
else:
|
||||
return '<no value>'
|
||||
|
||||
# XXX Compatibility stub
|
||||
def prettyPrinter(self, scope=0): return self.prettyPrint(scope)
|
||||
|
||||
def prettyPrinter(self, scope=0):
|
||||
return self.prettyPrint(scope)
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
def prettyPrintType(self, scope=0):
|
||||
return '%s -> %s' % (self.tagSet, self.__class__.__name__)
|
||||
|
||||
#
|
||||
# Constructed types:
|
||||
# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice
|
||||
@ -148,102 +408,194 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
|
||||
# of types for Sequence/Set/Choice.
|
||||
#
|
||||
|
||||
def setupComponent():
|
||||
"""Returns a sentinel value.
|
||||
|
||||
Indicates to a constructed type to set up its inner component so that it
|
||||
can be referred to. This is useful in situation when you want to populate
|
||||
descendants of a constructed type what requires being able to refer to
|
||||
their parent types along the way.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
>>> constructed['record'] = setupComponent()
|
||||
>>> constructed['record']['scalar'] = 42
|
||||
"""
|
||||
return noValue
|
||||
|
||||
|
||||
class AbstractConstructedAsn1Item(Asn1ItemBase):
|
||||
|
||||
#: If `True`, requires exact component type matching,
|
||||
#: otherwise subtype relation is only enforced
|
||||
strictConstraints = False
|
||||
|
||||
componentType = None
|
||||
sizeSpec = constraint.ConstraintsIntersection()
|
||||
def __init__(self, componentType=None, tagSet=None,
|
||||
subtypeSpec=None, sizeSpec=None):
|
||||
Asn1ItemBase.__init__(self, tagSet, subtypeSpec)
|
||||
if componentType is None:
|
||||
self._componentType = self.componentType
|
||||
else:
|
||||
self._componentType = componentType
|
||||
if sizeSpec is None:
|
||||
self._sizeSpec = self.sizeSpec
|
||||
else:
|
||||
self._sizeSpec = sizeSpec
|
||||
sizeSpec = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
readOnly = {
|
||||
'componentType': self.componentType,
|
||||
'sizeSpec': self.sizeSpec
|
||||
}
|
||||
readOnly.update(kwargs)
|
||||
|
||||
Asn1ItemBase.__init__(self, **readOnly)
|
||||
|
||||
self._componentValues = []
|
||||
self._componentValuesSet = 0
|
||||
|
||||
def __repr__(self):
|
||||
r = self.__class__.__name__ + '()'
|
||||
for idx in range(len(self._componentValues)):
|
||||
if self._componentValues[idx] is None:
|
||||
continue
|
||||
r = r + '.setComponentByPosition(%s, %r)' % (
|
||||
idx, self._componentValues[idx]
|
||||
)
|
||||
return r
|
||||
representation = []
|
||||
if self.componentType is not self.__class__.componentType:
|
||||
representation.append('componentType=%r' % (self.componentType,))
|
||||
if self.tagSet is not self.__class__.tagSet:
|
||||
representation.append('tagSet=%r' % (self.tagSet,))
|
||||
if self.subtypeSpec is not self.__class__.subtypeSpec:
|
||||
representation.append('subtypeSpec=%r' % (self.subtypeSpec,))
|
||||
representation = '%s(%s)' % (self.__class__.__name__, ', '.join(representation))
|
||||
if self._componentValues:
|
||||
for idx, component in enumerate(self._componentValues):
|
||||
if component is None or component is noValue:
|
||||
continue
|
||||
representation += '.setComponentByPosition(%d, %s)' % (idx, repr(component))
|
||||
return representation
|
||||
|
||||
def __eq__(self, other):
|
||||
return self is other and True or self._componentValues == other
|
||||
def __ne__(self, other): return self._componentValues != other
|
||||
def __lt__(self, other): return self._componentValues < other
|
||||
def __le__(self, other): return self._componentValues <= other
|
||||
def __gt__(self, other): return self._componentValues > other
|
||||
def __ge__(self, other): return self._componentValues >= other
|
||||
|
||||
def __ne__(self, other):
|
||||
return self._componentValues != other
|
||||
|
||||
def __lt__(self, other):
|
||||
return self._componentValues < other
|
||||
|
||||
def __le__(self, other):
|
||||
return self._componentValues <= other
|
||||
|
||||
def __gt__(self, other):
|
||||
return self._componentValues > other
|
||||
|
||||
def __ge__(self, other):
|
||||
return self._componentValues >= other
|
||||
|
||||
if sys.version_info[0] <= 2:
|
||||
def __nonzero__(self): return bool(self._componentValues)
|
||||
def __nonzero__(self):
|
||||
return self._componentValues and True or False
|
||||
else:
|
||||
def __bool__(self): return bool(self._componentValues)
|
||||
def __bool__(self):
|
||||
return self._componentValues and True or False
|
||||
|
||||
def getComponentTagMap(self):
|
||||
raise error.PyAsn1Error('Method not implemented')
|
||||
def _cloneComponentValues(self, myClone, cloneValueFlag):
|
||||
pass
|
||||
|
||||
def _cloneComponentValues(self, myClone, cloneValueFlag): pass
|
||||
def clone(self, **kwargs):
|
||||
"""Create a copy of a |ASN.1| type or object.
|
||||
|
||||
Any parameters to the *clone()* method will replace corresponding
|
||||
properties of the |ASN.1| object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
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)
|
||||
|
||||
sizeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
||||
Object representing non-default ASN.1 size constraint(s)
|
||||
|
||||
Returns
|
||||
-------
|
||||
:
|
||||
new instance of |ASN.1| type/value
|
||||
|
||||
"""
|
||||
cloneValueFlag = kwargs.pop('cloneValueFlag', False)
|
||||
|
||||
initilaizers = self.readOnly.copy()
|
||||
initilaizers.update(kwargs)
|
||||
|
||||
clone = self.__class__(**initilaizers)
|
||||
|
||||
def clone(self, tagSet=None, subtypeSpec=None, sizeSpec=None,
|
||||
cloneValueFlag=None):
|
||||
if tagSet is None:
|
||||
tagSet = self._tagSet
|
||||
if subtypeSpec is None:
|
||||
subtypeSpec = self._subtypeSpec
|
||||
if sizeSpec is None:
|
||||
sizeSpec = self._sizeSpec
|
||||
r = self.__class__(self._componentType, tagSet, subtypeSpec, sizeSpec)
|
||||
if cloneValueFlag:
|
||||
self._cloneComponentValues(r, cloneValueFlag)
|
||||
return r
|
||||
self._cloneComponentValues(clone, cloneValueFlag)
|
||||
|
||||
def subtype(self, implicitTag=None, explicitTag=None, subtypeSpec=None,
|
||||
sizeSpec=None, cloneValueFlag=None):
|
||||
return clone
|
||||
|
||||
def subtype(self, **kwargs):
|
||||
"""Create a copy of a |ASN.1| type or object.
|
||||
|
||||
Any parameters to the *subtype()* method will be added to the corresponding
|
||||
properties of the |ASN.1| object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
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)
|
||||
|
||||
sizeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
||||
Object representing non-default ASN.1 size constraint(s)
|
||||
|
||||
Returns
|
||||
-------
|
||||
:
|
||||
new instance of |ASN.1| type/value
|
||||
|
||||
"""
|
||||
|
||||
initializers = self.readOnly.copy()
|
||||
|
||||
cloneValueFlag = kwargs.pop('cloneValueFlag', False)
|
||||
|
||||
implicitTag = kwargs.pop('implicitTag', None)
|
||||
if implicitTag is not None:
|
||||
tagSet = self._tagSet.tagImplicitly(implicitTag)
|
||||
elif explicitTag is not None:
|
||||
tagSet = self._tagSet.tagExplicitly(explicitTag)
|
||||
else:
|
||||
tagSet = self._tagSet
|
||||
if subtypeSpec is None:
|
||||
subtypeSpec = self._subtypeSpec
|
||||
else:
|
||||
subtypeSpec = subtypeSpec + self._subtypeSpec
|
||||
if sizeSpec is None:
|
||||
sizeSpec = self._sizeSpec
|
||||
else:
|
||||
sizeSpec = sizeSpec + self._sizeSpec
|
||||
r = self.__class__(self._componentType, tagSet, subtypeSpec, sizeSpec)
|
||||
initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag)
|
||||
|
||||
explicitTag = kwargs.pop('explicitTag', None)
|
||||
if explicitTag is not None:
|
||||
initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag)
|
||||
|
||||
for arg, option in kwargs.items():
|
||||
initializers[arg] += option
|
||||
|
||||
clone = self.__class__(**initializers)
|
||||
|
||||
if cloneValueFlag:
|
||||
self._cloneComponentValues(r, cloneValueFlag)
|
||||
return r
|
||||
self._cloneComponentValues(clone, cloneValueFlag)
|
||||
|
||||
def _verifyComponent(self, idx, value): pass
|
||||
return clone
|
||||
|
||||
def verifySizeSpec(self): self._sizeSpec(self)
|
||||
def verifySizeSpec(self):
|
||||
self.sizeSpec(self)
|
||||
|
||||
def getComponentByPosition(self, idx):
|
||||
raise error.PyAsn1Error('Method not implemented')
|
||||
|
||||
def setComponentByPosition(self, idx, value, verifyConstraints=True):
|
||||
raise error.PyAsn1Error('Method not implemented')
|
||||
|
||||
def getComponentType(self): return self._componentType
|
||||
def setComponents(self, *args, **kwargs):
|
||||
for idx, value in enumerate(args):
|
||||
self[idx] = value
|
||||
for k in kwargs:
|
||||
self[k] = kwargs[k]
|
||||
return self
|
||||
|
||||
def __getitem__(self, idx): return self.getComponentByPosition(idx)
|
||||
def __setitem__(self, idx, value): self.setComponentByPosition(idx, value)
|
||||
def __len__(self):
|
||||
return len(self._componentValues)
|
||||
|
||||
def __len__(self): return len(self._componentValues)
|
||||
|
||||
def clear(self):
|
||||
self._componentValues = []
|
||||
self._componentValuesSet = 0
|
||||
|
||||
def setDefaultComponents(self): pass
|
||||
# backward compatibility
|
||||
|
||||
def setDefaultComponents(self):
|
||||
pass
|
||||
|
||||
def getComponentType(self):
|
||||
return self.componentType
|
||||
|
387
third_party/python/pyasn1/pyasn1/type/char.py
vendored
387
third_party/python/pyasn1/pyasn1/type/char.py
vendored
@ -1,61 +1,374 @@
|
||||
# ASN.1 "character string" types
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
import sys
|
||||
from pyasn1.type import univ, tag
|
||||
from pyasn1 import error
|
||||
|
||||
class UTF8String(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
|
||||
)
|
||||
encoding = "utf-8"
|
||||
|
||||
class NumericString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
__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| type or object.
|
||||
|
||||
|ASN.1| objects are immutable and duck-type Python 2 :class:`unicode` or Python 3 :class:`str`.
|
||||
When used in octet-stream context, |ASN.1| type assumes "|encoding|" encoding.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
|
||||
unicode object (Python 2) or string (Python 3), alternatively string
|
||||
(Python 2) or bytes (Python 3) representing octet-stream of serialized
|
||||
unicode string (note `encoding` parameter) or |ASN.1| class instance.
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
------
|
||||
: :py:class:`pyasn1.error.PyAsn1Error`
|
||||
On constraint violation or bad initializer.
|
||||
"""
|
||||
|
||||
if sys.version_info[0] <= 2:
|
||||
def __str__(self):
|
||||
try:
|
||||
return self._value.encode(self.encoding)
|
||||
except UnicodeEncodeError:
|
||||
raise error.PyAsn1Error(
|
||||
"Can't encode string '%s' with codec %s" % (self._value, self.encoding)
|
||||
)
|
||||
|
||||
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):
|
||||
raise error.PyAsn1Error(
|
||||
"Can't decode string '%s' with codec %s" % (value, self.encoding)
|
||||
)
|
||||
|
||||
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):
|
||||
return str(self._value)
|
||||
|
||||
def __bytes__(self):
|
||||
try:
|
||||
return self._value.encode(self.encoding)
|
||||
except UnicodeEncodeError:
|
||||
raise error.PyAsn1Error(
|
||||
"Can't encode string '%s' with codec %s" % (self._value, self.encoding)
|
||||
)
|
||||
|
||||
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):
|
||||
raise error.PyAsn1Error(
|
||||
"Can't decode string '%s' with codec %s" % (value, self.encoding)
|
||||
)
|
||||
|
||||
def asOctets(self, padding=True):
|
||||
return bytes(self)
|
||||
|
||||
def asNumbers(self, padding=True):
|
||||
return tuple(bytes(self))
|
||||
|
||||
def prettyOut(self, value):
|
||||
return value
|
||||
|
||||
def __reversed__(self):
|
||||
return reversed(self._value)
|
||||
|
||||
def clone(self, value=noValue, **kwargs):
|
||||
"""Creates a copy of a |ASN.1| type or object.
|
||||
|
||||
Any parameters to the *clone()* method will replace corresponding
|
||||
properties of the |ASN.1| object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
|
||||
unicode object (Python 2) or string (Python 3), alternatively string
|
||||
(Python 2) or bytes (Python 3) representing octet-stream of serialized
|
||||
unicode string (note `encoding` parameter) or |ASN.1| class instance.
|
||||
|
||||
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)
|
||||
|
||||
encoding: :py:class:`str`
|
||||
Unicode codec ID to encode/decode :py:class:`unicode` (Python 2) or
|
||||
:py:class:`str` (Python 3) the payload when |ASN.1| object is used
|
||||
in octet-stream context.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:
|
||||
new instance of |ASN.1| type/value
|
||||
|
||||
"""
|
||||
return univ.OctetString.clone(self, value, **kwargs)
|
||||
|
||||
def subtype(self, value=noValue, **kwargs):
|
||||
"""Creates a copy of a |ASN.1| type or object.
|
||||
|
||||
Any parameters to the *subtype()* method will be added to the corresponding
|
||||
properties of the |ASN.1| object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
|
||||
unicode object (Python 2) or string (Python 3), alternatively string
|
||||
(Python 2) or bytes (Python 3) representing octet-stream of serialized
|
||||
unicode string (note `encoding` parameter) or |ASN.1| class instance.
|
||||
|
||||
implicitTag: :py:class:`~pyasn1.type.tag.Tag`
|
||||
Implicitly apply given ASN.1 tag object to caller's
|
||||
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
|
||||
new object's ASN.1 tag(s).
|
||||
|
||||
explicitTag: :py:class:`~pyasn1.type.tag.Tag`
|
||||
Explicitly apply given ASN.1 tag object to caller's
|
||||
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
|
||||
new object's ASN.1 tag(s).
|
||||
|
||||
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
||||
Object representing non-default ASN.1 subtype constraint(s)
|
||||
|
||||
encoding: :py:class:`str`
|
||||
Unicode codec ID to encode/decode :py:class:`unicode` (Python 2) or
|
||||
:py:class:`str` (Python 3) the payload when |ASN.1| object is used
|
||||
in octet-stream context.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:
|
||||
new instance of |ASN.1| type/value
|
||||
|
||||
"""
|
||||
return univ.OctetString.subtype(self, value, **kwargs)
|
||||
|
||||
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'
|
||||
|
||||
class PrintableString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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'
|
||||
|
||||
class TeletexString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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'
|
||||
|
||||
class VideotexString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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'
|
||||
|
||||
class IA5String(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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'
|
||||
|
||||
class GraphicString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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'
|
||||
|
||||
class VisibleString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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'
|
||||
|
||||
class GeneralString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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'
|
||||
|
||||
class UniversalString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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"
|
||||
|
||||
class BMPString(univ.OctetString):
|
||||
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
||||
# 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()
|
||||
|
174
third_party/python/pyasn1/pyasn1/type/constraint.py
vendored
174
third_party/python/pyasn1/pyasn1/type/constraint.py
vendored
@ -1,86 +1,124 @@
|
||||
#
|
||||
# ASN.1 subtype constraints classes.
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Constraints are relatively rare, but every ASN1 object
|
||||
# is doing checks all the time for whether they have any
|
||||
# constraints and whether they are applicable to the object.
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
# What we're going to do is define objects/functions that
|
||||
# can be called unconditionally if they are present, and that
|
||||
# are simply not present if there are no constraints.
|
||||
#
|
||||
# Original concept and code by Mike C. Fletcher.
|
||||
# Original concept and code by Mike C. Fletcher.
|
||||
#
|
||||
import sys
|
||||
from pyasn1.type import error
|
||||
|
||||
class AbstractConstraint:
|
||||
__all__ = ['SingleValueConstraint', 'ContainedSubtypeConstraint', 'ValueRangeConstraint',
|
||||
'ValueSizeConstraint', 'PermittedAlphabetConstraint', 'InnerTypeConstraint',
|
||||
'ConstraintsExclusion', 'ConstraintsIntersection', 'ConstraintsUnion']
|
||||
|
||||
|
||||
class AbstractConstraint(object):
|
||||
"""Abstract base-class for constraint objects
|
||||
|
||||
Constraints should be stored in a simple sequence in the
|
||||
namespace of their client Asn1Item sub-classes.
|
||||
namespace of their client Asn1Item sub-classes in cases
|
||||
when ASN.1 constraint is define.
|
||||
"""
|
||||
|
||||
def __init__(self, *values):
|
||||
self._valueMap = {}
|
||||
self._valueMap = set()
|
||||
self._setValues(values)
|
||||
self.__hashedValues = None
|
||||
self.__hash = hash((self.__class__.__name__, self._values))
|
||||
|
||||
def __call__(self, value, idx=None):
|
||||
if not self._values:
|
||||
return
|
||||
|
||||
try:
|
||||
self._testValue(value, idx)
|
||||
|
||||
except error.ValueConstraintError:
|
||||
raise error.ValueConstraintError(
|
||||
'%s failed at: \"%s\"' % (self, sys.exc_info()[1])
|
||||
'%s failed at: %r' % (self, sys.exc_info()[1])
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (
|
||||
self.__class__.__name__,
|
||||
', '.join([repr(x) for x in self._values])
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self is other and True or self._values == other
|
||||
def __ne__(self, other): return self._values != other
|
||||
def __lt__(self, other): return self._values < other
|
||||
def __le__(self, other): return self._values <= other
|
||||
def __gt__(self, other): return self._values > other
|
||||
def __ge__(self, other): return self._values >= other
|
||||
|
||||
def __ne__(self, other):
|
||||
return self._values != other
|
||||
|
||||
def __lt__(self, other):
|
||||
return self._values < other
|
||||
|
||||
def __le__(self, other):
|
||||
return self._values <= other
|
||||
|
||||
def __gt__(self, other):
|
||||
return self._values > other
|
||||
|
||||
def __ge__(self, other):
|
||||
return self._values >= other
|
||||
|
||||
if sys.version_info[0] <= 2:
|
||||
def __nonzero__(self): return bool(self._values)
|
||||
def __nonzero__(self):
|
||||
return self._values and True or False
|
||||
else:
|
||||
def __bool__(self): return bool(self._values)
|
||||
def __bool__(self):
|
||||
return self._values and True or False
|
||||
|
||||
def __hash__(self):
|
||||
if self.__hashedValues is None:
|
||||
self.__hashedValues = hash((self.__class__.__name__, self._values))
|
||||
return self.__hashedValues
|
||||
return self.__hash
|
||||
|
||||
def _setValues(self, values):
|
||||
self._values = values
|
||||
|
||||
def _setValues(self, values): self._values = values
|
||||
def _testValue(self, value, idx):
|
||||
raise error.ValueConstraintError(value)
|
||||
|
||||
# Constraints derivation logic
|
||||
def getValueMap(self): return self._valueMap
|
||||
def getValueMap(self):
|
||||
return self._valueMap
|
||||
|
||||
def isSuperTypeOf(self, otherConstraint):
|
||||
return self in otherConstraint.getValueMap() or \
|
||||
otherConstraint is self or otherConstraint == self
|
||||
# TODO: fix possible comparison of set vs scalars here
|
||||
return (otherConstraint is self or
|
||||
not self._values or
|
||||
otherConstraint == self or
|
||||
self in otherConstraint.getValueMap())
|
||||
|
||||
def isSubTypeOf(self, otherConstraint):
|
||||
return otherConstraint in self._valueMap or \
|
||||
otherConstraint is self or otherConstraint == self
|
||||
return (otherConstraint is self or
|
||||
not self or
|
||||
otherConstraint == self or
|
||||
otherConstraint in self._valueMap)
|
||||
|
||||
class SingleValueConstraint(AbstractConstraint):
|
||||
"""Value must be part of defined values constraint"""
|
||||
|
||||
def _setValues(self, values):
|
||||
self._values = values
|
||||
self._set = set(values)
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
# XXX index vals for performance?
|
||||
if value not in self._values:
|
||||
if value not in self._set:
|
||||
raise error.ValueConstraintError(value)
|
||||
|
||||
|
||||
class ContainedSubtypeConstraint(AbstractConstraint):
|
||||
"""Value must satisfy all of defined set of constraints"""
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
for c in self._values:
|
||||
c(value, idx)
|
||||
|
||||
|
||||
class ValueRangeConstraint(AbstractConstraint):
|
||||
"""Value must be within start and stop values (inclusive)"""
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
if value < self.start or value > self.stop:
|
||||
raise error.ValueConstraintError(value)
|
||||
@ -89,7 +127,7 @@ class ValueRangeConstraint(AbstractConstraint):
|
||||
if len(values) != 2:
|
||||
raise error.PyAsn1Error(
|
||||
'%s: bad constraint values' % (self.__class__.__name__,)
|
||||
)
|
||||
)
|
||||
self.start, self.stop = values
|
||||
if self.start > self.stop:
|
||||
raise error.PyAsn1Error(
|
||||
@ -99,28 +137,31 @@ class ValueRangeConstraint(AbstractConstraint):
|
||||
)
|
||||
)
|
||||
AbstractConstraint._setValues(self, values)
|
||||
|
||||
|
||||
|
||||
class ValueSizeConstraint(ValueRangeConstraint):
|
||||
"""len(value) must be within start and stop values (inclusive)"""
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
l = len(value)
|
||||
if l < self.start or l > self.stop:
|
||||
valueSize = len(value)
|
||||
if valueSize < self.start or valueSize > self.stop:
|
||||
raise error.ValueConstraintError(value)
|
||||
|
||||
|
||||
class PermittedAlphabetConstraint(SingleValueConstraint):
|
||||
def _setValues(self, values):
|
||||
self._values = ()
|
||||
for v in values:
|
||||
self._values = self._values + tuple(v)
|
||||
self._values = values
|
||||
self._set = set(values)
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
for v in value:
|
||||
if v not in self._values:
|
||||
raise error.ValueConstraintError(value)
|
||||
if not self._set.issuperset(value):
|
||||
raise error.ValueConstraintError(value)
|
||||
|
||||
# This is a bit kludgy, meaning two op modes within a single constraing
|
||||
|
||||
# This is a bit kludgy, meaning two op modes within a single constraint
|
||||
class InnerTypeConstraint(AbstractConstraint):
|
||||
"""Value must satisfy type and presense constraints"""
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
if self.__singleTypeConstraint:
|
||||
self.__singleTypeConstraint(value)
|
||||
@ -128,7 +169,7 @@ class InnerTypeConstraint(AbstractConstraint):
|
||||
if idx not in self.__multipleTypeConstraint:
|
||||
raise error.ValueConstraintError(value)
|
||||
constraint, status = self.__multipleTypeConstraint[idx]
|
||||
if status == 'ABSENT': # XXX presense is not checked!
|
||||
if status == 'ABSENT': # XXX presense is not checked!
|
||||
raise error.ValueConstraintError(value)
|
||||
constraint(value)
|
||||
|
||||
@ -142,10 +183,12 @@ class InnerTypeConstraint(AbstractConstraint):
|
||||
self.__singleTypeConstraint = v
|
||||
AbstractConstraint._setValues(self, values)
|
||||
|
||||
# Boolean ops on constraints
|
||||
|
||||
# Boolean ops on constraints
|
||||
|
||||
class ConstraintsExclusion(AbstractConstraint):
|
||||
"""Value must not fit the single constraint"""
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
try:
|
||||
self._values[0](value, idx)
|
||||
@ -159,42 +202,57 @@ class ConstraintsExclusion(AbstractConstraint):
|
||||
raise error.PyAsn1Error('Single constraint expected')
|
||||
AbstractConstraint._setValues(self, values)
|
||||
|
||||
|
||||
class AbstractConstraintSet(AbstractConstraint):
|
||||
"""Value must not satisfy the single constraint"""
|
||||
def __getitem__(self, idx): return self._values[idx]
|
||||
|
||||
def __add__(self, value): return self.__class__(self, value)
|
||||
def __radd__(self, value): return self.__class__(self, value)
|
||||
def __getitem__(self, idx):
|
||||
return self._values[idx]
|
||||
|
||||
def __len__(self): return len(self._values)
|
||||
def __iter__(self):
|
||||
return iter(self._values)
|
||||
|
||||
def __add__(self, value):
|
||||
return self.__class__(*(self._values + (value,)))
|
||||
|
||||
def __radd__(self, value):
|
||||
return self.__class__(*((value,) + self._values))
|
||||
|
||||
def __len__(self):
|
||||
return len(self._values)
|
||||
|
||||
# Constraints inclusion in sets
|
||||
|
||||
|
||||
def _setValues(self, values):
|
||||
self._values = values
|
||||
for v in values:
|
||||
self._valueMap[v] = 1
|
||||
self._valueMap.update(v.getValueMap())
|
||||
for constraint in values:
|
||||
if constraint:
|
||||
self._valueMap.add(constraint)
|
||||
self._valueMap.update(constraint.getValueMap())
|
||||
|
||||
|
||||
class ConstraintsIntersection(AbstractConstraintSet):
|
||||
"""Value must satisfy all constraints"""
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
for v in self._values:
|
||||
v(value, idx)
|
||||
for constraint in self._values:
|
||||
constraint(value, idx)
|
||||
|
||||
|
||||
class ConstraintsUnion(AbstractConstraintSet):
|
||||
"""Value must satisfy at least one constraint"""
|
||||
|
||||
def _testValue(self, value, idx):
|
||||
for v in self._values:
|
||||
for constraint in self._values:
|
||||
try:
|
||||
v(value, idx)
|
||||
constraint(value, idx)
|
||||
except error.ValueConstraintError:
|
||||
pass
|
||||
else:
|
||||
return
|
||||
raise error.ValueConstraintError(
|
||||
'all of %s failed for \"%s\"' % (self._values, value)
|
||||
)
|
||||
)
|
||||
|
||||
# XXX
|
||||
# add tests for type check
|
||||
|
10
third_party/python/pyasn1/pyasn1/type/error.py
vendored
10
third_party/python/pyasn1/pyasn1/type/error.py
vendored
@ -1,3 +1,11 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
from pyasn1.error import PyAsn1Error
|
||||
|
||||
class ValueConstraintError(PyAsn1Error): pass
|
||||
|
||||
class ValueConstraintError(PyAsn1Error):
|
||||
pass
|
||||
|
587
third_party/python/pyasn1/pyasn1/type/namedtype.py
vendored
587
third_party/python/pyasn1/pyasn1/type/namedtype.py
vendored
@ -1,132 +1,511 @@
|
||||
# NamedType specification for constructed types
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
import sys
|
||||
from pyasn1.type import tagmap
|
||||
from pyasn1.type import tag, tagmap
|
||||
from pyasn1 import error
|
||||
|
||||
class NamedType:
|
||||
isOptional = 0
|
||||
isDefaulted = 0
|
||||
def __init__(self, name, t):
|
||||
self.__name = name; self.__type = t
|
||||
def __repr__(self): return '%s(%s, %s)' % (
|
||||
self.__class__.__name__, self.__name, self.__type
|
||||
)
|
||||
def getType(self): return self.__type
|
||||
def getName(self): return self.__name
|
||||
def __getitem__(self, idx):
|
||||
if idx == 0: return self.__name
|
||||
if idx == 1: return self.__type
|
||||
raise IndexError()
|
||||
|
||||
class OptionalNamedType(NamedType):
|
||||
isOptional = 1
|
||||
class DefaultedNamedType(NamedType):
|
||||
isDefaulted = 1
|
||||
|
||||
class NamedTypes:
|
||||
def __init__(self, *namedTypes):
|
||||
self.__namedTypes = namedTypes
|
||||
self.__namedTypesLen = len(self.__namedTypes)
|
||||
self.__minTagSet = None
|
||||
self.__tagToPosIdx = {}; self.__nameToPosIdx = {}
|
||||
self.__tagMap = { False: None, True: None }
|
||||
self.__ambigiousTypes = {}
|
||||
__all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType', 'NamedTypes']
|
||||
|
||||
|
||||
class NamedType(object):
|
||||
"""Create named field object for a constructed ASN.1 type.
|
||||
|
||||
The |NamedType| object represents a single name and ASN.1 type of a constructed ASN.1 type.
|
||||
|
||||
|NamedType| objects are immutable and duck-type Python :class:`tuple` objects
|
||||
holding *name* and *asn1Object* components.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name: :py:class:`str`
|
||||
Field name
|
||||
|
||||
asn1Object:
|
||||
ASN.1 type object
|
||||
"""
|
||||
isOptional = False
|
||||
isDefaulted = False
|
||||
|
||||
def __init__(self, name, asn1Object):
|
||||
self.__name = name
|
||||
self.__type = asn1Object
|
||||
self.__nameAndType = name, asn1Object
|
||||
|
||||
def __repr__(self):
|
||||
r = '%s(' % self.__class__.__name__
|
||||
for n in self.__namedTypes:
|
||||
r = r + '%r, ' % (n,)
|
||||
return r + ')'
|
||||
return '%s(%r, %r)' % (self.__class__.__name__, self.__name, self.__type)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.__nameAndType == other
|
||||
|
||||
def __ne__(self, other):
|
||||
return self.__nameAndType != other
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.__nameAndType < other
|
||||
|
||||
def __le__(self, other):
|
||||
return self.__nameAndType <= other
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.__nameAndType > other
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.__nameAndType >= other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.__nameAndType)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return self.__nameAndType[idx]
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.__nameAndType)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.__name
|
||||
|
||||
def __getitem__(self, idx): return self.__namedTypes[idx]
|
||||
@property
|
||||
def asn1Object(self):
|
||||
return self.__type
|
||||
|
||||
# Backward compatibility
|
||||
|
||||
def getName(self):
|
||||
return self.name
|
||||
|
||||
def getType(self):
|
||||
return self.asn1Object
|
||||
|
||||
|
||||
class OptionalNamedType(NamedType):
|
||||
__doc__ = NamedType.__doc__
|
||||
|
||||
isOptional = True
|
||||
|
||||
|
||||
class DefaultedNamedType(NamedType):
|
||||
__doc__ = NamedType.__doc__
|
||||
|
||||
isDefaulted = True
|
||||
|
||||
|
||||
class NamedTypes(object):
|
||||
"""Create a collection of named fields for a constructed ASN.1 type.
|
||||
|
||||
The NamedTypes object represents a collection of named fields of a constructed ASN.1 type.
|
||||
|
||||
*NamedTypes* objects are immutable and duck-type Python :class:`dict` objects
|
||||
holding *name* as keys and ASN.1 type object as values.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
*namedTypes: :class:`~pyasn1.type.namedtype.NamedType`
|
||||
"""
|
||||
def __init__(self, *namedTypes, **kwargs):
|
||||
self.__namedTypes = namedTypes
|
||||
self.__namedTypesLen = len(self.__namedTypes)
|
||||
self.__minTagSet = self.__computeMinTagSet()
|
||||
self.__nameToPosMap = self.__computeNameToPosMap()
|
||||
self.__tagToPosMap = self.__computeTagToPosMap()
|
||||
self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {}
|
||||
self.__uniqueTagMap = self.__computeTagMaps(unique=True)
|
||||
self.__nonUniqueTagMap = self.__computeTagMaps(unique=False)
|
||||
self.__hasOptionalOrDefault = bool([True for namedType in self.__namedTypes
|
||||
if namedType.isDefaulted or namedType.isOptional])
|
||||
self.__requiredComponents = frozenset(
|
||||
[idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted]
|
||||
)
|
||||
self.__keys = frozenset([namedType.name for namedType in self.__namedTypes])
|
||||
self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes])
|
||||
self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes])
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%s)' % (
|
||||
self.__class__.__name__, ', '.join([repr(x) for x in self.__namedTypes])
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.__namedTypes == other
|
||||
|
||||
def __ne__(self, other):
|
||||
return self.__namedTypes != other
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.__namedTypes < other
|
||||
|
||||
def __le__(self, other):
|
||||
return self.__namedTypes <= other
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.__namedTypes > other
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.__namedTypes >= other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.__namedTypes)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
try:
|
||||
return self.__namedTypes[idx]
|
||||
|
||||
except TypeError:
|
||||
return self.__namedTypes[self.__nameToPosMap[idx]]
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.__nameToPosMap
|
||||
|
||||
def __iter__(self):
|
||||
return (x[0] for x in self.__namedTypes)
|
||||
|
||||
if sys.version_info[0] <= 2:
|
||||
def __nonzero__(self): return bool(self.__namedTypesLen)
|
||||
def __nonzero__(self):
|
||||
return self.__namedTypesLen > 0
|
||||
else:
|
||||
def __bool__(self): return bool(self.__namedTypesLen)
|
||||
def __len__(self): return self.__namedTypesLen
|
||||
|
||||
def getTypeByPosition(self, idx):
|
||||
if idx < 0 or idx >= self.__namedTypesLen:
|
||||
raise error.PyAsn1Error('Type position out of range')
|
||||
else:
|
||||
return self.__namedTypes[idx].getType()
|
||||
def __bool__(self):
|
||||
return self.__namedTypesLen > 0
|
||||
|
||||
def getPositionByType(self, tagSet):
|
||||
if not self.__tagToPosIdx:
|
||||
idx = self.__namedTypesLen
|
||||
while idx > 0:
|
||||
idx = idx - 1
|
||||
tagMap = self.__namedTypes[idx].getType().getTagMap()
|
||||
for t in tagMap.getPosMap():
|
||||
if t in self.__tagToPosIdx:
|
||||
raise error.PyAsn1Error('Duplicate type %s' % (t,))
|
||||
self.__tagToPosIdx[t] = idx
|
||||
def __len__(self):
|
||||
return self.__namedTypesLen
|
||||
|
||||
# Python dict protocol
|
||||
|
||||
def values(self):
|
||||
return self.__values
|
||||
|
||||
def keys(self):
|
||||
return self.__keys
|
||||
|
||||
def items(self):
|
||||
return self.__items
|
||||
|
||||
def clone(self):
|
||||
return self.__class__(*self.__namedTypes)
|
||||
|
||||
class PostponedError(object):
|
||||
def __init__(self, errorMsg):
|
||||
self.__errorMsg = errorMsg
|
||||
|
||||
def __getitem__(self, item):
|
||||
raise error.PyAsn1Error(self.__errorMsg)
|
||||
|
||||
def __computeTagToPosMap(self):
|
||||
tagToPosMap = {}
|
||||
for idx, namedType in enumerate(self.__namedTypes):
|
||||
tagMap = namedType.asn1Object.tagMap
|
||||
if isinstance(tagMap, NamedTypes.PostponedError):
|
||||
return tagMap
|
||||
if not tagMap:
|
||||
continue
|
||||
for _tagSet in tagMap.presentTypes:
|
||||
if _tagSet in tagToPosMap:
|
||||
return NamedTypes.PostponedError('Duplicate component tag %s at %s' % (_tagSet, namedType))
|
||||
tagToPosMap[_tagSet] = idx
|
||||
|
||||
return tagToPosMap
|
||||
|
||||
def __computeNameToPosMap(self):
|
||||
nameToPosMap = {}
|
||||
for idx, namedType in enumerate(self.__namedTypes):
|
||||
if namedType.name in nameToPosMap:
|
||||
return NamedTypes.PostponedError('Duplicate component name %s at %s' % (namedType.name, namedType))
|
||||
nameToPosMap[namedType.name] = idx
|
||||
|
||||
return nameToPosMap
|
||||
|
||||
def __computeAmbiguousTypes(self):
|
||||
ambigiousTypes = {}
|
||||
partialAmbigiousTypes = ()
|
||||
for idx, namedType in reversed(tuple(enumerate(self.__namedTypes))):
|
||||
if namedType.isOptional or namedType.isDefaulted:
|
||||
partialAmbigiousTypes = (namedType,) + partialAmbigiousTypes
|
||||
else:
|
||||
partialAmbigiousTypes = (namedType,)
|
||||
if len(partialAmbigiousTypes) == len(self.__namedTypes):
|
||||
ambigiousTypes[idx] = self
|
||||
else:
|
||||
ambigiousTypes[idx] = NamedTypes(*partialAmbigiousTypes, **dict(terminal=True))
|
||||
return ambigiousTypes
|
||||
|
||||
def getTypeByPosition(self, idx):
|
||||
"""Return ASN.1 type object by its position in fields set.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
idx: :py:class:`int`
|
||||
Field index
|
||||
|
||||
Returns
|
||||
-------
|
||||
:
|
||||
ASN.1 type
|
||||
|
||||
Raises
|
||||
------
|
||||
: :class:`~pyasn1.error.PyAsn1Error`
|
||||
If given position is out of fields range
|
||||
"""
|
||||
try:
|
||||
return self.__tagToPosIdx[tagSet]
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('Type %s not found' % (tagSet,))
|
||||
|
||||
def getNameByPosition(self, idx):
|
||||
try:
|
||||
return self.__namedTypes[idx].getName()
|
||||
return self.__namedTypes[idx].asn1Object
|
||||
|
||||
except IndexError:
|
||||
raise error.PyAsn1Error('Type position out of range')
|
||||
def getPositionByName(self, name):
|
||||
if not self.__nameToPosIdx:
|
||||
idx = self.__namedTypesLen
|
||||
while idx > 0:
|
||||
idx = idx - 1
|
||||
n = self.__namedTypes[idx].getName()
|
||||
if n in self.__nameToPosIdx:
|
||||
raise error.PyAsn1Error('Duplicate name %s' % (n,))
|
||||
self.__nameToPosIdx[n] = idx
|
||||
|
||||
def getPositionByType(self, tagSet):
|
||||
"""Return field position by its ASN.1 type.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tagSet: :class:`~pysnmp.type.tag.TagSet`
|
||||
ASN.1 tag set distinguishing one ASN.1 type from others.
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :py:class:`int`
|
||||
ASN.1 type position in fields set
|
||||
|
||||
Raises
|
||||
------
|
||||
: :class:`~pyasn1.error.PyAsn1Error`
|
||||
If *tagSet* is not present or ASN.1 types are not unique within callee *NamedTypes*
|
||||
"""
|
||||
try:
|
||||
return self.__nameToPosIdx[name]
|
||||
return self.__tagToPosMap[tagSet]
|
||||
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('Type %s not found' % (tagSet,))
|
||||
|
||||
def getNameByPosition(self, idx):
|
||||
"""Return field name by its position in fields set.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
idx: :py:class:`idx`
|
||||
Field index
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :py:class:`str`
|
||||
Field name
|
||||
|
||||
Raises
|
||||
------
|
||||
: :class:`~pyasn1.error.PyAsn1Error`
|
||||
If given field name is not present in callee *NamedTypes*
|
||||
"""
|
||||
try:
|
||||
return self.__namedTypes[idx].name
|
||||
|
||||
except IndexError:
|
||||
raise error.PyAsn1Error('Type position out of range')
|
||||
|
||||
def getPositionByName(self, name):
|
||||
"""Return field position by filed name.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
name: :py:class:`str`
|
||||
Field name
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :py:class:`int`
|
||||
Field position in fields set
|
||||
|
||||
Raises
|
||||
------
|
||||
: :class:`~pyasn1.error.PyAsn1Error`
|
||||
If *name* is not present or not unique within callee *NamedTypes*
|
||||
"""
|
||||
try:
|
||||
return self.__nameToPosMap[name]
|
||||
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('Name %s not found' % (name,))
|
||||
|
||||
def __buildAmbigiousTagMap(self):
|
||||
ambigiousTypes = ()
|
||||
idx = self.__namedTypesLen
|
||||
while idx > 0:
|
||||
idx = idx - 1
|
||||
t = self.__namedTypes[idx]
|
||||
if t.isOptional or t.isDefaulted:
|
||||
ambigiousTypes = (t, ) + ambigiousTypes
|
||||
else:
|
||||
ambigiousTypes = (t, )
|
||||
self.__ambigiousTypes[idx] = NamedTypes(*ambigiousTypes)
|
||||
|
||||
def getTagMapNearPosition(self, idx):
|
||||
if not self.__ambigiousTypes: self.__buildAmbigiousTagMap()
|
||||
"""Return ASN.1 types that are allowed at or past given field position.
|
||||
|
||||
Some ASN.1 serialization allow for skipping optional and defaulted fields.
|
||||
Some constructed ASN.1 types allow reordering of the fields. When recovering
|
||||
such objects it may be important to know which types can possibly be
|
||||
present at any given position in the field sets.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
idx: :py:class:`int`
|
||||
Field index
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :class:`~pyasn1.type.tagmap.TagMap`
|
||||
Map if ASN.1 types allowed at given field position
|
||||
|
||||
Raises
|
||||
------
|
||||
: :class:`~pyasn1.error.PyAsn1Error`
|
||||
If given position is out of fields range
|
||||
"""
|
||||
try:
|
||||
return self.__ambigiousTypes[idx].getTagMap()
|
||||
return self.__ambiguousTypes[idx].tagMap
|
||||
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('Type position out of range')
|
||||
|
||||
def getPositionNearType(self, tagSet, idx):
|
||||
if not self.__ambigiousTypes: self.__buildAmbigiousTagMap()
|
||||
"""Return the closest field position where given ASN.1 type is allowed.
|
||||
|
||||
Some ASN.1 serialization allow for skipping optional and defaulted fields.
|
||||
Some constructed ASN.1 types allow reordering of the fields. When recovering
|
||||
such objects it may be important to know at which field position, in field set,
|
||||
given *tagSet* is allowed at or past *idx* position.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tagSet: :class:`~pyasn1.type.tag.TagSet`
|
||||
ASN.1 type which field position to look up
|
||||
|
||||
idx: :py:class:`int`
|
||||
Field position at or past which to perform ASN.1 type look up
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :py:class:`int`
|
||||
Field position in fields set
|
||||
|
||||
Raises
|
||||
------
|
||||
: :class:`~pyasn1.error.PyAsn1Error`
|
||||
If *tagSet* is not present or not unique within callee *NamedTypes*
|
||||
or *idx* is out of fields range
|
||||
"""
|
||||
try:
|
||||
return idx+self.__ambigiousTypes[idx].getPositionByType(tagSet)
|
||||
return idx + self.__ambiguousTypes[idx].getPositionByType(tagSet)
|
||||
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error('Type position out of range')
|
||||
|
||||
def genMinTagSet(self):
|
||||
if self.__minTagSet is None:
|
||||
for t in self.__namedTypes:
|
||||
__type = t.getType()
|
||||
tagSet = getattr(__type,'getMinTagSet',__type.getTagSet)()
|
||||
if self.__minTagSet is None or tagSet < self.__minTagSet:
|
||||
self.__minTagSet = tagSet
|
||||
def __computeMinTagSet(self):
|
||||
minTagSet = None
|
||||
for namedType in self.__namedTypes:
|
||||
asn1Object = namedType.asn1Object
|
||||
|
||||
try:
|
||||
tagSet = asn1Object.minTagSet
|
||||
|
||||
except AttributeError:
|
||||
tagSet = asn1Object.tagSet
|
||||
|
||||
if minTagSet is None or tagSet < minTagSet:
|
||||
minTagSet = tagSet
|
||||
|
||||
return minTagSet or tag.TagSet()
|
||||
|
||||
@property
|
||||
def minTagSet(self):
|
||||
"""Return the minimal TagSet among ASN.1 type in callee *NamedTypes*.
|
||||
|
||||
Some ASN.1 types/serialization protocols require ASN.1 types to be
|
||||
arranged based on their numerical tag value. The *minTagSet* property
|
||||
returns that.
|
||||
|
||||
Returns
|
||||
-------
|
||||
: :class:`~pyasn1.type.tagset.TagSet`
|
||||
Minimal TagSet among ASN.1 types in callee *NamedTypes*
|
||||
"""
|
||||
return self.__minTagSet
|
||||
|
||||
def getTagMap(self, uniq=False):
|
||||
if self.__tagMap[uniq] is None:
|
||||
tagMap = tagmap.TagMap()
|
||||
for nt in self.__namedTypes:
|
||||
tagMap = tagMap.clone(
|
||||
nt.getType(), nt.getType().getTagMap(), uniq
|
||||
)
|
||||
self.__tagMap[uniq] = tagMap
|
||||
return self.__tagMap[uniq]
|
||||
|
||||
def __computeTagMaps(self, unique):
|
||||
presentTypes = {}
|
||||
skipTypes = {}
|
||||
defaultType = None
|
||||
for namedType in self.__namedTypes:
|
||||
tagMap = namedType.asn1Object.tagMap
|
||||
if isinstance(tagMap, NamedTypes.PostponedError):
|
||||
return tagMap
|
||||
for tagSet in tagMap:
|
||||
if unique and tagSet in presentTypes:
|
||||
return NamedTypes.PostponedError('Non-unique tagSet %s of %s at %s' % (tagSet, namedType, self))
|
||||
presentTypes[tagSet] = namedType.asn1Object
|
||||
skipTypes.update(tagMap.skipTypes)
|
||||
|
||||
if defaultType is None:
|
||||
defaultType = tagMap.defaultType
|
||||
elif tagMap.defaultType is not None:
|
||||
return NamedTypes.PostponedError('Duplicate default ASN.1 type at %s' % (self,))
|
||||
|
||||
return tagmap.TagMap(presentTypes, skipTypes, defaultType)
|
||||
|
||||
@property
|
||||
def tagMap(self):
|
||||
"""Return a *TagMap* object from tags and types recursively.
|
||||
|
||||
Return a :class:`~pyasn1.type.tagmap.TagMap` object by
|
||||
combining tags from *TagMap* objects of children types and
|
||||
associating them with their immediate child type.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
OuterType ::= CHOICE {
|
||||
innerType INTEGER
|
||||
}
|
||||
|
||||
Calling *.tagMap* on *OuterType* will yield a map like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
Integer.tagSet -> Choice
|
||||
"""
|
||||
return self.__nonUniqueTagMap
|
||||
|
||||
@property
|
||||
def tagMapUnique(self):
|
||||
"""Return a *TagMap* object from unique tags and types recursively.
|
||||
|
||||
Return a :class:`~pyasn1.type.tagmap.TagMap` object by
|
||||
combining tags from *TagMap* objects of children types and
|
||||
associating them with their immediate child type.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
OuterType ::= CHOICE {
|
||||
innerType INTEGER
|
||||
}
|
||||
|
||||
Calling *.tagMapUnique* on *OuterType* will yield a map like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
Integer.tagSet -> Choice
|
||||
|
||||
Note
|
||||
----
|
||||
|
||||
Duplicate *TagSet* objects found in the tree of children
|
||||
types would cause error.
|
||||
"""
|
||||
return self.__uniqueTagMap
|
||||
|
||||
@property
|
||||
def hasOptionalOrDefault(self):
|
||||
return self.__hasOptionalOrDefault
|
||||
|
||||
@property
|
||||
def namedTypes(self):
|
||||
return iter(self.__namedTypes)
|
||||
|
||||
@property
|
||||
def requiredComponents(self):
|
||||
return self.__requiredComponents
|
||||
|
209
third_party/python/pyasn1/pyasn1/type/namedval.py
vendored
209
third_party/python/pyasn1/pyasn1/type/namedval.py
vendored
@ -1,46 +1,181 @@
|
||||
#
|
||||
# This file is part of pyasn1 software.
|
||||
#
|
||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
||||
# License: http://pyasn1.sf.net/license.html
|
||||
#
|
||||
# ASN.1 named integers
|
||||
#
|
||||
from pyasn1 import error
|
||||
|
||||
__all__ = [ 'NamedValues' ]
|
||||
__all__ = ['NamedValues']
|
||||
|
||||
|
||||
class NamedValues(object):
|
||||
"""Create named values object.
|
||||
|
||||
The |NamedValues| object represents a collection of string names
|
||||
associated with numeric IDs. These objects are used for giving
|
||||
names to otherwise numerical values.
|
||||
|
||||
|NamedValues| objects are immutable and duck-type Python
|
||||
:class:`dict` object mapping ID to name and vice-versa.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
\*args: variable number of two-element :py:class:`tuple`
|
||||
\*\*kwargs: keyword parameters of:
|
||||
|
||||
name: :py:class:`str`
|
||||
Value name
|
||||
|
||||
value: :py:class:`int`
|
||||
A numerical value
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> nv = namedval.NamedValues('a', 'b', ('c', 0), d=1)
|
||||
>>> nv
|
||||
>>> {'c': 0, 'd': 1, 'a': 2, 'b': 3}
|
||||
>>> nv[0]
|
||||
'c'
|
||||
>>> nv['a']
|
||||
2
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.__names = {}
|
||||
self.__numbers = {}
|
||||
|
||||
anonymousNames = []
|
||||
|
||||
for namedValue in args:
|
||||
if isinstance(namedValue, (tuple, list)):
|
||||
try:
|
||||
name, number = namedValue
|
||||
|
||||
except ValueError:
|
||||
raise error.PyAsn1Error('Not a proper attribute-value pair %r' % (namedValue,))
|
||||
|
||||
class NamedValues:
|
||||
def __init__(self, *namedValues):
|
||||
self.nameToValIdx = {}; self.valToNameIdx = {}
|
||||
self.namedValues = ()
|
||||
automaticVal = 1
|
||||
for namedValue in namedValues:
|
||||
if isinstance(namedValue, tuple):
|
||||
name, val = namedValue
|
||||
else:
|
||||
name = namedValue
|
||||
val = automaticVal
|
||||
if name in self.nameToValIdx:
|
||||
raise error.PyAsn1Error('Duplicate name %s' % (name,))
|
||||
self.nameToValIdx[name] = val
|
||||
if val in self.valToNameIdx:
|
||||
raise error.PyAsn1Error('Duplicate value %s=%s' % (name, val))
|
||||
self.valToNameIdx[val] = name
|
||||
self.namedValues = self.namedValues + ((name, val),)
|
||||
automaticVal = automaticVal + 1
|
||||
def __str__(self): return str(self.namedValues)
|
||||
|
||||
def getName(self, value):
|
||||
if value in self.valToNameIdx:
|
||||
return self.valToNameIdx[value]
|
||||
anonymousNames.append(namedValue)
|
||||
continue
|
||||
|
||||
def getValue(self, name):
|
||||
if name in self.nameToValIdx:
|
||||
return self.nameToValIdx[name]
|
||||
|
||||
def __getitem__(self, i): return self.namedValues[i]
|
||||
def __len__(self): return len(self.namedValues)
|
||||
if name in self.__names:
|
||||
raise error.PyAsn1Error('Duplicate name %s' % (name,))
|
||||
|
||||
if number in self.__numbers:
|
||||
raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number))
|
||||
|
||||
self.__names[name] = number
|
||||
self.__numbers[number] = name
|
||||
|
||||
for name, number in kwargs.items():
|
||||
if name in self.__names:
|
||||
raise error.PyAsn1Error('Duplicate name %s' % (name,))
|
||||
|
||||
if number in self.__numbers:
|
||||
raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number))
|
||||
|
||||
self.__names[name] = number
|
||||
self.__numbers[number] = name
|
||||
|
||||
if anonymousNames:
|
||||
|
||||
number = self.__numbers and max(self.__numbers) + 1 or 0
|
||||
|
||||
for name in anonymousNames:
|
||||
|
||||
if name in self.__names:
|
||||
raise error.PyAsn1Error('Duplicate name %s' % (name,))
|
||||
|
||||
self.__names[name] = number
|
||||
self.__numbers[number] = name
|
||||
|
||||
number += 1
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r)' % (self.__class__.__name__, tuple(self.items()))
|
||||
|
||||
def __str__(self):
|
||||
return str(self.items())
|
||||
|
||||
def __eq__(self, other):
|
||||
return dict(self) == other
|
||||
|
||||
def __ne__(self, other):
|
||||
return dict(self) != other
|
||||
|
||||
def __lt__(self, other):
|
||||
return dict(self) < other
|
||||
|
||||
def __le__(self, other):
|
||||
return dict(self) <= other
|
||||
|
||||
def __gt__(self, other):
|
||||
return dict(self) > other
|
||||
|
||||
def __ge__(self, other):
|
||||
return dict(self) >= other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.items())
|
||||
|
||||
# Python dict protocol (read-only)
|
||||
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
return self.__numbers[key]
|
||||
|
||||
except KeyError:
|
||||
return self.__names[key]
|
||||
|
||||
def __len__(self):
|
||||
return len(self.__names)
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.__names or key in self.__numbers
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.__names)
|
||||
|
||||
def values(self):
|
||||
return iter(self.__numbers)
|
||||
|
||||
def keys(self):
|
||||
return iter(self.__names)
|
||||
|
||||
def items(self):
|
||||
for name in self.__names:
|
||||
yield name, self.__names[name]
|
||||
|
||||
# support merging
|
||||
|
||||
def __add__(self, namedValues):
|
||||
return self.__class__(*self.namedValues + namedValues)
|
||||
def __radd__(self, namedValues):
|
||||
return self.__class__(*namedValues + tuple(self))
|
||||
|
||||
def clone(self, *namedValues):
|
||||
return self.__class__(*tuple(self) + namedValues)
|
||||
return self.__class__(*tuple(self.items()) + tuple(namedValues.items()))
|
||||
|
||||
# XXX clone/subtype?
|
||||
# XXX clone/subtype?
|
||||
|
||||
def clone(self, *args, **kwargs):
|
||||
new = self.__class__(*args, **kwargs)
|
||||
return self + new
|
||||
|
||||
# legacy protocol
|
||||
|
||||
def getName(self, value):
|
||||
if value in self.__numbers:
|
||||
return self.__numbers[value]
|
||||
|
||||
def getValue(self, name):
|
||||
if name in self.__names:
|
||||
return self.__names[name]
|
||||
|
||||
def getValues(self, *names):
|
||||
try:
|
||||
return [self.__names[name] for name in names]
|
||||
|
||||
except KeyError:
|
||||
raise error.PyAsn1Error(
|
||||
'Unknown bit identifier(s): %s' % (set(names).difference(self.__names),)
|
||||
)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user