Forráskód Böngészése

HUE-2877 [desktop] Add pyasn1 and ndg_httpsclient to support SSL Server Name Indication

Erick Tryzelaar 10 éve
szülő
commit
e5e78f7938
92 módosított fájl, 14233 hozzáadás és 0 törlés
  1. 12 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/MANIFEST.in
  2. 121 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/PKG-INFO
  3. 32 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/documentation/Makefile
  4. 19 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/__init__.py
  5. 9 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/__init__.py
  6. 131 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/https.py
  7. 98 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/ssl_context_util.py
  8. 237 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/ssl_peer_verification.py
  9. 282 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/ssl_socket.py
  10. 153 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/subj_alt_name.py
  11. 26 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/README
  12. 29 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/__init__.py
  13. 20 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/pki/ca/08bd99c7.0
  14. 20 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/pki/ca/ade0138a.0
  15. 82 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/pki/localhost.crt
  16. 27 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/pki/localhost.key
  17. 2 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/scripts/openssl_https_server.sh
  18. 122 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/test_https.py
  19. 56 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/test_urllib2.py
  20. 62 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/test_utils.py
  21. 78 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/urllib2_build_opener.py
  22. 414 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/utils.py
  23. 5 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/setup.cfg
  24. 151 0
      desktop/core/ext-py/ndg_httpsclient-0.4.0/setup.py
  25. 343 0
      desktop/core/ext-py/pyasn1-0.1.8/CHANGES
  26. 24 0
      desktop/core/ext-py/pyasn1-0.1.8/LICENSE
  27. 3 0
      desktop/core/ext-py/pyasn1-0.1.8/MANIFEST.in
  28. 26 0
      desktop/core/ext-py/pyasn1-0.1.8/PKG-INFO
  29. 67 0
      desktop/core/ext-py/pyasn1-0.1.8/README
  30. 10 0
      desktop/core/ext-py/pyasn1-0.1.8/THANKS
  31. 36 0
      desktop/core/ext-py/pyasn1-0.1.8/TODO
  32. 503 0
      desktop/core/ext-py/pyasn1-0.1.8/doc/codecs.html
  33. 436 0
      desktop/core/ext-py/pyasn1-0.1.8/doc/constraints.html
  34. 377 0
      desktop/core/ext-py/pyasn1-0.1.8/doc/constructed.html
  35. 156 0
      desktop/core/ext-py/pyasn1-0.1.8/doc/intro.html
  36. 2405 0
      desktop/core/ext-py/pyasn1-0.1.8/doc/pyasn1-tutorial.html
  37. 794 0
      desktop/core/ext-py/pyasn1-0.1.8/doc/scalar.html
  38. 233 0
      desktop/core/ext-py/pyasn1-0.1.8/doc/tagging.html
  39. 8 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/__init__.py
  40. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/__init__.py
  41. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/ber/__init__.py
  42. 841 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/ber/decoder.py
  43. 433 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/ber/encoder.py
  44. 8 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/ber/eoo.py
  45. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/cer/__init__.py
  46. 35 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/cer/decoder.py
  47. 130 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/cer/encoder.py
  48. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/der/__init__.py
  49. 9 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/der/decoder.py
  50. 32 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/der/encoder.py
  51. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/compat/__init__.py
  52. 10 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/compat/binary.py
  53. 10 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/compat/iterfunc.py
  54. 20 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/compat/octets.py
  55. 110 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/debug.py
  56. 3 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/error.py
  57. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/__init__.py
  58. 277 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/base.py
  59. 64 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/char.py
  60. 200 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/constraint.py
  61. 3 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/error.py
  62. 149 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/namedtype.py
  63. 58 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/namedval.py
  64. 128 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/tag.py
  65. 66 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/tagmap.py
  66. 1156 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/univ.py
  67. 17 0
      desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/useful.py
  68. 5 0
      desktop/core/ext-py/pyasn1-0.1.8/setup.cfg
  69. 104 0
      desktop/core/ext-py/pyasn1-0.1.8/setup.py
  70. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/test/__init__.py
  71. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/__init__.py
  72. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/ber/__init__.py
  73. 22 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/ber/suite.py
  74. 727 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/ber/test_decoder.py
  75. 483 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/ber/test_encoder.py
  76. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/cer/__init__.py
  77. 22 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/cer/suite.py
  78. 31 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/cer/test_decoder.py
  79. 176 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/cer/test_encoder.py
  80. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/der/__init__.py
  81. 22 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/der/suite.py
  82. 31 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/der/test_decoder.py
  83. 51 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/der/test_encoder.py
  84. 29 0
      desktop/core/ext-py/pyasn1-0.1.8/test/codec/suite.py
  85. 26 0
      desktop/core/ext-py/pyasn1-0.1.8/test/suite.py
  86. 1 0
      desktop/core/ext-py/pyasn1-0.1.8/test/type/__init__.py
  87. 20 0
      desktop/core/ext-py/pyasn1-0.1.8/test/type/suite.py
  88. 280 0
      desktop/core/ext-py/pyasn1-0.1.8/test/type/test_constraint.py
  89. 91 0
      desktop/core/ext-py/pyasn1-0.1.8/test/type/test_namedtype.py
  90. 22 0
      desktop/core/ext-py/pyasn1-0.1.8/test/type/test_namedval.py
  91. 115 0
      desktop/core/ext-py/pyasn1-0.1.8/test/type/test_tag.py
  92. 596 0
      desktop/core/ext-py/pyasn1-0.1.8/test/type/test_univ.py

+ 12 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/MANIFEST.in

@@ -0,0 +1,12 @@
+#
+# MANIFEST.in file to enable inclusion of unit test data files and config
+# 
+# NDG HTTPS Client Package
+# 
+# P J Kershaw 17/01/12
+# 
+# Copyright (C) 2012 STFC
+# 
+# Licence: BSD - See LICENCE file for details
+recursive-include ndg/httpsclient/test *.crt *.key *.sh README
+recursive-include documentation Makefile

+ 121 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/PKG-INFO

@@ -0,0 +1,121 @@
+Metadata-Version: 1.1
+Name: ndg_httpsclient
+Version: 0.4.0
+Summary: Provides enhanced HTTPS support for httplib and urllib2 using PyOpenSSL
+Home-page: https://github.com/cedadev/ndg_httpsclient/
+Author: Richard Wilkinson and Philip Kershaw
+Author-email: Philip.Kershaw@stfc.ac.uk
+License: BSD - See LICENCE file for details
+Description: 
+        This is a HTTPS client implementation for httplib and urllib2 based on
+        PyOpenSSL.  PyOpenSSL provides a more fully featured SSL implementation over the
+        default provided with Python and importantly enables full verification of the
+        SSL peer.
+        
+        Releases
+        ========
+        0.4.0
+        -----
+         * Made dual compatible with Python 2 / 3.
+         
+        0.3.3
+        -----
+         * Fix to add in AnotherName for ``subjectAltNames`` field - added for support for CACert issued
+           certs (thanks to Gu1).
+         * Fix to HTTP Basic Auth option for ``ndg.httpsclient.utils.main``
+         * Fix to ``ServerSSLCertVerification`` so that it can pass a function-based callback instead of using ``__call__``. In newer versions of OpenSSL (>= 0.14) the latter failed because of a request for ``__name__`` attribute.
+        
+        0.3.2
+        -----
+         * Fix to SubjectAltNames support check - should only be enabled if pyasn1 is 
+           installed.
+         * Fix to open_url: HTTP Request object was being created inside if headers is 
+           None block - now corrected to create regardless.
+         * Added http basic auth support to script. (Thanks to Willem van Engen)
+         
+        0.3.1
+        -----
+         * extended utils functions to support keyword for passing additional urllib2
+           handlers.
+        
+        0.3.0
+        -----
+         * Added ndg.httpsclient.utils.fetch_stream_from_url function and added
+           parameter for data to post in open_url and fetch_* methods.
+         * fix to ndg.httpsclient.utils module _should_use_proxy and open_url functions
+        
+        0.2.0
+        -----
+         * added support for SSL verification with subjectAltNames using pyasn1
+         * fixed minor bug - SSL cert DN prefix matching
+        
+        0.1.0
+        -----
+        Initial release
+        
+        Prerequisites
+        =============
+        This has been developed and tested for Python 2.6 and 2.7 with pyOpenSSL 0.13 and 0.14.  
+        Version 0.4.0 tested with pyOpenSSL 0.15.1 and Python 2.7 and 3.4.  Note that proxy support 
+        is only available from Python 2.6.2 onwards.  pyasn1 is required for correct SSL 
+        verification with subjectAltNames.
+        
+        Installation
+        ============
+        Installation can be performed using easy_install or pip.
+        
+        Running ndg_httpclient
+        ======================
+        A simple script for fetching data using HTTP or HTTPS GET from a specified URL.
+        
+        Parameter:
+        
+        ``url``
+          The URL of the resource to be fetched
+        
+        Options:
+        
+        ``-h, --help``
+          Show help message and exit.
+        
+        ``-c FILE, --certificate=FILE``
+          Certificate file - defaults to ``$HOME/credentials.pem``
+        
+        ``-k FILE, --private-key=FILE``
+          Private key file - defaults to the certificate file
+        
+        ``-t DIR, --ca-certificate-dir=DIR``
+          Trusted CA certificate file directory.
+        
+        ``-d, --debug``
+          Print debug information - this may be useful in solving problems with HTTP or 
+          HTTPS access to a server.
+            
+        ``-p FILE, --post-data-file=FILE``
+          POST data file
+            
+        ``-f FILE, --fetch=FILE``
+          Output file
+            
+        ``-n, --no-verify-peer``
+          Skip verification of peer certificate.
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 3 - Alpha
+Classifier: Environment :: Console
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: End Users/Desktop
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: Intended Audience :: Science/Research
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Natural Language :: English
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Programming Language :: Python
+Classifier: Topic :: Security
+Classifier: Topic :: Internet
+Classifier: Topic :: Scientific/Engineering
+Classifier: Topic :: System :: Distributed Computing
+Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
+Classifier: Topic :: Software Development :: Libraries :: Python Modules

+ 32 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/documentation/Makefile

@@ -0,0 +1,32 @@
+#
+# Makefile to generate epydoc documentation for the NDG HTTPS Client Package
+#
+# @author P J Kershaw 17/01/12
+#
+
+# @copyright: (C) 2012 STFC
+#
+# @license: BSD - see LICENSE file for details
+#
+# $Id$
+
+# Generate HTML from embedded epydoc text in source code.
+EPYDOC=epydoc
+EPYDOC_INDIR=../ndg
+EPYDOC_OUTDIR=.
+EPYDOC_NAME='NDG HTTPS Client'
+EPYDOC_LOGFILE=epydoc.log
+EPYDOC_OPTS=--no-frames --include-log --graph=all -v --debug
+ZIP=zip
+ZIP_OUTFILE=./documentation.zip
+ZIP_INFILES=./*.*
+
+epydoc:
+	${EPYDOC} ${EPYDOC_INDIR} -o ${EPYDOC_OUTDIR} --name ${EPYDOC_NAME} \
+	${EPYDOC_OPTS} > ${EPYDOC_LOGFILE}
+    
+zip:
+	${ZIP} ${ZIP_OUTFILE} ${ZIP_INFILES}    
+
+clean:
+	rm -f *.txt *.html *.gif *.css *.js *.png *.log

+ 19 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/__init__.py

@@ -0,0 +1,19 @@
+"""ndg_httpsclient - PyOpenSSL utility to make a httplib-like interface suitable
+for use with urllib2
+
+This is a setuptools namespace_package.  DO NOT place any other
+code in this file!  There is no guarantee that it will be installed
+with easy_install.  See:
+
+http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+
+... for details.
+"""
+__author__ = "P J Kershaw"
+__date__ = "06/01/12"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+
+__import__('pkg_resources').declare_namespace(__name__)

+ 9 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/__init__.py

@@ -0,0 +1,9 @@
+"""ndg_httpsclient - PyOpenSSL utility to make a httplib-like interface suitable
+for use with urllib2
+"""
+__author__ = "P J Kershaw (STFC) and Richard Wilkinson (Tessella)"
+__date__ = "09/12/11"
+__copyright__ = "(C) 2011 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'

+ 131 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/https.py

@@ -0,0 +1,131 @@
+"""ndg_httpsclient HTTPS module containing PyOpenSSL implementation of
+httplib.HTTPSConnection
+
+PyOpenSSL utility to make a httplib-like interface suitable for use with 
+urllib2
+"""
+__author__ = "P J Kershaw (STFC)"
+__date__ = "09/12/11"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+import logging
+import socket
+import sys
+
+if sys.version_info[0] > 2:
+    from http.client import HTTPS_PORT
+    from http.client import HTTPConnection
+
+    from urllib.request import AbstractHTTPHandler
+else:
+    from httplib import HTTPS_PORT
+    from httplib import HTTPConnection
+
+    from urllib2 import AbstractHTTPHandler
+
+
+from OpenSSL import SSL
+
+from ndg.httpsclient.ssl_socket import SSLSocket
+
+log = logging.getLogger(__name__)
+
+
+class HTTPSConnection(HTTPConnection):
+    """This class allows communication via SSL using PyOpenSSL.
+    It is based on httplib.HTTPSConnection, modified to use PyOpenSSL.
+
+    Note: This uses the constructor inherited from HTTPConnection to allow it to
+    be used with httplib and HTTPSContextHandler. To use the class directly with
+    an SSL context set ssl_context after construction.
+    
+    @cvar default_port: default port for this class (443)
+    @type default_port: int
+    @cvar default_ssl_method: default SSL method used if no SSL context is
+    explicitly set - defaults to version 2/3.
+    @type default_ssl_method: int
+    """
+    default_port = HTTPS_PORT
+    default_ssl_method = SSL.SSLv23_METHOD
+    
+    def __init__(self, host, port=None, strict=None,
+                 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, ssl_context=None):
+        HTTPConnection.__init__(self, host, port, strict, timeout)
+        if not hasattr(self, 'ssl_context'):
+            self.ssl_context = None
+
+        if ssl_context is not None:
+            if not isinstance(ssl_context, SSL.Context):
+                raise TypeError('Expecting OpenSSL.SSL.Context type for "'
+                                'ssl_context" keyword; got %r instead' %
+                                ssl_context)
+                
+            self.ssl_context = ssl_context
+            
+    def connect(self):
+        """Create SSL socket and connect to peer
+        """
+        if getattr(self, 'ssl_context', None):
+            if not isinstance(self.ssl_context, SSL.Context):
+                raise TypeError('Expecting OpenSSL.SSL.Context type for "'
+                                'ssl_context" attribute; got %r instead' %
+                                self.ssl_context)
+            ssl_context = self.ssl_context
+        else:
+            ssl_context = SSL.Context(self.__class__.default_ssl_method)
+
+        sock = socket.create_connection((self.host, self.port), self.timeout)
+        
+        # Tunnel if using a proxy - ONLY available for Python 2.6.2 and above      
+        if getattr(self, '_tunnel_host', None):
+            self.sock = sock
+            self._tunnel()
+            
+        self.sock = SSLSocket(ssl_context, sock)
+        
+        # Go to client mode.
+        self.sock.set_connect_state()
+
+    def close(self):
+        """Close socket and shut down SSL connection"""
+        if hasattr(self.sock, "close"):
+            self.sock.close()
+        
+        
+class HTTPSContextHandler(AbstractHTTPHandler):
+    '''HTTPS handler that allows a SSL context to be set for the SSL
+    connections.
+    '''
+    https_request = AbstractHTTPHandler.do_request_
+
+    def __init__(self, ssl_context, debuglevel=0):
+        """
+        @param ssl_context:SSL context
+        @type ssl_context: OpenSSL.SSL.Context
+        @param debuglevel: debug level for HTTPSHandler
+        @type debuglevel: int
+        """
+        AbstractHTTPHandler.__init__(self, debuglevel)
+
+        if ssl_context is not None:
+            if not isinstance(ssl_context, SSL.Context):
+                raise TypeError('Expecting OpenSSL.SSL.Context type for "'
+                                'ssl_context" keyword; got %r instead' %
+                                ssl_context)
+            self.ssl_context = ssl_context
+        else:
+            self.ssl_context = SSL.Context(SSL.TLSv1_METHOD)
+
+    def https_open(self, req):
+        """Opens HTTPS request
+        @param req: HTTP request
+        @return: HTTP Response object
+        """
+        # Make a custom class extending HTTPSConnection, with the SSL context
+        # set as a class variable so that it is available to the connect method.
+        customHTTPSContextConnection = type('CustomHTTPSContextConnection',
+                                            (HTTPSConnection, object),
+                                            {'ssl_context': self.ssl_context})
+        return self.do_open(customHTTPSContextConnection, req)

+ 98 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/ssl_context_util.py

@@ -0,0 +1,98 @@
+"""ndg_httpsclient SSL Context utilities module containing convenience routines
+for setting SSL context configuration.
+
+"""
+__author__ = "P J Kershaw (STFC)"
+__date__ = "09/12/11"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+import sys
+
+if sys.version_info[0] > 2:
+    import urllib.parse as urlparse_
+else:
+    import urlparse as urlparse_
+
+from OpenSSL import SSL
+
+from ndg.httpsclient.ssl_peer_verification import ServerSSLCertVerification
+
+
+class SSlContextConfig(object):
+    """
+    Holds configuration options for creating a SSL context. This is used as a
+    template to create the contexts with specific verification callbacks.
+    """
+    def __init__(self, key_file=None, cert_file=None, pem_file=None, ca_dir=None,
+                 verify_peer=False):
+        self.key_file = key_file
+        self.cert_file = cert_file
+        self.pem_file = pem_file
+        self.ca_dir = ca_dir
+        self.verify_peer = verify_peer
+
+
+def make_ssl_context_from_config(ssl_config=False, url=None):
+    return make_ssl_context(ssl_config.key_file, ssl_config.cert_file,
+                            ssl_config.pem_file, ssl_config.ca_dir,
+                            ssl_config.verify_peer, url)
+
+
+def make_ssl_context(key_file=None, cert_file=None, pem_file=None, ca_dir=None,
+                     verify_peer=False, url=None, method=SSL.TLSv1_METHOD,
+                     key_file_passphrase=None):
+    """
+    Creates SSL context containing certificate and key file locations.
+    """
+    ssl_context = SSL.Context(method)
+    
+    # Key file defaults to certificate file if present.
+    if cert_file:
+        ssl_context.use_certificate_file(cert_file)
+        
+    if key_file_passphrase:
+        passwd_cb = lambda max_passphrase_len, set_prompt, userdata: \
+                           key_file_passphrase 
+        ssl_context.set_passwd_cb(passwd_cb)
+        
+    if key_file:
+        ssl_context.use_privatekey_file(key_file)
+    elif cert_file:
+        ssl_context.use_privatekey_file(cert_file)
+
+    if pem_file or ca_dir:
+        ssl_context.load_verify_locations(pem_file, ca_dir)
+
+    def _callback(conn, x509, errnum, errdepth, preverify_ok):
+        """Default certification verification callback.
+        Performs no checks and returns the status passed in.
+        """
+        return preverify_ok
+    
+    verify_callback = _callback
+
+    if verify_peer:
+        ssl_context.set_verify_depth(9)
+        if url:
+            set_peer_verification_for_url_hostname(ssl_context, url)
+        else:
+            ssl_context.set_verify(SSL.VERIFY_PEER, verify_callback)
+    else:
+        ssl_context.set_verify(SSL.VERIFY_NONE, verify_callback)
+        
+    return ssl_context
+
+
+def set_peer_verification_for_url_hostname(ssl_context, url, 
+                                           if_verify_enabled=False):
+    '''Convenience routine to set peer verification callback based on
+    ServerSSLCertVerification class'''
+    if not if_verify_enabled or (ssl_context.get_verify_mode() & SSL.VERIFY_PEER):
+        urlObj = urlparse_.urlparse(url)
+        hostname = urlObj.hostname
+        server_ssl_cert_verif = ServerSSLCertVerification(hostname=hostname)
+        verify_callback_ = server_ssl_cert_verif.get_verify_server_cert_func()
+        ssl_context.set_verify(SSL.VERIFY_PEER, verify_callback_)
+

+ 237 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/ssl_peer_verification.py

@@ -0,0 +1,237 @@
+"""ndg_httpsclient - module containing SSL peer verification class.
+"""
+__author__ = "P J Kershaw (STFC)"
+__date__ = "09/12/11"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+import re
+import logging
+log = logging.getLogger(__name__)
+
+try:
+    from ndg.httpsclient.subj_alt_name import SubjectAltName
+    from pyasn1.codec.der import decoder as der_decoder
+    SUBJ_ALT_NAME_SUPPORT = True
+    
+except ImportError as e:
+    SUBJ_ALT_NAME_SUPPORT = False
+    SUBJ_ALT_NAME_SUPPORT_MSG = (
+        'SubjectAltName support is disabled - check pyasn1 package '
+        'installation to enable'
+    )
+    import warnings
+    warnings.warn(SUBJ_ALT_NAME_SUPPORT_MSG)
+
+
+class ServerSSLCertVerification(object):
+    """Check server identity.  If hostname doesn't match, allow match of
+    host's Distinguished Name against server DN setting"""
+    DN_LUT = {
+        'commonName':               'CN',
+        'organisationalUnitName':   'OU',
+        'organisation':             'O',
+        'countryName':              'C',
+        'emailAddress':             'EMAILADDRESS',
+        'localityName':             'L',
+        'stateOrProvinceName':      'ST',
+        'streetAddress':            'STREET',
+        'domainComponent':          'DC',
+        'userid':                   'UID'
+    }
+    SUBJ_ALT_NAME_EXT_NAME = 'subjectAltName'
+    PARSER_RE_STR = '/(%s)=' % '|'.join(list(DN_LUT.keys()) + list(DN_LUT.values()))
+    PARSER_RE = re.compile(PARSER_RE_STR)
+
+    __slots__ = ('__hostname', '__certDN', '__subj_alt_name_match')
+
+    def __init__(self, certDN=None, hostname=None, subj_alt_name_match=True):
+        """Override parent class __init__ to enable setting of certDN
+        setting
+
+        @type certDN: string
+        @param certDN: Set the expected Distinguished Name of the
+        server to avoid errors matching hostnames.  This is useful
+        where the hostname is not fully qualified
+        @type hostname: string
+        @param hostname: hostname to match against peer certificate 
+        subjectAltNames or subject common name
+        @type subj_alt_name_match: bool
+        @param subj_alt_name_match: flag to enable/disable matching of hostname
+        against peer certificate subjectAltNames.  Nb. A setting of True will 
+        be ignored if the pyasn1 package is not installed
+        """
+        self.__certDN = None
+        self.__hostname = None
+
+        if certDN is not None:
+            self.certDN = certDN
+
+        if hostname is not None:
+            self.hostname = hostname
+        
+        if subj_alt_name_match:
+            if not SUBJ_ALT_NAME_SUPPORT:
+                log.warning('Overriding "subj_alt_name_match" keyword setting: '
+                            'peer verification with subjectAltNames is disabled')
+                self.__subj_alt_name_match = False
+            else:    
+                self.__subj_alt_name_match = True
+        else:
+            log.debug('Disabling peer verification with subject '
+                      'subjectAltNames!')
+            self.__subj_alt_name_match = False
+
+    def __call__(self, connection, peerCert, errorStatus, errorDepth,
+                 preverifyOK):
+        """Verify server certificate
+
+        @type connection: OpenSSL.SSL.Connection
+        @param connection: SSL connection object
+        @type peerCert: basestring
+        @param peerCert: server host certificate as OpenSSL.crypto.X509
+        instance
+        @type errorStatus: int
+        @param errorStatus: error status passed from caller.  This is the value
+        returned by the OpenSSL C function X509_STORE_CTX_get_error().  Look-up
+        x509_vfy.h in the OpenSSL source to get the meanings of the different
+        codes.  PyOpenSSL doesn't help you!
+        @type errorDepth: int
+        @param errorDepth: a non-negative integer representing where in the
+        certificate chain the error occurred. If it is zero it occured in the
+        end entity certificate, one if it is the certificate which signed the
+        end entity certificate and so on.
+
+        @type preverifyOK: int
+        @param preverifyOK: the error status - 0 = Error, 1 = OK of the current
+        SSL context irrespective of any verification checks done here.  If this
+        function yields an OK status, it should enforce the preverifyOK value
+        so that any error set upstream overrides and is honoured.
+        @rtype: int
+        @return: status code - 0/False = Error, 1/True = OK
+        """
+        if peerCert.has_expired():
+            # Any expired certificate in the chain should result in an error
+            log.error('Certificate %r in peer certificate chain has expired',
+                      peerCert.get_subject())
+
+            return False
+
+        elif errorDepth == 0:
+            # Only interested in DN of last certificate in the chain - this must
+            # match the expected Server DN setting
+            peerCertSubj = peerCert.get_subject()
+            peerCertDN = peerCertSubj.get_components()
+            peerCertDN.sort()
+
+            if self.certDN is None:
+                # Check hostname against peer certificate CN field instead:
+                if self.hostname is None:
+                    log.error('No "hostname" or "certDN" set to check peer '
+                              'certificate against')
+                    return False
+
+                # Check for subject alternative names
+                if self.__subj_alt_name_match:
+                    dns_names = self._get_subj_alt_name(peerCert)
+                    if self.hostname in dns_names:
+                        return preverifyOK
+                
+                # If no subjectAltNames, default to check of subject Common Name   
+                if peerCertSubj.commonName == self.hostname:
+                    return preverifyOK
+                else:
+                    log.error('Peer certificate CN %r doesn\'t match the '
+                              'expected CN %r', peerCertSubj.commonName,
+                              self.hostname)
+                    return False
+            else:
+                if peerCertDN == self.certDN:
+                    return preverifyOK
+                else:
+                    log.error('Peer certificate DN %r doesn\'t match the '
+                              'expected DN %r', peerCertDN, self.certDN)
+                    return False
+        else:
+            return preverifyOK
+
+    def get_verify_server_cert_func(self):
+        def verify_server_cert(connection, peerCert, errorStatus, errorDepth,
+                preverifyOK):
+            return self.__call__(connection, peerCert, errorStatus,
+                                 errorDepth, preverifyOK)
+        
+        return verify_server_cert
+
+    @classmethod
+    def _get_subj_alt_name(cls, peer_cert):
+        '''Extract subjectAltName DNS name settings from certificate extensions
+        
+        @param peer_cert: peer certificate in SSL connection.  subjectAltName
+        settings if any will be extracted from this
+        @type peer_cert: OpenSSL.crypto.X509
+        '''
+        # Search through extensions
+        dns_name = []
+        general_names = SubjectAltName()
+        for i in range(peer_cert.get_extension_count()):
+            ext = peer_cert.get_extension(i)
+            ext_name = ext.get_short_name()
+            if ext_name == cls.SUBJ_ALT_NAME_EXT_NAME:
+                # PyOpenSSL returns extension data in ASN.1 encoded form
+                ext_dat = ext.get_data()
+                decoded_dat = der_decoder.decode(ext_dat, 
+                                                 asn1Spec=general_names)
+                
+                for name in decoded_dat:
+                    if isinstance(name, SubjectAltName):
+                        for entry in range(len(name)):
+                            component = name.getComponentByPosition(entry)
+                            dns_name.append(str(component.getComponent()))
+                            
+        return dns_name
+        
+    def _getCertDN(self):
+        return self.__certDN
+
+    def _setCertDN(self, val):
+        if isinstance(val, str):
+            # Allow for quoted DN
+            certDN = val.strip('"')
+
+            dnFields = self.__class__.PARSER_RE.split(certDN)
+            if len(dnFields) < 2:
+                raise TypeError('Error parsing DN string: "%s"' % certDN)
+
+            self.__certDN = list(zip(dnFields[1::2], dnFields[2::2]))
+            self.__certDN.sort()
+
+        elif not isinstance(val, list):
+            for i in val:
+                if not len(i) == 2:
+                    raise TypeError('Expecting list of two element DN field, '
+                                    'DN field value pairs for "certDN" '
+                                    'attribute')
+            self.__certDN = val
+        else:
+            raise TypeError('Expecting list or string type for "certDN" '
+                            'attribute')
+
+    certDN = property(fget=_getCertDN,
+                      fset=_setCertDN,
+                      doc="Distinguished Name for Server Certificate")
+
+    # Get/Set Property methods
+    def _getHostname(self):
+        return self.__hostname
+
+    def _setHostname(self, val):
+        if not isinstance(val, str):
+            raise TypeError("Expecting string type for hostname "
+                                 "attribute")
+        self.__hostname = val
+
+    hostname = property(fget=_getHostname,
+                        fset=_setHostname,
+                        doc="hostname of server")

+ 282 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/ssl_socket.py

@@ -0,0 +1,282 @@
+"""PyOpenSSL utilities including HTTPSSocket class which wraps PyOpenSSL
+SSL connection into a httplib-like interface suitable for use with urllib2
+
+"""
+__author__ = "P J Kershaw"
+__date__ = "21/12/10"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+
+from datetime import datetime
+import logging
+import socket
+from io import BytesIO
+
+from OpenSSL import SSL
+
+log = logging.getLogger(__name__)
+
+
+class SSLSocket(object):
+    """SSL Socket class wraps pyOpenSSL's SSL.Connection class implementing
+    the makefile method so that it is compatible with the standard socket
+    interface and usable with httplib.
+
+    @cvar default_buf_size: default buffer size for recv operations in the
+    makefile method
+    @type default_buf_size: int
+    """
+    default_buf_size = 8192
+
+    def __init__(self, ctx, sock=None):
+        """Create SSL socket object
+
+        @param ctx: SSL context
+        @type ctx: OpenSSL.SSL.Context
+        @param sock: underlying socket object
+        @type sock: socket.socket
+        """
+        if sock is not None:
+            self.socket = sock
+        else:
+            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+
+        self.__ssl_conn = SSL.Connection(ctx, self.socket)
+        self.buf_size = self.__class__.default_buf_size
+        self._makefile_refs = 0
+
+    def __del__(self):
+        """Close underlying socket when this object goes out of scope
+        """
+        self.close()
+
+    @property
+    def buf_size(self):
+        """Buffer size for makefile method recv() operations"""
+        return self.__buf_size
+
+    @buf_size.setter
+    def buf_size(self, value):
+        """Buffer size for makefile method recv() operations"""
+        if not isinstance(value, int):
+            raise TypeError('Expecting int type for "buf_size"; '
+                            'got %r instead' % type(value))
+        self.__buf_size = value
+
+    def close(self):
+        """Shutdown the SSL connection and call the close method of the
+        underlying socket"""
+        if self._makefile_refs < 1:        
+            try:
+                self.__ssl_conn.shutdown()
+            except (SSL.Error, SSL.SysCallError):
+                # Make errors on shutdown non-fatal
+                pass
+        else:
+            self._makefile_refs -= 1
+
+    def set_shutdown(self, mode):
+        """Set the shutdown state of the Connection.
+        @param mode: bit vector of either or both of SENT_SHUTDOWN and
+        RECEIVED_SHUTDOWN
+        """
+        self.__ssl_conn.set_shutdown(mode)
+
+    def get_shutdown(self):
+        """Get the shutdown state of the Connection.
+        @return: bit vector of either or both of SENT_SHUTDOWN and
+        RECEIVED_SHUTDOWN
+        """
+        return self.__ssl_conn.get_shutdown()
+
+    def bind(self, addr):
+        """bind to the given address - calls method of the underlying socket
+        @param addr: address/port number tuple
+        @type addr: tuple"""
+        self.__ssl_conn.bind(addr)
+
+    def listen(self, backlog):
+        """Listen for connections made to the socket.
+
+        @param backlog: specifies the maximum number of queued connections and
+        should be at least 1; the maximum value is system-dependent (usually 5).
+        @param backlog: int
+        """
+        self.__ssl_conn.listen(backlog)
+
+    def set_accept_state(self):
+        """Set the connection to work in server mode. The handshake will be
+        handled automatically by read/write"""
+        self.__ssl_conn.set_accept_state()
+
+    def accept(self):
+        """Accept an SSL connection.
+
+        @return: pair (ssl, addr) where ssl is a new SSL connection object and
+        addr is the address bound to the other end of the SSL connection.
+        @rtype: tuple
+        """
+        return self.__ssl_conn.accept()
+
+    def set_connect_state(self):
+        """Set the connection to work in client mode. The handshake will be
+        handled automatically by read/write"""
+        self.__ssl_conn.set_connect_state()
+
+    def connect(self, addr):
+        """Call the connect method of the underlying socket and set up SSL on
+        the socket, using the Context object supplied to this Connection object
+        at creation.
+
+        @param addr: address/port number pair
+        @type addr: tuple
+        """
+        self.__ssl_conn.connect(addr)
+
+    def shutdown(self, how):
+        """Send the shutdown message to the Connection.
+
+        @param how: for socket.socket this flag determines whether read, write
+        or both type operations are supported.  OpenSSL.SSL.Connection doesn't
+        support this so this parameter is IGNORED
+        @return: true if the shutdown message exchange is completed and false
+        otherwise (in which case you call recv() or send() when the connection
+        becomes readable/writeable.
+        @rtype: bool
+        """
+        return self.__ssl_conn.shutdown()
+
+    def renegotiate(self):
+        """Renegotiate this connection's SSL parameters."""
+        return self.__ssl_conn.renegotiate()
+
+    def pending(self):
+        """@return: numbers of bytes that can be safely read from the SSL
+        buffer.
+        @rtype: int
+        """
+        return self.__ssl_conn.pending()
+
+    def send(self, data, *flags_arg):
+        """Send data to the socket. Nb. The optional flags argument is ignored.
+        - retained for compatibility with socket.socket interface
+
+        @param data: data to send down the socket
+        @type data: string
+        """
+        return self.__ssl_conn.send(data)
+
+    def sendall(self, data):
+        self.__ssl_conn.sendall(data)
+
+    def recv(self, size=default_buf_size):
+        """Receive data from the Connection.
+
+        @param size: The maximum amount of data to be received at once
+        @type size: int
+        @return: data received.
+        @rtype: string
+        """
+        return self.__ssl_conn.recv(size)
+
+    def setblocking(self, mode):
+        """Set this connection's underlying socket blocking _mode_.
+
+        @param mode: blocking mode
+        @type mode: int
+        """
+        self.__ssl_conn.setblocking(mode)
+
+    def fileno(self):
+        """
+        @return: file descriptor number for the underlying socket
+        @rtype: int
+        """
+        return self.__ssl_conn.fileno()
+
+    def getsockopt(self, *args):
+        """See socket.socket.getsockopt
+        """
+        return self.__ssl_conn.getsockopt(*args)
+
+    def setsockopt(self, *args):
+        """See socket.socket.setsockopt
+
+        @return: value of the given socket option
+        @rtype: int/string
+        """
+        return self.__ssl_conn.setsockopt(*args)
+
+    def state_string(self):
+        """Return the SSL state of this connection."""
+        return self.__ssl_conn.state_string()
+
+    def makefile(self, *args):
+        """Specific to Python socket API and required by httplib: convert
+        response into a file-like object.  This implementation reads using recv
+        and copies the output into a StringIO buffer to simulate a file object
+        for consumption by httplib
+
+        Nb. Ignoring optional file open mode (StringIO is generic and will
+        open for read and write unless a string is passed to the constructor)
+        and buffer size - httplib set a zero buffer size which results in recv
+        reading nothing
+
+        @return: file object for data returned from socket
+        @rtype: cStringIO.StringO
+        """
+        self._makefile_refs += 1
+        
+        # Optimisation
+        _buf_size = self.buf_size
+
+        i=0
+        stream = BytesIO()
+        startTime = datetime.utcnow()
+        try:
+            dat = self.__ssl_conn.recv(_buf_size)
+            while dat:
+                i+=1
+                stream.write(dat)
+                dat = self.__ssl_conn.recv(_buf_size)
+
+        except (SSL.ZeroReturnError, SSL.SysCallError):
+            # Connection is closed - assuming here that all is well and full
+            # response has been received.  httplib will catch an error in
+            # incomplete content since it checks the content-length header
+            # against the actual length of data received
+            pass
+
+        if log.getEffectiveLevel() <= logging.DEBUG:
+            log.debug("Socket.makefile %d recv calls completed in %s", i,
+                      datetime.utcnow() - startTime)
+
+        # Make sure to rewind the buffer otherwise consumers of the content will
+        # read from the end of the buffer
+        stream.seek(0)
+
+        return stream
+    
+    def getsockname(self):
+        """
+        @return: the socket's own address
+        @rtype:
+        """
+        return self.__ssl_conn.getsockname()
+
+    def getpeername(self):
+        """
+        @return: remote address to which the socket is connected
+        """
+        return self.__ssl_conn.getpeername()
+
+    def get_context(self):
+        '''Retrieve the Context object associated with this Connection. '''
+        return self.__ssl_conn.get_context()
+
+    def get_peer_certificate(self):
+        '''Retrieve the other side's certificate (if any)  '''
+        return self.__ssl_conn.get_peer_certificate()

+ 153 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/subj_alt_name.py

@@ -0,0 +1,153 @@
+"""NDG HTTPS Client package
+
+Use pyasn1 to provide support for parsing ASN.1 formatted subjectAltName
+content for SSL peer verification.  Code based on:
+
+http://stackoverflow.com/questions/5519958/how-do-i-parse-subjectaltname-extension-data-using-pyasn1
+"""
+__author__ = "P J Kershaw"
+__date__ = "01/02/12"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+try:
+    from pyasn1.type import univ, constraint, char, namedtype, tag
+    
+except ImportError as e:
+    import_error_msg = ('Error importing pyasn1, subjectAltName check for SSL '
+                        'peer verification will be disabled.  Import error '
+                        'is: %s' % e)
+    import warnings
+    warnings.warn(import_error_msg)
+    class Pyasn1ImportError(ImportError):
+        "Raise for pyasn1 import error"
+    raise Pyasn1ImportError(import_error_msg)
+    
+    
+MAX = 64
+
+
+class DirectoryString(univ.Choice):
+    """ASN.1 Directory string class"""
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType(
+            'teletexString', char.TeletexString().subtype(
+                subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType(
+            'printableString', char.PrintableString().subtype(
+                subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType(
+            'universalString', char.UniversalString().subtype(
+                subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType(
+            'utf8String', char.UTF8String().subtype(
+                subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType(
+            'bmpString', char.BMPString().subtype(
+                subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        namedtype.NamedType(
+            'ia5String', char.IA5String().subtype(
+                subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
+        )
+
+
+class AttributeValue(DirectoryString):
+    """ASN.1 Attribute value"""
+
+
+class AttributeType(univ.ObjectIdentifier):
+    """ASN.1 Attribute type"""
+
+
+class AttributeTypeAndValue(univ.Sequence):
+    """ASN.1 Attribute type and value class"""
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('type', AttributeType()),
+        namedtype.NamedType('value', AttributeValue()),
+        )
+
+
+class RelativeDistinguishedName(univ.SetOf):
+    '''ASN.1 Realtive distinguished name'''
+    componentType = AttributeTypeAndValue()
+
+class RDNSequence(univ.SequenceOf):
+    '''ASN.1 RDN sequence class'''
+    componentType = RelativeDistinguishedName()
+
+
+class Name(univ.Choice):
+    '''ASN.1 name class'''
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('', RDNSequence()),
+        )
+
+
+class Extension(univ.Sequence):
+    '''ASN.1 extension class'''
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('extnID', univ.ObjectIdentifier()),
+        namedtype.DefaultedNamedType('critical', univ.Boolean('False')),
+        namedtype.NamedType('extnValue', univ.OctetString()),
+        )
+
+
+class Extensions(univ.SequenceOf):
+    '''ASN.1 extensions class'''
+    componentType = Extension()
+    sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX)
+
+
+class AnotherName(univ.Sequence):
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('type-id', univ.ObjectIdentifier()),
+        namedtype.NamedType('value', univ.Any().subtype(
+                            explicitTag=tag.Tag(tag.tagClassContext,
+                                                tag.tagFormatSimple, 0)))
+        )
+
+
+class GeneralName(univ.Choice):
+    '''ASN.1 configuration for X.509 certificate subjectAltNames fields'''
+    componentType = namedtype.NamedTypes(
+        namedtype.NamedType('otherName', AnotherName().subtype(
+                            implicitTag=tag.Tag(tag.tagClassContext,
+                                                tag.tagFormatSimple, 0))),
+        namedtype.NamedType('rfc822Name', char.IA5String().subtype(
+                            implicitTag=tag.Tag(tag.tagClassContext,
+                                                tag.tagFormatSimple, 1))),
+        namedtype.NamedType('dNSName', char.IA5String().subtype(
+                            implicitTag=tag.Tag(tag.tagClassContext,
+                                                tag.tagFormatSimple, 2))),
+#        namedtype.NamedType('x400Address', ORAddress().subtype(
+#                            implicitTag=tag.Tag(tag.tagClassContext,
+#                                                tag.tagFormatSimple, 3))),
+        namedtype.NamedType('directoryName', Name().subtype(
+                            implicitTag=tag.Tag(tag.tagClassContext,
+                                                tag.tagFormatSimple, 4))),
+#        namedtype.NamedType('ediPartyName', EDIPartyName().subtype(
+#                            implicitTag=tag.Tag(tag.tagClassContext,
+#                                                tag.tagFormatSimple, 5))),
+        namedtype.NamedType('uniformResourceIdentifier', char.IA5String().subtype(
+                            implicitTag=tag.Tag(tag.tagClassContext,
+                                                tag.tagFormatSimple, 6))),
+        namedtype.NamedType('iPAddress', univ.OctetString().subtype(
+                            implicitTag=tag.Tag(tag.tagClassContext,
+                                                tag.tagFormatSimple, 7))),
+        namedtype.NamedType('registeredID', univ.ObjectIdentifier().subtype(
+                            implicitTag=tag.Tag(tag.tagClassContext,
+                                                tag.tagFormatSimple, 8))),
+        )
+
+
+class GeneralNames(univ.SequenceOf):
+    '''Sequence of names for ASN.1 subjectAltNames settings'''
+    componentType = GeneralName()
+    sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX)
+
+
+class SubjectAltName(GeneralNames):
+    '''ASN.1 implementation for subjectAltNames support'''
+
+

+ 26 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/README

@@ -0,0 +1,26 @@
+NDG HTTPS Client Unit tests directory
+=====================================
+The unit tests expect to connect to a simple HTTPS server listening on port 
+4443.  An OpenSSL script is provided for this purpose in scripts/.  To run,
+
+$ ./scripts/openssl_https_server.sh
+
+Unit tests
+----------
+Run for example,
+
+$ python ./test_urllib2.py
+
+Troubleshooting
+---------------
+ * Run the openssl script from *this* directory.  
+ * Also ensure it is has execute bits set. e.g.
+
+ $ chmod 755 ./scripts/openssl_https_server.sh
+ 
+ * You may need to set the no_proxy environment variable if you have a HTTPS
+ proxy in place:
+ 
+ $ export no_proxy=localhost
+
+

+ 29 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/__init__.py

@@ -0,0 +1,29 @@
+"""Unit tests package for ndg_httpsclient
+
+PyOpenSSL utility to make a httplib-like interface suitable for use with 
+urllib2
+"""
+__author__ = "P J Kershaw (STFC)"
+__date__ = "05/01/12"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+import os
+import unittest
+    
+class Constants(object):
+    '''Convenience base class from which other unit tests can extend.  Its
+    sets the generic data directory path'''
+    PORT = 4443
+    PORT2 = 4444
+    HOSTNAME = 'localhost'
+    TEST_URI = 'https://%s:%d' % (HOSTNAME, PORT)
+    TEST_URI2 = 'https://%s:%d' % (HOSTNAME, PORT2)
+
+    UNITTEST_DIR = os.path.dirname(os.path.abspath(__file__))
+    CACERT_DIR = os.path.join(UNITTEST_DIR, 'pki', 'ca')
+    SSL_CERT_FILENAME = 'localhost.crt'
+    SSL_CERT_FILEPATH = os.path.join(UNITTEST_DIR, 'pki', SSL_CERT_FILENAME)
+    SSL_PRIKEY_FILENAME = 'localhost.key'
+    SSL_PRIKEY_FILEPATH = os.path.join(UNITTEST_DIR, 'pki', SSL_PRIKEY_FILENAME)

+ 20 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/pki/ca/08bd99c7.0

@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBATANBgkqhkiG9w0BAQUFADA3MREwDwYDVQQLDAhTZWN1
+cml0eTEUMBIGA1UEAwwLTkRHIFRlc3QgQ0ExDDAKBgNVBAoMA05ERzAeFw0xNTAx
+MjExNDMzMThaFw0yMDAxMjAxNDMzMThaMDcxETAPBgNVBAsMCFNlY3VyaXR5MRQw
+EgYDVQQDDAtOREcgVGVzdCBDQTEMMAoGA1UECgwDTkRHMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEArq4QKUTRq45nCDR/p+OlHIIN8+ugUbiCfteazbTG
+rX8vIQ9HxSuz/xvxTw+E0KgA4YSK2SJJP4QiCjlMKYS3Rt8o361GNtnRmeo5qyBu
+GMSv73XL1uuqumggUZyrhhksckR7gyNFnKVXzZjAQPepsT0xBjs5uEAEqXJzAf+r
+24AnT3MZRh7gsyEe3sZjd75kZVwcrWhrocyKlMCR77yEr+uP4pg+dEMhDMKKxlaF
+C5RPMotOpWm/7AToHrGia34WSmcxvuOwxOkI4xEW6mxWMaVTBCXUh6Wb/0m/x8Nv
+9VvS2UBC4sCp4MqlDpySxQpT1RgrhMTEmtUOh50l4eEhdwIDAQABo0UwQzASBgNV
+HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUkEvQjGOP
+Oj5DZEvsm96AdiiFXWgwDQYJKoZIhvcNAQEFBQADggEBAGD0kQASmNzvtYL+JUGf
+gTPyJhADl9Ai9GvZJsY/wX0IRTxRl5y08Dqlg3qyGG3GzL918cr1sVCYnLepNQES
+T0MIz50DCKGryNSc74JHPDxpYaSV6whmNH5iwh8fy6tmJwF3FWbGXD2ddc+ofJqP
+WPPJtzqxuuJ6iXQIFqD9mEn3iXVcvFuSzpdpH9paORTKB0j4gya9zctB8LP0ZXIE
+//wREc+4msnmoTn+qkFAOPBg9WnvoipfyCXPgbTagxlofVjZ7gAgYIefqhXBTQdd
+5tnYdyQQBRcUXQS2bBX03q8ftcxOjc3SvXI4MvrqofuFPwu4GnrspnC0KQYlXwEI
+7ds=
+-----END CERTIFICATE-----

+ 20 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/pki/ca/ade0138a.0

@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDLjCCAhagAwIBAgIBATANBgkqhkiG9w0BAQUFADA3MREwDwYDVQQLDAhTZWN1
+cml0eTEUMBIGA1UEAwwLTkRHIFRlc3QgQ0ExDDAKBgNVBAoMA05ERzAeFw0xNTAx
+MjExNDMzMThaFw0yMDAxMjAxNDMzMThaMDcxETAPBgNVBAsMCFNlY3VyaXR5MRQw
+EgYDVQQDDAtOREcgVGVzdCBDQTEMMAoGA1UECgwDTkRHMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEArq4QKUTRq45nCDR/p+OlHIIN8+ugUbiCfteazbTG
+rX8vIQ9HxSuz/xvxTw+E0KgA4YSK2SJJP4QiCjlMKYS3Rt8o361GNtnRmeo5qyBu
+GMSv73XL1uuqumggUZyrhhksckR7gyNFnKVXzZjAQPepsT0xBjs5uEAEqXJzAf+r
+24AnT3MZRh7gsyEe3sZjd75kZVwcrWhrocyKlMCR77yEr+uP4pg+dEMhDMKKxlaF
+C5RPMotOpWm/7AToHrGia34WSmcxvuOwxOkI4xEW6mxWMaVTBCXUh6Wb/0m/x8Nv
+9VvS2UBC4sCp4MqlDpySxQpT1RgrhMTEmtUOh50l4eEhdwIDAQABo0UwQzASBgNV
+HRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUkEvQjGOP
+Oj5DZEvsm96AdiiFXWgwDQYJKoZIhvcNAQEFBQADggEBAGD0kQASmNzvtYL+JUGf
+gTPyJhADl9Ai9GvZJsY/wX0IRTxRl5y08Dqlg3qyGG3GzL918cr1sVCYnLepNQES
+T0MIz50DCKGryNSc74JHPDxpYaSV6whmNH5iwh8fy6tmJwF3FWbGXD2ddc+ofJqP
+WPPJtzqxuuJ6iXQIFqD9mEn3iXVcvFuSzpdpH9paORTKB0j4gya9zctB8LP0ZXIE
+//wREc+4msnmoTn+qkFAOPBg9WnvoipfyCXPgbTagxlofVjZ7gAgYIefqhXBTQdd
+5tnYdyQQBRcUXQS2bBX03q8ftcxOjc3SvXI4MvrqofuFPwu4GnrspnC0KQYlXwEI
+7ds=
+-----END CERTIFICATE-----

+ 82 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/pki/localhost.crt

@@ -0,0 +1,82 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: OU=Security, CN=NDG Test CA, O=NDG
+        Validity
+            Not Before: Jan 21 14:45:01 2015 GMT
+            Not After : Jan 20 14:45:01 2018 GMT
+        Subject: O=NDG, OU=Security, CN=localhost
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:e3:29:45:fc:56:2d:a2:21:b6:49:c6:6a:ef:b3:
+                    ed:d3:32:47:77:d9:85:ef:e5:6a:db:70:8b:5d:41:
+                    4d:b5:76:f5:96:42:5a:f7:82:a5:bb:b3:e1:f9:ac:
+                    c6:b7:71:61:f4:4d:dd:28:f6:b1:ef:65:dc:5a:8c:
+                    47:b1:17:38:e1:8a:5f:40:b0:bb:a0:87:61:a7:72:
+                    f8:c1:a1:5f:3b:f7:94:b5:cb:c3:50:84:ef:a8:13:
+                    d4:92:ff:af:3a:d1:31:42:90:4b:58:4c:84:47:a6:
+                    3a:a3:3d:c1:9a:43:3c:10:f6:8a:b5:97:11:b7:74:
+                    ab:32:92:be:9a:fc:ef:5e:45:78:30:61:67:10:63:
+                    09:ef:61:b7:1c:47:cc:69:c9:e7:27:8f:4d:97:33:
+                    59:33:b8:47:89:86:4c:cd:a4:38:7c:d0:60:ee:52:
+                    c8:e1:2a:f1:3b:9b:e9:7c:d5:af:88:33:91:9c:10:
+                    63:89:01:03:fb:26:5e:3f:61:c3:b4:f0:fb:1f:ad:
+                    e8:d2:49:8e:2f:16:81:bb:9c:d6:a5:48:91:58:7d:
+                    ac:ac:2c:02:8a:f2:f4:22:80:1f:8c:32:5b:b5:77:
+                    d0:36:e9:27:9a:9f:31:67:d5:4e:32:8d:cf:ce:73:
+                    ef:88:86:e9:3c:53:e6:09:55:02:2b:86:7d:91:8d:
+                    fb:53
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                A3:77:23:B5:1C:98:85:C8:6D:31:40:1C:2F:20:57:CD:C9:36:74:1B
+            X509v3 Authority Key Identifier: 
+                keyid:90:4B:D0:8C:63:8F:3A:3E:43:64:4B:EC:9B:DE:80:76:28:85:5D:68
+
+            X509v3 Subject Alternative Name: 
+                DNS:localhost
+    Signature Algorithm: sha1WithRSAEncryption
+        33:b4:87:0e:2c:71:88:6d:ab:cc:14:c8:3f:1e:8d:e5:ed:26:
+        6b:b8:76:93:29:b1:0b:c5:e7:41:6f:14:62:8f:e1:81:bb:02:
+        13:5c:b2:34:b7:94:f2:7d:1e:fe:e7:89:0b:2e:56:30:58:eb:
+        90:d4:05:5b:18:d9:c5:68:61:c0:f6:f7:1a:0f:14:d8:89:8e:
+        ee:ec:59:b8:48:96:58:33:2e:98:95:56:c3:02:e9:93:cd:3f:
+        4c:0d:b5:b5:b6:6e:6f:95:5f:65:eb:1a:ce:56:20:e2:72:d4:
+        f7:58:5f:c0:7b:49:5f:ac:6b:01:7b:c8:f0:13:19:03:dd:4e:
+        05:55:f9:31:52:ea:45:eb:54:b9:4b:a2:3f:22:c7:11:47:8a:
+        94:b4:e9:9e:c0:09:96:72:66:ba:01:d3:f3:00:6e:24:ca:a9:
+        6d:8e:7f:0b:a0:fd:f9:c9:4f:3a:36:07:c7:4a:c7:c7:1f:c7:
+        e0:2d:c3:21:d0:44:68:81:38:af:ce:cb:38:be:db:02:3d:ba:
+        62:00:43:94:22:c8:d7:43:cd:db:73:23:9d:28:aa:d6:4c:08:
+        45:8f:b5:1d:04:c7:2b:8e:22:12:e6:af:cd:9c:13:db:c9:76:
+        f4:0c:10:25:fa:5c:46:77:7d:e5:ee:16:b4:f1:24:94:22:06:
+        85:40:0c:5f
+-----BEGIN CERTIFICATE-----
+MIIDejCCAmKgAwIBAgIBATANBgkqhkiG9w0BAQUFADA3MREwDwYDVQQLDAhTZWN1
+cml0eTEUMBIGA1UEAwwLTkRHIFRlc3QgQ0ExDDAKBgNVBAoMA05ERzAeFw0xNTAx
+MjExNDQ1MDFaFw0xODAxMjAxNDQ1MDFaMDUxDDAKBgNVBAoTA05ERzERMA8GA1UE
+CxMIU2VjdXJpdHkxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAOMpRfxWLaIhtknGau+z7dMyR3fZhe/lattwi11BTbV2
+9ZZCWveCpbuz4fmsxrdxYfRN3Sj2se9l3FqMR7EXOOGKX0Cwu6CHYady+MGhXzv3
+lLXLw1CE76gT1JL/rzrRMUKQS1hMhEemOqM9wZpDPBD2irWXEbd0qzKSvpr8715F
+eDBhZxBjCe9htxxHzGnJ5yePTZczWTO4R4mGTM2kOHzQYO5SyOEq8Tub6XzVr4gz
+kZwQY4kBA/smXj9hw7Tw+x+t6NJJji8Wgbuc1qVIkVh9rKwsAory9CKAH4wyW7V3
+0DbpJ5qfMWfVTjKNz85z74iG6TxT5glVAiuGfZGN+1MCAwEAAaOBkjCBjzAJBgNV
+HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZp
+Y2F0ZTAdBgNVHQ4EFgQUo3cjtRyYhchtMUAcLyBXzck2dBswHwYDVR0jBBgwFoAU
+kEvQjGOPOj5DZEvsm96AdiiFXWgwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqG
+SIb3DQEBBQUAA4IBAQAztIcOLHGIbavMFMg/Ho3l7SZruHaTKbELxedBbxRij+GB
+uwITXLI0t5TyfR7+54kLLlYwWOuQ1AVbGNnFaGHA9vcaDxTYiY7u7Fm4SJZYMy6Y
+lVbDAumTzT9MDbW1tm5vlV9l6xrOViDictT3WF/Ae0lfrGsBe8jwExkD3U4FVfkx
+UupF61S5S6I/IscRR4qUtOmewAmWcma6AdPzAG4kyqltjn8LoP35yU86NgfHSsfH
+H8fgLcMh0ERogTivzss4vtsCPbpiAEOUIsjXQ83bcyOdKKrWTAhFj7UdBMcrjiIS
+5q/NnBPbyXb0DBAl+lxGd33l7ha08SSUIgaFQAxf
+-----END CERTIFICATE-----

+ 27 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/pki/localhost.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA4ylF/FYtoiG2ScZq77Pt0zJHd9mF7+Vq23CLXUFNtXb1lkJa
+94Klu7Ph+azGt3Fh9E3dKPax72XcWoxHsRc44YpfQLC7oIdhp3L4waFfO/eUtcvD
+UITvqBPUkv+vOtExQpBLWEyER6Y6oz3BmkM8EPaKtZcRt3SrMpK+mvzvXkV4MGFn
+EGMJ72G3HEfMacnnJ49NlzNZM7hHiYZMzaQ4fNBg7lLI4SrxO5vpfNWviDORnBBj
+iQED+yZeP2HDtPD7H63o0kmOLxaBu5zWpUiRWH2srCwCivL0IoAfjDJbtXfQNukn
+mp8xZ9VOMo3PznPviIbpPFPmCVUCK4Z9kY37UwIDAQABAoIBAF29Fmg+l64kAzkG
+a/JmaWmRgfRvCton7aSIGLpuzEZpxIYw86DXhNSkMkf5iDcCzs0lpHHW+y4y9m9X
+G+50CsDnfM8RHxvrQdz7kLM2iDoSvIcYgoyjjtHo/Pt8Dy9SS+WP7ceOK7f1XJUo
+Us/5lrvZQPwWTvVJa6v+6jDC13Qqp34qNXCBZvU2WJpjM8Yau3C6ixP2ifJMmoOV
+5BT7bUPwn9QT49PFDLSbKKUnvr8ClhXF2hF2B4ztm3SIjhMe7kwuU+i8yWlFiGT+
+RzSvKGGA7QtDeww5vrMEpaudQaU0MvcKbsolk/MDh0Kcy3fKKz1OSZEvvZ1hCzlr
+4flLOOECgYEA+YG32ohJ5QZnaQ+DXOl/QSzAlL5ZZeSSny25tkJetLKthTcSfHNH
++gWRFujONATuA7EmgkzNC+d+3JjYJIcVODb/22yoAVQFVXvz+Ihe5UyM14r/ZV/b
+4w/dLvLpWnw17BaqDwl216xnNXa/Y4IzTXwgw2G8noTKlby6You0NMcCgYEA6RKu
+95+y1xMIVdfMEExRcwUDFxFA9f1WFArq2D/GYiJhOQtjXJm5nQpsiczcF0xHvXjA
+6YiwFBF8L6d77ZlYb1AoKeE2me/wtRqaZtAGqnzqS7fx06hgFD8FAGxtHYXW2Ozj
+rKYEb3Xqkpko+XzuLIXaXSP/TcE2PuWMRa9IIRUCgYBNYx2KS3FX9seGP4iH/eg5
+Z88Hk46Y2u9bLcyHKkjDlRPa2L0EGqF9e9KHn4etfMXyITUHfxiuE4w2kbWghsFf
+ITf0b9wgJVZOMFb4hBui1T5t8C/M2pGR+K6qzC7yoMn8wv7WESJqPI/6di1giNau
+tsxWrW7aX+eRz+qjfB9VqwKBgQCOfEaMyYuqok8JM7jkCdQNTfYapwigmbSC4j25
+4BsmqT/ogMbIuI3ZrKK4B45Ri+ebtHOzEUYbrqjN9UT09zcyLb2wBKe9qgrsnIvh
+6LD6jw0pJxXmwFukZPZo0OBQGR9EVGXHiWLSxTKXVpzPEQoGG/pn0HbmkQTZpLmB
+bGvbFQKBgQDKNboMRllLx6adl5vI8aEvX5M4BI/6RIFuMI+6glO8mf2MrC46w0a7
+jo/Z5G2GLfAZ2GXUW3PoWxWYGjxyX12LvOg+R137uzD/itqij9IRgv91X+Go27Co
+ch20cYyr3Sblp2hMH9gDL+4fvtKGZKc1Bm+uI3wO61RRBl0JEYT3Ww==
+-----END RSA PRIVATE KEY-----

+ 2 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/scripts/openssl_https_server.sh

@@ -0,0 +1,2 @@
+#!/bin/sh
+openssl s_server -www -cert pki/localhost.crt -key pki/localhost.key -accept 4443

+ 122 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/test_https.py

@@ -0,0 +1,122 @@
+"""unit tests module for ndg.httpsclient.https.HTTPSconnection class
+
+PyOpenSSL utility to make a httplib-like interface suitable for use with 
+urllib2
+"""
+__author__ = "P J Kershaw (STFC)"
+__date__ = "06/01/12"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+import logging
+logging.basicConfig(level=logging.DEBUG)
+log = logging.getLogger(__name__)
+import unittest
+import socket
+
+from OpenSSL import SSL
+
+from ndg.httpsclient.test import Constants
+from ndg.httpsclient.https import HTTPSConnection
+from ndg.httpsclient.ssl_peer_verification import ServerSSLCertVerification
+
+
+class TestHTTPSConnection(unittest.TestCase):
+    '''Test ndg HTTPS client HTTPSConnection class'''
+
+    def test01_open(self):
+        conn = HTTPSConnection(Constants.HOSTNAME, port=Constants.PORT)
+        conn.connect()
+        conn.request('GET', '/')
+        resp = conn.getresponse()
+        print('Response = %s' % resp.read())
+        conn.close()
+
+    def test02_open_fails(self):
+        conn = HTTPSConnection(Constants.HOSTNAME, port=Constants.PORT2)
+        self.assertRaises(socket.error, conn.connect)
+
+    def test03_ssl_verification_of_peer_fails(self):
+        ctx = SSL.Context(SSL.TLSv1_METHOD)
+        
+        def verify_callback(conn, x509, errnum, errdepth, preverify_ok): 
+            log.debug('SSL peer certificate verification failed for %r',
+                      x509.get_subject())
+            return preverify_ok 
+            
+        ctx.set_verify(SSL.VERIFY_PEER, verify_callback)
+        ctx.set_verify_depth(9)
+        
+        # Set bad location - unit test dir has no CA certs to verify with
+        ctx.load_verify_locations(None, Constants.UNITTEST_DIR)
+        
+        conn = HTTPSConnection(Constants.HOSTNAME, port=Constants.PORT,
+                               ssl_context=ctx)
+        conn.connect()        
+        self.assertRaises(SSL.Error, conn.request, 'GET', '/')
+
+    def test03_ssl_verification_of_peer_succeeds(self):
+        ctx = SSL.Context(SSL.TLSv1_METHOD)
+        
+        verify_callback = lambda conn, x509, errnum, errdepth, preverify_ok: \
+            preverify_ok 
+            
+        ctx.set_verify(SSL.VERIFY_PEER, verify_callback)
+        ctx.set_verify_depth(9)
+        
+        # Set correct location for CA certs to verify with
+        ctx.load_verify_locations(None, Constants.CACERT_DIR)
+        
+        conn = HTTPSConnection(Constants.HOSTNAME, port=Constants.PORT,
+                               ssl_context=ctx)
+        conn.connect()
+        conn.request('GET', '/')
+        resp = conn.getresponse()
+        print('Response = %s' % resp.read())
+
+    def test04_ssl_verification_with_subj_alt_name(self):
+        ctx = SSL.Context(SSL.TLSv1_METHOD)
+        
+        verification = ServerSSLCertVerification(hostname='localhost')
+        verify_callback = verification.get_verify_server_cert_func()
+        
+        ctx.set_verify(SSL.VERIFY_PEER, verify_callback)
+        ctx.set_verify_depth(9)
+        
+        # Set correct location for CA certs to verify with
+        ctx.load_verify_locations(None, Constants.CACERT_DIR)
+        
+        conn = HTTPSConnection(Constants.HOSTNAME, port=Constants.PORT,
+                               ssl_context=ctx)
+        conn.connect()
+        conn.request('GET', '/')
+        resp = conn.getresponse()
+        print('Response = %s' % resp.read())
+
+    def test04_ssl_verification_with_subj_common_name(self):
+        ctx = SSL.Context(SSL.TLSv1_METHOD)
+        
+        # Explicitly set verification of peer hostname using peer certificate
+        # subject common name
+        verification = ServerSSLCertVerification(hostname='localhost',
+                                                 subj_alt_name_match=False)
+
+        verify_callback = verification.get_verify_server_cert_func()
+        
+        ctx.set_verify(SSL.VERIFY_PEER, verify_callback)
+        ctx.set_verify_depth(9)
+        
+        # Set correct location for CA certs to verify with
+        ctx.load_verify_locations(None, Constants.CACERT_DIR)
+        
+        conn = HTTPSConnection(Constants.HOSTNAME, port=Constants.PORT,
+                               ssl_context=ctx)
+        conn.connect()
+        conn.request('GET', '/')
+        resp = conn.getresponse()
+        print('Response = %s' % resp.read())
+
+        
+if __name__ == "__main__":
+    unittest.main()

+ 56 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/test_urllib2.py

@@ -0,0 +1,56 @@
+"""unit tests module for ndg.httpsclient.urllib2_build_opener module
+
+PyOpenSSL utility to make a httplib-like interface suitable for use with 
+urllib2
+"""
+__author__ = "P J Kershaw (STFC)"
+__date__ = "06/01/12"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+import sys
+
+if sys.version_info[0] > 2:
+    from urllib.error import URLError as URLError_
+else:
+    from urllib2 import URLError as URLError_
+    
+import unittest
+
+from OpenSSL import SSL
+from ndg.httpsclient.test import Constants
+from ndg.httpsclient.urllib2_build_opener import build_opener
+
+
+class Urllib2TestCase(unittest.TestCase):
+    """Unit tests for urllib2 functionality"""
+    
+    def test01_urllib2_build_opener(self):     
+        opener = build_opener()
+        self.assertTrue(opener)
+
+    def test02_open(self):
+        opener = build_opener()
+        res = opener.open(Constants.TEST_URI)
+        self.assertTrue(res)
+        print("res = %s" % res.read())
+
+    def test03_open_fails_unknown_loc(self):
+        opener = build_opener()
+        self.assertRaises(URLError_, opener.open, Constants.TEST_URI2)
+        
+    def test04_open_peer_cert_verification_fails(self):
+        # Explicitly set empty CA directory to make verification fail
+        ctx = SSL.Context(SSL.TLSv1_METHOD)
+        verify_callback = lambda conn, x509, errnum, errdepth, preverify_ok: \
+            preverify_ok 
+            
+        ctx.set_verify(SSL.VERIFY_PEER, verify_callback)
+        ctx.load_verify_locations(None, './')
+        opener = build_opener(ssl_context=ctx)
+        self.assertRaises(SSL.Error, opener.open, Constants.TEST_URI)
+        
+        
+if __name__ == "__main__":
+    unittest.main()

+ 62 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/test/test_utils.py

@@ -0,0 +1,62 @@
+"""unit tests module for ndg.httpsclient.utils module
+
+PyOpenSSL utility to make a httplib-like interface suitable for use with 
+urllib2
+"""
+__author__ = "P J Kershaw (STFC)"
+__date__ = "06/01/12"
+__copyright__ = "(C) 2012 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+import unittest
+import os
+
+from OpenSSL import SSL
+
+from ndg.httpsclient.test import Constants
+from ndg.httpsclient.utils import (Configuration, fetch_from_url, open_url,
+                                   _should_use_proxy)
+
+
+class TestUtilsModule(unittest.TestCase):
+    '''Test ndg.httpsclient.utils module'''
+
+    def test01_configuration(self):
+        config = Configuration(SSL.Context(SSL.TLSv1_METHOD), True)
+        self.assertTrue(config.ssl_context)
+        self.assertEqual(config.debug, True)
+
+    def test02_fetch_from_url(self):
+        config = Configuration(SSL.Context(SSL.TLSv1_METHOD), True)
+        res = fetch_from_url(Constants.TEST_URI, config)
+        self.assertTrue(res)
+        
+    def test03_open_url(self):
+        config = Configuration(SSL.Context(SSL.TLSv1_METHOD), True)
+        res = open_url(Constants.TEST_URI, config)
+        self.assertEqual(res[0], 200, 
+                         'open_url for %r failed' % Constants.TEST_URI)
+        
+    def test04__should_use_proxy(self):
+        if 'no_proxy' in os.environ:
+            no_proxy = os.environ['no_proxy']
+            del os.environ['no_proxy']
+        else:
+            no_proxy = None
+               
+        self.assertTrue(_should_use_proxy(Constants.TEST_URI), 
+                        'Expecting use proxy = True')
+        
+        os.environ['no_proxy'] = 'localhost,localhost.localdomain'
+        self.assertFalse(_should_use_proxy(Constants.TEST_URI), 
+                         'Expecting use proxy = False')
+        
+        if no_proxy is not None:
+            os.environ['no_proxy'] = no_proxy
+        else:
+            del os.environ['no_proxy']
+    
+
+if __name__ == "__main__":
+    unittest.main()

+ 78 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/urllib2_build_opener.py

@@ -0,0 +1,78 @@
+"""urllib2 style build opener integrates with HTTPSConnection class from this
+package.
+"""
+__author__ = "P J Kershaw"
+__date__ = "21/12/10"
+__copyright__ = "(C) 2011 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+import logging
+import sys
+
+# Py 2 <=> 3 compatibility for class type checking
+if sys.version_info[0] > 2:
+    class_type_ = type
+    from urllib.request import (ProxyHandler, UnknownHandler, 
+                                HTTPDefaultErrorHandler, FTPHandler, 
+                                FileHandler, HTTPErrorProcessor, 
+                                HTTPHandler, OpenerDirector, 
+                                HTTPRedirectHandler)
+else:
+    import types
+    class_type_ = types.ClassType
+    
+    from urllib2 import (ProxyHandler, UnknownHandler, HTTPDefaultErrorHandler, 
+                         FTPHandler, FileHandler, HTTPErrorProcessor, 
+                         HTTPHandler, OpenerDirector, HTTPRedirectHandler)
+
+from ndg.httpsclient.https import HTTPSContextHandler
+
+log = logging.getLogger(__name__)
+
+
+# Copied from urllib2 with modifications for ssl
+def build_opener(*handlers, **kw):
+    """Create an opener object from a list of handlers.
+
+    The opener will use several default handlers, including support
+    for HTTP and FTP.
+
+    If any of the handlers passed as arguments are subclasses of the
+    default handlers, the default handlers will not be used.
+    """
+    def isclass(obj):
+        return isinstance(obj, class_type_) or hasattr(obj, "__bases__")
+
+    opener = OpenerDirector()
+    default_classes = [ProxyHandler, UnknownHandler, HTTPHandler,
+                       HTTPDefaultErrorHandler, HTTPRedirectHandler,
+                       FTPHandler, FileHandler, HTTPErrorProcessor]
+    check_classes = list(default_classes)
+    check_classes.append(HTTPSContextHandler)
+    skip = []
+    for klass in check_classes:
+        for check in handlers:
+            if isclass(check):
+                if issubclass(check, klass):
+                    skip.append(klass)
+            elif isinstance(check, klass):
+                skip.append(klass)
+
+    for klass in default_classes:
+        if klass not in skip:
+            opener.add_handler(klass())
+            
+    # Pick up SSL context from keyword settings
+    ssl_context = kw.get('ssl_context')
+    
+    # Add the HTTPS handler with ssl_context
+    if HTTPSContextHandler not in skip:
+        opener.add_handler(HTTPSContextHandler(ssl_context))
+
+    for h in handlers:
+        if isclass(h):
+            h = h()
+        opener.add_handler(h)
+
+    return opener

+ 414 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/ndg/httpsclient/utils.py

@@ -0,0 +1,414 @@
+"""Utilities using NDG HTTPS Client, including a main module that can be used to
+fetch from a URL.
+"""
+__author__ = "R B Wilkinson"
+__date__ = "09/12/11"
+__copyright__ = "(C) 2011 Science and Technology Facilities Council"
+__license__ = "BSD - see LICENSE file in top-level directory"
+__contact__ = "Philip.Kershaw@stfc.ac.uk"
+__revision__ = '$Id$'
+
+import logging
+from optparse import OptionParser
+import os
+import sys
+
+if sys.version_info[0] > 2:
+    import http.cookiejar as cookiejar_
+    import http.client as http_client_
+    from urllib.request import Request as Request_
+    from urllib.request import HTTPHandler as HTTPHandler_
+    from urllib.request import HTTPCookieProcessor as HTTPCookieProcessor_
+    from urllib.request import HTTPBasicAuthHandler as HTTPBasicAuthHandler_
+    from urllib.request import HTTPPasswordMgrWithDefaultRealm as \
+                                            HTTPPasswordMgrWithDefaultRealm_
+    from urllib.request import ProxyHandler as ProxyHandler_
+    from urllib.error import HTTPError as HTTPError_
+    import urllib.parse as urlparse_
+else:
+    import cookielib as cookiejar_
+    import httplib as http_client_
+    from urllib2 import Request as Request_
+    from urllib2 import HTTPHandler as HTTPHandler_
+    from urllib2 import HTTPCookieProcessor as HTTPCookieProcessor_
+    from urllib2 import HTTPBasicAuthHandler as HTTPBasicAuthHandler_
+    from urllib2 import HTTPPasswordMgrWithDefaultRealm as \
+                                            HTTPPasswordMgrWithDefaultRealm_
+    from urllib2 import ProxyHandler as ProxyHandler_
+    from urllib2 import HTTPError as HTTPError_
+    import urlparse as urlparse_
+
+from ndg.httpsclient.urllib2_build_opener import build_opener
+from ndg.httpsclient.https import HTTPSContextHandler
+from ndg.httpsclient import ssl_context_util
+
+log = logging.getLogger(__name__)
+
+class AccumulatingHTTPCookieProcessor(HTTPCookieProcessor_):
+    """Cookie processor that adds new cookies (instead of replacing the existing
+    ones as HTTPCookieProcessor does)
+    """
+    def http_request(self, request):
+        """Processes cookies for a HTTP request.
+        @param request: request to process
+        @type request: urllib2.Request
+        @return: request
+        @rtype: urllib2.Request
+        """
+        COOKIE_HEADER_NAME = "Cookie"
+        tmp_request = Request_(request.get_full_url(), request.data, {},
+                                      request.origin_req_host,
+                                      request.unverifiable)
+        self.cookiejar.add_cookie_header(tmp_request)
+        # Combine existing and new cookies.
+        new_cookies = tmp_request.get_header(COOKIE_HEADER_NAME)
+        if new_cookies:
+            if request.has_header(COOKIE_HEADER_NAME):
+                # Merge new cookies with existing ones.
+                old_cookies = request.get_header(COOKIE_HEADER_NAME)
+                merged_cookies = '; '.join([old_cookies, new_cookies])
+                request.add_unredirected_header(COOKIE_HEADER_NAME,
+                                                merged_cookies)
+            else:
+                # No existing cookies so just set new ones.
+                request.add_unredirected_header(COOKIE_HEADER_NAME, new_cookies)
+        return request
+
+    # Process cookies for HTTPS in the same way.
+    https_request = http_request
+
+
+class URLFetchError(Exception):
+    """Error fetching content from URL"""
+    
+
+def fetch_from_url(url, config, data=None, handlers=None):
+    """Returns data retrieved from a URL.
+    @param url: URL to attempt to open
+    @type url: basestring
+    @param config: SSL context configuration
+    @type config: Configuration
+    @return data retrieved from URL or None
+    """
+    return_code, return_message, response = open_url(url, config, data=data,
+                                                     handlers=handlers)
+    if return_code and return_code == http_client_.OK:
+        return_data = response.read()
+        response.close()
+        return return_data
+    else:
+        raise URLFetchError(return_message)
+
+def fetch_from_url_to_file(url, config, output_file, data=None, handlers=None):
+    """Writes data retrieved from a URL to a file.
+    @param url: URL to attempt to open
+    @type url: basestring
+    @param config: SSL context configuration
+    @type config: Configuration
+    @param output_file: output file
+    @type output_file: basestring
+    @return: tuple (
+        returned HTTP status code or 0 if an error occurred
+        returned message
+        boolean indicating whether access was successful)
+    """
+    return_code, return_message, response = open_url(url, config, data=data,
+                                                     handlers=handlers)
+    if return_code == http_client_.OK:
+        return_data = response.read()
+        response.close()
+        outfile = open(output_file, "w")
+        outfile.write(return_data)
+        outfile.close()
+        
+    return return_code, return_message, return_code == http_client_.OK
+
+
+def fetch_stream_from_url(url, config, data=None, handlers=None):
+    """Returns data retrieved from a URL.
+    @param url: URL to attempt to open
+    @type url: basestring
+    @param config: SSL context configuration
+    @type config: Configuration
+    @param data: HTTP POST data
+    @type data: str
+    @param handlers: list of custom urllib2 handlers to add to the request
+    @type handlers: iterable
+    @return: data retrieved from URL or None
+    @rtype: file derived type
+    """
+    return_code, return_message, response = open_url(url, config, data=data,
+                                                     handlers=handlers)
+    if return_code and return_code == http_client_.OK:
+        return response
+    else:
+        raise URLFetchError(return_message)
+
+
+def open_url(url, config, data=None, handlers=None):
+    """Attempts to open a connection to a specified URL.
+    @param url: URL to attempt to open
+    @param config: SSL context configuration
+    @type config: Configuration
+    @param data: HTTP POST data
+    @type data: str
+    @param handlers: list of custom urllib2 handlers to add to the request
+    @type handlers: iterable
+    @return: tuple (
+        returned HTTP status code or 0 if an error occurred
+        returned message or error description
+        response object)
+    """
+    debuglevel = 1 if config.debug else 0
+
+    # Set up handlers for URL opener.
+    if config.cookie:
+        cj = config.cookie
+    else:
+        cj = cookiejar_.CookieJar()
+        
+    # Use a cookie processor that accumulates cookies when redirects occur so
+    # that an application can redirect for authentication and retain both any
+    # cookies for the application and the security system (c.f.,
+    # urllib2.HTTPCookieProcessor which replaces cookies).
+    cookie_handler = AccumulatingHTTPCookieProcessor(cj)
+
+    if not handlers:
+        handlers = []
+        
+    handlers.append(cookie_handler)
+
+    if config.debug:
+        http_handler = HTTPHandler_(debuglevel=debuglevel)
+        https_handler = HTTPSContextHandler(config.ssl_context, 
+                                            debuglevel=debuglevel)
+        handlers.extend([http_handler, https_handler])
+        
+    if config.http_basicauth:
+        # currently only supports http basic auth
+        auth_handler = HTTPBasicAuthHandler_(HTTPPasswordMgrWithDefaultRealm_())
+        auth_handler.add_password(realm=None, uri=url,
+                                  user=config.httpauth[0],
+                                  passwd=config.httpauth[1])
+        handlers.append(auth_handler)
+
+
+    # Explicitly remove proxy handling if the host is one listed in the value of
+    # the no_proxy environment variable because urllib2 does use proxy settings 
+    # set via http_proxy and https_proxy, but does not take the no_proxy value 
+    # into account.
+    if not _should_use_proxy(url, config.no_proxy):
+        handlers.append(ProxyHandler_({}))
+        log.debug("Not using proxy")
+    elif config.proxies:
+        handlers.append(ProxyHandler_(config.proxies))
+        log.debug("Configuring proxies: %s" % config.proxies)
+
+    opener = build_opener(*handlers, ssl_context=config.ssl_context)
+    
+    headers = config.headers
+    if headers is None: 
+        headers = {}
+        
+    request = Request_(url, data, headers)
+
+    # Open the URL and check the response.
+    return_code = 0
+    return_message = ''
+    response = None
+    
+    # FIXME
+    response = opener.open(request)
+
+    try:
+        response = opener.open(request)
+        return_message = response.msg
+        return_code = response.code
+        if log.isEnabledFor(logging.DEBUG):
+            for index, cookie in enumerate(cj):
+                log.debug("%s  :  %s", index, cookie)
+                
+    except HTTPError_ as exc:
+        return_code = exc.code
+        return_message = "Error: %s" % exc.msg
+        if log.isEnabledFor(logging.DEBUG):
+            log.debug("%s %s", exc.code, exc.msg)
+            
+    except Exception as exc:
+        return_message = "Error: %s" % exc.__str__()
+        if log.isEnabledFor(logging.DEBUG):
+            import traceback
+            log.debug(traceback.format_exc())
+            
+    return (return_code, return_message, response)
+
+
+def _should_use_proxy(url, no_proxy=None):
+    """Determines whether a proxy should be used to open a connection to the 
+    specified URL, based on the value of the no_proxy environment variable.
+    @param url: URL
+    @type url: basestring or urllib2.Request
+    """
+    if no_proxy is None:
+        no_proxy_effective = os.environ.get('no_proxy', '')
+    else:
+        no_proxy_effective = no_proxy
+
+    urlObj = urlparse_.urlparse(_url_as_string(url))
+    for np in [h.strip() for h in no_proxy_effective.split(',')]:
+        if urlObj.hostname == np:
+            return False
+
+    return True
+
+def _url_as_string(url):
+    """Returns the URL string from a URL value that is either a string or
+    urllib2.Request..
+    @param url: URL
+    @type url: basestring or urllib2.Request
+    @return: URL string
+    @rtype: basestring
+    """
+    if isinstance(url, Request_):
+        return url.get_full_url()
+    elif isinstance(url, str):
+        return url
+    else:
+        raise TypeError("Expected type %r or %r" %
+                        (str, Request_))
+
+
+class Configuration(object):
+    """Connection configuration.
+    """
+    def __init__(self, ssl_context, debug=False, proxies=None, no_proxy=None,
+                 cookie=None, http_basicauth=None, headers=None):
+        """
+        @param ssl_context: SSL context to use with this configuration
+        @type ssl_context: OpenSSL.SSL.Context
+        @param debug: if True, output debugging information
+        @type debug: bool
+        @param proxies: proxies to use for 
+        @type proxies: dict with basestring keys and values
+        @param no_proxy: hosts for which a proxy should not be used
+        @type no_proxy: basestring
+        @param cookie: cookies to set for request
+        @type cookie: cookielib.CookieJar (python 3 - http.cookiejar)
+        @param http_basicauth: http authentication, or None
+        @type http_basicauth: tuple of (username,password)
+        @param headers: http headers
+        @type headers: dict
+        """
+        self.ssl_context = ssl_context
+        self.debug = debug
+        self.proxies = proxies
+        self.no_proxy = no_proxy
+        self.cookie = cookie
+        self.http_basicauth = http_basicauth
+        self.headers = headers
+
+
+def main():
+    '''Utility to fetch data using HTTP or HTTPS GET from a specified URL.
+    '''
+    parser = OptionParser(usage="%prog [options] url")
+    parser.add_option("-c", "--certificate", dest="cert_file", metavar="FILE",
+                      default=os.path.expanduser("~/credentials.pem"),
+                      help="Certificate file - defaults to $HOME/credentials.pem")
+    parser.add_option("-k", "--private-key", dest="key_file", metavar="FILE",
+                      default=None,
+                      help="Private key file - defaults to the certificate file")
+    parser.add_option("-t", "--ca-certificate-dir", dest="ca_dir", 
+                      metavar="PATH",
+                      default=None,
+                      help="Trusted CA certificate file directory")
+    parser.add_option("-d", "--debug", action="store_true", dest="debug", 
+                      default=False,
+                      help="Print debug information.")
+    parser.add_option("-p", "--post-data-file", dest="data_file",
+                      metavar="FILE", default=None,
+                      help="POST data file")
+    parser.add_option("-f", "--fetch", dest="output_file", metavar="FILE",
+                      default=None, help="Output file")
+    parser.add_option("-n", "--no-verify-peer", action="store_true", 
+                      dest="no_verify_peer", default=False,
+                      help="Skip verification of peer certificate.")
+    parser.add_option("-a", "--basicauth", dest="basicauth", 
+                      metavar="USER:PASSWD",
+                      default=None,
+                      help="HTTP authentication credentials")
+    parser.add_option("--header", action="append", dest="headers", 
+                      metavar="HEADER: VALUE",
+                      help="Add HTTP header to request")
+    (options, args) = parser.parse_args()
+    if len(args) != 1:
+        parser.error("Incorrect number of arguments")
+
+    url = args[0]
+
+    if options.debug:
+        logging.getLogger().setLevel(logging.DEBUG)
+
+    if options.key_file and os.path.exists(options.key_file):
+        key_file = options.key_file
+    else:
+        key_file = None
+    
+    if options.cert_file and os.path.exists(options.cert_file):
+        cert_file = options.cert_file
+    else:
+        cert_file = None
+    
+    if options.ca_dir and os.path.exists(options.ca_dir):
+        ca_dir = options.ca_dir 
+    else:
+        ca_dir = None
+        
+    verify_peer = not options.no_verify_peer
+
+    if options.data_file and os.path.exists(options.data_file):
+        data_file = open(options.data_file)
+        data = data_file.read()
+        data_file.close()
+    else:
+        data = None
+    
+    if options.basicauth:
+        http_basicauth = options.basicauth.split(':', 1)
+    else:
+        http_basicauth = None
+
+    headers = {}
+    if options.headers:
+        for h in options.headers:
+            key, val = h.split(':', 1)
+            headers[key.strip()] = val.lstrip()
+            
+    # If a private key file is not specified, the key is assumed to be stored in 
+    # the certificate file.
+    ssl_context = ssl_context_util.make_ssl_context(key_file,
+                                                    cert_file,
+                                                    None,
+                                                    ca_dir,
+                                                    verify_peer, 
+                                                    url)
+
+    config = Configuration(ssl_context, 
+                           options.debug,
+                           http_basicauth=http_basicauth,
+                           headers=headers)
+    if options.output_file:
+        return_code, return_message = fetch_from_url_to_file(
+                                                      url, 
+                                                      config,
+                                                      options.output_file,
+                                                      data)[:2]
+        raise SystemExit(return_code, return_message)
+    else:
+        data = fetch_from_url(url, config)
+        print(data)
+
+
+if __name__=='__main__':
+    logging.basicConfig()
+    main()

+ 5 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/setup.cfg

@@ -0,0 +1,5 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+

+ 151 - 0
desktop/core/ext-py/ndg_httpsclient-0.4.0/setup.py

@@ -0,0 +1,151 @@
+try:
+    from setuptools import setup, find_packages
+except ImportError:
+    from ez_setup import use_setuptools
+    use_setuptools()
+    from setuptools import setup, find_packages
+
+_long_description = '''
+This is a HTTPS client implementation for httplib and urllib2 based on
+PyOpenSSL.  PyOpenSSL provides a more fully featured SSL implementation over the
+default provided with Python and importantly enables full verification of the
+SSL peer.
+
+Releases
+========
+0.4.0
+-----
+ * Made dual compatible with Python 2 / 3.
+ 
+0.3.3
+-----
+ * Fix to add in AnotherName for ``subjectAltNames`` field - added for support for CACert issued
+   certs (thanks to Gu1).
+ * Fix to HTTP Basic Auth option for ``ndg.httpsclient.utils.main``
+ * Fix to ``ServerSSLCertVerification`` so that it can pass a function-based callback instead of using ``__call__``. In newer versions of OpenSSL (>= 0.14) the latter failed because of a request for ``__name__`` attribute.
+
+0.3.2
+-----
+ * Fix to SubjectAltNames support check - should only be enabled if pyasn1 is 
+   installed.
+ * Fix to open_url: HTTP Request object was being created inside if headers is 
+   None block - now corrected to create regardless.
+ * Added http basic auth support to script. (Thanks to Willem van Engen)
+ 
+0.3.1
+-----
+ * extended utils functions to support keyword for passing additional urllib2
+   handlers.
+
+0.3.0
+-----
+ * Added ndg.httpsclient.utils.fetch_stream_from_url function and added
+   parameter for data to post in open_url and fetch_* methods.
+ * fix to ndg.httpsclient.utils module _should_use_proxy and open_url functions
+
+0.2.0
+-----
+ * added support for SSL verification with subjectAltNames using pyasn1
+ * fixed minor bug - SSL cert DN prefix matching
+
+0.1.0
+-----
+Initial release
+
+Prerequisites
+=============
+This has been developed and tested for Python 2.6 and 2.7 with pyOpenSSL 0.13 and 0.14.  
+Version 0.4.0 tested with pyOpenSSL 0.15.1 and Python 2.7 and 3.4.  Note that proxy support 
+is only available from Python 2.6.2 onwards.  pyasn1 is required for correct SSL 
+verification with subjectAltNames.
+
+Installation
+============
+Installation can be performed using easy_install or pip.
+
+Running ndg_httpclient
+======================
+A simple script for fetching data using HTTP or HTTPS GET from a specified URL.
+
+Parameter:
+
+``url``
+  The URL of the resource to be fetched
+
+Options:
+
+``-h, --help``
+  Show help message and exit.
+
+``-c FILE, --certificate=FILE``
+  Certificate file - defaults to ``$HOME/credentials.pem``
+
+``-k FILE, --private-key=FILE``
+  Private key file - defaults to the certificate file
+
+``-t DIR, --ca-certificate-dir=DIR``
+  Trusted CA certificate file directory.
+
+``-d, --debug``
+  Print debug information - this may be useful in solving problems with HTTP or 
+  HTTPS access to a server.
+    
+``-p FILE, --post-data-file=FILE``
+  POST data file
+    
+``-f FILE, --fetch=FILE``
+  Output file
+    
+``-n, --no-verify-peer``
+  Skip verification of peer certificate.
+'''
+    
+setup(
+    name='ndg_httpsclient',
+    version="0.4.0",
+    description='Provides enhanced HTTPS support for httplib and urllib2 using '
+                'PyOpenSSL',
+    author='Richard Wilkinson and Philip Kershaw',
+    author_email='Philip.Kershaw@stfc.ac.uk',
+    url='https://github.com/cedadev/ndg_httpsclient/',
+    long_description=_long_description,
+    license='BSD - See LICENCE file for details',
+    namespace_packages=['ndg'],
+    packages=find_packages(),
+    package_dir={'ndg.httpsclient': 'ndg/httpsclient'},
+    package_data={
+        'ndg.httpsclient': [
+            'test/README', 
+            'test/scripts/*.sh',
+            'test/pki/localhost.*',
+            'test/pki/ca/*.0'
+            ],
+    },
+    install_requires = ['PyOpenSSL'],
+    extras_require = {'subjectAltName_support': 'pyasn1'},
+    classifiers = [
+        'Development Status :: 3 - Alpha',
+        'Environment :: Console',
+        'Environment :: Web Environment',
+        'Intended Audience :: End Users/Desktop',
+        'Intended Audience :: Developers',
+        'Intended Audience :: System Administrators',
+        'Intended Audience :: Science/Research',
+        'License :: OSI Approved :: BSD License',
+        'Natural Language :: English',
+        'Operating System :: Microsoft :: Windows',
+        'Operating System :: POSIX :: Linux',
+        'Programming Language :: Python',
+        'Topic :: Security',
+        'Topic :: Internet',
+        'Topic :: Scientific/Engineering',
+        'Topic :: System :: Distributed Computing',
+        'Topic :: System :: Systems Administration :: Authentication/Directory',
+        'Topic :: Software Development :: Libraries :: Python Modules'
+    ],
+    zip_safe = False,
+    entry_points = {
+        'console_scripts': ['ndg_httpclient = ndg.httpsclient.utils:main',
+                            ],
+        }
+)

+ 343 - 0
desktop/core/ext-py/pyasn1-0.1.8/CHANGES

@@ -0,0 +1,343 @@
+Revision 0.1.8
+--------------
+
+- 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 analisys.
+- 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.
+- 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)
+- DER codec hardened not to tolerate indefinite length encoding/decoding.
+
+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

+ 24 - 0
desktop/core/ext-py/pyasn1-0.1.8/LICENSE

@@ -0,0 +1,24 @@
+Copyright (c) 2005-2015, Ilya Etingof <ilya@glas.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, 
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. 

+ 3 - 0
desktop/core/ext-py/pyasn1-0.1.8/MANIFEST.in

@@ -0,0 +1,3 @@
+include CHANGES README LICENSE THANKS TODO
+recursive-include test *.py
+recursive-include doc *.html

+ 26 - 0
desktop/core/ext-py/pyasn1-0.1.8/PKG-INFO

@@ -0,0 +1,26 @@
+Metadata-Version: 1.0
+Name: pyasn1
+Version: 0.1.8
+Summary: ASN.1 types and codecs
+Home-page: http://sourceforge.net/projects/pyasn1/
+Author: Ilya Etingof <ilya@glas.net>
+Author-email: ilya@glas.net
+License: BSD
+Description: A 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 :: 3
+Classifier: Topic :: Communications
+Classifier: Topic :: Security :: Cryptography
+Classifier: Topic :: Software Development :: Libraries :: Python Modules

+ 67 - 0
desktop/core/ext-py/pyasn1-0.1.8/README

@@ -0,0 +1,67 @@
+
+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.4
+* 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.8.tar.gz
+$ cd pyasn1-0.1.8
+$ python setup.py install
+$ python setup.py test    # run unit tests (optional)
+
+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

+ 10 - 0
desktop/core/ext-py/pyasn1-0.1.8/THANKS

@@ -0,0 +1,10 @@
+Denis S. Otkidach
+Gregory Golberg
+Bud P. Bruegger
+Jacek Konieczny
+Tanya Tereschenko
+Matěj Cepl
+Alex Gaynor
+Geoffrey Thomas
+Daniel Bratell
+Kim Gräsman

+ 36 - 0
desktop/core/ext-py/pyasn1-0.1.8/TODO

@@ -0,0 +1,36 @@
+* 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?

+ 503 - 0
desktop/core/ext-py/pyasn1-0.1.8/doc/codecs.html

@@ -0,0 +1,503 @@
+<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 - 0
desktop/core/ext-py/pyasn1-0.1.8/doc/constraints.html

@@ -0,0 +1,436 @@
+<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 - 0
desktop/core/ext-py/pyasn1-0.1.8/doc/constructed.html

@@ -0,0 +1,377 @@
+<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 - 0
desktop/core/ext-py/pyasn1-0.1.8/doc/intro.html

@@ -0,0 +1,156 @@
+<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 - 0
desktop/core/ext-py/pyasn1-0.1.8/doc/pyasn1-tutorial.html

@@ -0,0 +1,2405 @@
+<html>
+<title>
+PyASN1 programmer's manual
+</title>
+<head>
+</head>
+<body>
+<center>
+<table width=60%>
+<tr>
+<td>
+
+<h3>
+PyASN1 programmer's 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="#1">1. Data model for ASN.1 types</a>
+<li><a href="#1.1">1.1 Scalar types</a>
+<li><a href="#1.1.1">1.1.1 Boolean type</a>
+<li><a href="#1.1.2">1.1.2 Null type</a>
+<li><a href="#1.1.3">1.1.3 Integer type</a>
+<li><a href="#1.1.4">1.1.4 Enumerated type</a>
+<li><a href="#1.1.5">1.1.5 Real type</a>
+<li><a href="#1.1.6">1.1.6 Bit string type</a>
+<li><a href="#1.1.7">1.1.7 OctetString type</a>
+<li><a href="#1.1.8">1.1.8 ObjectIdentifier type</a>
+<li><a href="#1.1.9">1.1.9 Character string types</a>
+<li><a href="#1.1.10">1.1.10 Useful types</a>
+<li><a href="#1.2">1.2 Tagging</a>
+<li><a href="#1.3">1.3 Constructed types</a>
+<li><a href="#1.3.1">1.3.1 Sequence and Set types</a>
+<li><a href="#1.3.2">1.3.2 SequenceOf and SetOf types</a>
+<li><a href="#1.3.3">1.3.3 Choice type</a>
+<li><a href="#1.3.4">1.3.4 Any type</a>
+<li><a href="#1.4">1.4 Subtype constraints</a>
+<li><a href="#1.4.1">1.4.1 Single value constraint</a>
+<li><a href="#1.4.2">1.4.2 Value range constraint</a>
+<li><a href="#1.4.3">1.4.3 Size constraint</a>
+<li><a href="#1.4.4">1.4.4 Alphabet constraint</a>
+<li><a href="#1.4.5">1.4.5 Constraint combinations</a>
+<li><a href="#1.5">1.5 Types relationships</a>
+<li><a href="#2">2. Codecs</a>
+<li><a href="#2.1">2.1 Encoders</a>
+<li><a href="#2.2">2.2 Decoders</a>
+<li><a href="#2.2.1">2.2.1 Decoding untagged types</a>
+<li><a href="#2.2.2">2.2.2 Ignoring unknown types</a>
+<li><a href="#3">3. Feedback and getting help</a>
+</ul>
+
+
+<a name="1"></a>
+<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>
+
+<a name="1.2"></a>
+<h4>
+1.2 Tagging
+</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(
+...   tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10), # base tag
+...   tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10)  # effective tag
+... )
+>>> 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(
+...   tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) # base tag
+...   tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) # effective tag
+... )
+>>> 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>
+
+
+<a name="1.3"></a>
+<h4>
+1.3 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>
+
+<a name="1.4"></a>
+<h4>
+1.4 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>
+
+<a name="2"></a>
+<h3>
+2. 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>
+
+<a name="3"></a>
+<h3>
+3. Feedback and getting help
+</h3>
+
+<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>

+ 794 - 0
desktop/core/ext-py/pyasn1-0.1.8/doc/scalar.html

@@ -0,0 +1,794 @@
+<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>

+ 233 - 0
desktop/core/ext-py/pyasn1-0.1.8/doc/tagging.html

@@ -0,0 +1,233 @@
+<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>

+ 8 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/__init__.py

@@ -0,0 +1,8 @@
+import sys
+
+# http://www.python.org/dev/peps/pep-0396/
+__version__ = '0.1.8'
+
+if sys.version_info[:2] < (2, 4):
+    raise RuntimeError('PyASN1 requires Python 2.4 or later')
+

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/ber/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 841 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/ber/decoder.py

@@ -0,0 +1,841 @@
+# BER decoder
+from pyasn1.type import tag, univ, char, useful, tagmap
+from pyasn1.codec.ber import eoo
+from pyasn1.compat.octets import oct2int, isOctetsType
+from pyasn1 import debug, error
+
+class AbstractDecoder:
+    protoComponent = None
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,))
+
+    def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                             length, state, decodeFun, substrateFun):
+        raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,))
+
+class AbstractSimpleDecoder(AbstractDecoder):
+    tagFormats = (tag.tagFormatSimple,)
+    def _createComponent(self, asn1Spec, tagSet, value=None):
+        if tagSet[0][1] not in self.tagFormats:
+            raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType()))
+        if asn1Spec is None:
+            return self.protoComponent.clone(value, tagSet)
+        elif value is None:
+            return asn1Spec
+        else:
+            return asn1Spec.clone(value)
+        
+class AbstractConstructedDecoder(AbstractDecoder):
+    tagFormats = (tag.tagFormatConstructed,)
+    def _createComponent(self, asn1Spec, tagSet, value=None):
+        if tagSet[0][1] not in self.tagFormats:
+            raise error.PyAsn1Error('Invalid tag format %s for %s' % (tagSet[0], self.protoComponent.prettyPrintType()))
+        if asn1Spec is None:
+            return self.protoComponent.clone(tagSet)
+        else:
+            return asn1Spec.clone()
+                                
+class ExplicitTagDecoder(AbstractSimpleDecoder):
+    protoComponent = univ.Any('')
+    tagFormats = (tag.tagFormatConstructed,)
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        if substrateFun:
+            return substrateFun(
+                       self._createComponent(asn1Spec, tagSet, ''),
+                       substrate, length
+                   )
+        head, tail = substrate[:length], substrate[length:]
+        value, _ = decodeFun(head, asn1Spec, tagSet, length)
+        return value, tail
+
+    def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                             length, state, decodeFun, substrateFun):
+        if substrateFun:
+            return substrateFun(
+                       self._createComponent(asn1Spec, tagSet, ''),
+                       substrate, length
+                   )
+        value, substrate = decodeFun(substrate, asn1Spec, tagSet, length)
+        terminator, substrate = decodeFun(substrate, allowEoo=True)
+        if eoo.endOfOctets.isSameTypeWith(terminator) and \
+                terminator == eoo.endOfOctets:
+            return value, substrate
+        else:
+            raise error.PyAsn1Error('Missing end-of-octets terminator')
+
+explicitTagDecoder = ExplicitTagDecoder()
+
+class IntegerDecoder(AbstractSimpleDecoder):
+    protoComponent = univ.Integer(0)
+    precomputedValues = {
+        '\x00':  0,
+        '\x01':  1,
+        '\x02':  2,
+        '\x03':  3,
+        '\x04':  4,
+        '\x05':  5,
+        '\x06':  6,
+        '\x07':  7,
+        '\x08':  8,
+        '\x09':  9,
+        '\xff': -1,
+        '\xfe': -2,
+        '\xfd': -3,
+        '\xfc': -4,
+        '\xfb': -5
+        }
+    
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
+                     state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        if not head:
+            return self._createComponent(asn1Spec, tagSet, 0), tail
+        if head in self.precomputedValues:
+            value = self.precomputedValues[head]
+        else:
+            firstOctet = oct2int(head[0])
+            if firstOctet & 0x80:
+                value = -1
+            else:
+                value = 0
+            for octet in head:
+                value = value << 8 | oct2int(octet)
+        return self._createComponent(asn1Spec, tagSet, value), tail
+
+class BooleanDecoder(IntegerDecoder):
+    protoComponent = univ.Boolean(0)
+    def _createComponent(self, asn1Spec, tagSet, value=None):
+        return IntegerDecoder._createComponent(self, asn1Spec, tagSet, value and 1 or 0)
+
+class BitStringDecoder(AbstractSimpleDecoder):
+    protoComponent = univ.BitString(())
+    tagFormats = (tag.tagFormatSimple, tag.tagFormatConstructed)
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
+                     state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        if tagSet[0][1] == tag.tagFormatSimple:    # XXX what tag to check?
+            if not head:
+                raise error.PyAsn1Error('Empty substrate')
+            trailingBits = oct2int(head[0])
+            if trailingBits > 7:
+                raise error.PyAsn1Error(
+                    'Trailing bits overflow %s' % trailingBits
+                    )
+            head = head[1:]
+            lsb = p = 0; l = len(head)-1; b = []
+            while p <= l:
+                if p == l:
+                    lsb = trailingBits
+                j = 7                    
+                o = oct2int(head[p])
+                while j >= lsb:
+                    b.append((o>>j)&0x01)
+                    j = j - 1
+                p = p + 1
+            return self._createComponent(asn1Spec, tagSet, b), tail
+        r = self._createComponent(asn1Spec, tagSet, ())
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        while head:
+            component, head = decodeFun(head, self.protoComponent)
+            r = r + component
+        return r, tail
+
+    def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                             length, state, decodeFun, substrateFun):
+        r = self._createComponent(asn1Spec, tagSet, '')
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        while substrate:
+            component, substrate = decodeFun(substrate, self.protoComponent,
+                                             allowEoo=True)
+            if eoo.endOfOctets.isSameTypeWith(component) and \
+                    component == eoo.endOfOctets:
+                break
+            r = r + component
+        else:
+            raise error.SubstrateUnderrunError(
+                'No EOO seen before substrate ends'
+                )
+        return r, substrate
+
+class OctetStringDecoder(AbstractSimpleDecoder):
+    protoComponent = univ.OctetString('')
+    tagFormats = (tag.tagFormatSimple, tag.tagFormatConstructed)
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
+                     state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        if tagSet[0][1] == tag.tagFormatSimple:    # XXX what tag to check?
+            return self._createComponent(asn1Spec, tagSet, head), tail
+        r = self._createComponent(asn1Spec, tagSet, '')
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        while head:
+            component, head = decodeFun(head, self.protoComponent)
+            r = r + component
+        return r, tail
+
+    def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                             length, state, decodeFun, substrateFun):
+        r = self._createComponent(asn1Spec, tagSet, '')
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        while substrate:
+            component, substrate = decodeFun(substrate, self.protoComponent,
+                                             allowEoo=True)
+            if eoo.endOfOctets.isSameTypeWith(component) and \
+                    component == eoo.endOfOctets:
+                break
+            r = r + component
+        else:
+            raise error.SubstrateUnderrunError(
+                'No EOO seen before substrate ends'
+                )
+        return r, substrate
+
+class NullDecoder(AbstractSimpleDecoder):
+    protoComponent = univ.Null('')
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        r = self._createComponent(asn1Spec, tagSet)
+        if head:
+            raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length)
+        return r, tail
+
+class ObjectIdentifierDecoder(AbstractSimpleDecoder):
+    protoComponent = univ.ObjectIdentifier(())
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
+                     state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        if not head:
+            raise error.PyAsn1Error('Empty substrate')
+
+        oid = ()
+        index = 0
+        substrateLen = len(head)
+        while index < substrateLen:
+            subId = oct2int(head[index])
+            index += 1
+            if subId < 128:
+                oid = oid + (subId,)
+            elif subId > 128:
+                # Construct subid from a number of octets
+                nextSubId = subId
+                subId = 0
+                while nextSubId >= 128:
+                    subId = (subId << 7) + (nextSubId & 0x7F)
+                    if index >= substrateLen:
+                        raise error.SubstrateUnderrunError(
+                            'Short substrate for sub-OID past %s' % (oid,)
+                        )
+                    nextSubId = oct2int(head[index])
+                    index += 1
+                oid = oid + ((subId << 7) + nextSubId,)
+            elif subId == 128:
+                # ASN.1 spec forbids leading zeros (0x80) in OID
+                # encoding, tolerating it opens a vulnerability. See
+                # http://www.cosic.esat.kuleuven.be/publications/article-1432.pdf
+                # page 7
+                raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')
+       
+        # Decode two leading arcs
+        if 0 <= oid[0] <= 39:
+            oid = (0,) + oid
+        elif 40 <= oid[0] <= 79:
+            oid = (1, oid[0]-40) + oid[1:]
+        elif oid[0] >= 80:
+            oid = (2, oid[0]-80) + oid[1:]
+        else:
+            raise error.PyAsn1Error('Malformed first OID octet: %s' % head[0])
+
+        return self._createComponent(asn1Spec, tagSet, oid), tail
+
+class RealDecoder(AbstractSimpleDecoder):
+    protoComponent = univ.Real()
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        if not head:
+            return self._createComponent(asn1Spec, tagSet, 0.0), tail
+        fo = oct2int(head[0]); head = head[1:]
+        if fo & 0x80:  # binary encoding
+            if not head:
+                raise error.PyAsn1Error("Incomplete floating-point value")
+            n = (fo & 0x03) + 1
+            if n == 4:
+                n = oct2int(head[0])
+                head = head[1:]
+            eo, head = head[:n], head[n:]
+            if not eo or not head:
+                raise error.PyAsn1Error('Real exponent screwed')
+            e = oct2int(eo[0]) & 0x80 and -1 or 0
+            while eo:         # exponent
+                e <<= 8
+                e |= oct2int(eo[0])
+                eo = eo[1:]
+            b = fo >> 4 & 0x03 # base bits
+            if b > 2:
+                raise error.PyAsn1Error('Illegal Real base')
+            if b == 1: # encbase = 8
+                e *= 3
+            elif b == 2: # encbase = 16
+                e *= 4
+            p = 0
+            while head:  # value
+                p <<= 8
+                p |= oct2int(head[0])
+                head = head[1:]
+            if fo & 0x40:    # sign bit
+                p = -p
+            sf = fo >> 2 & 0x03  # scale bits
+            p *= 2**sf
+            value = (p, 2, e)
+        elif fo & 0x40:  # infinite value
+            value = fo & 0x01 and '-inf' or 'inf'
+        elif fo & 0xc0 == 0:  # character encoding
+            if not head:
+                raise error.PyAsn1Error("Incomplete floating-point value")
+            try:
+                if fo & 0x3 == 0x1:  # NR1
+                    value = (int(head), 10, 0)
+                elif fo & 0x3 == 0x2:  # NR2
+                    value = float(head)
+                elif fo & 0x3 == 0x3:  # NR3
+                    value = float(head)
+                else:
+                    raise error.SubstrateUnderrunError(
+                        'Unknown NR (tag %s)' % fo
+                        )
+            except ValueError:
+                raise error.SubstrateUnderrunError(
+                    'Bad character Real syntax'
+                    )
+        else:
+            raise error.SubstrateUnderrunError(
+                'Unknown encoding (tag %s)' % fo
+                )
+        return self._createComponent(asn1Spec, tagSet, value), tail
+        
+class SequenceDecoder(AbstractConstructedDecoder):
+    protoComponent = univ.Sequence()
+    def _getComponentTagMap(self, r, idx):
+        try:
+            return r.getComponentTagMapNearPosition(idx)
+        except error.PyAsn1Error:
+            return
+
+    def _getComponentPositionByType(self, r, t, idx):
+        return r.getComponentPositionNearType(t, idx)
+    
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        r = self._createComponent(asn1Spec, tagSet)
+        idx = 0
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        while head:
+            asn1Spec = self._getComponentTagMap(r, idx)
+            component, head = decodeFun(head, asn1Spec)
+            idx = self._getComponentPositionByType(
+                r, component.getEffectiveTagSet(), idx
+                )
+            r.setComponentByPosition(idx, component, asn1Spec is None)
+            idx = idx + 1
+        r.setDefaultComponents()
+        r.verifySizeSpec()
+        return r, tail
+
+    def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                             length, state, decodeFun, substrateFun):
+        r = self._createComponent(asn1Spec, tagSet)
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        idx = 0
+        while substrate:
+            asn1Spec = self._getComponentTagMap(r, idx)
+            component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
+            if eoo.endOfOctets.isSameTypeWith(component) and \
+                    component == eoo.endOfOctets:
+                break
+            idx = self._getComponentPositionByType(
+                r, component.getEffectiveTagSet(), idx
+                )            
+            r.setComponentByPosition(idx, component, asn1Spec is None)
+            idx = idx + 1                
+        else:
+            raise error.SubstrateUnderrunError(
+                'No EOO seen before substrate ends'
+                )
+        r.setDefaultComponents()
+        r.verifySizeSpec()
+        return r, substrate
+
+class SequenceOfDecoder(AbstractConstructedDecoder):
+    protoComponent = univ.SequenceOf()    
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        r = self._createComponent(asn1Spec, tagSet)
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        asn1Spec = r.getComponentType()
+        idx = 0
+        while head:
+            component, head = decodeFun(head, asn1Spec)
+            r.setComponentByPosition(idx, component, asn1Spec is None)
+            idx = idx + 1
+        r.verifySizeSpec()
+        return r, tail
+
+    def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                             length, state, decodeFun, substrateFun):
+        r = self._createComponent(asn1Spec, tagSet)
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        asn1Spec = r.getComponentType()
+        idx = 0
+        while substrate:
+            component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
+            if eoo.endOfOctets.isSameTypeWith(component) and \
+                    component == eoo.endOfOctets:
+                break
+            r.setComponentByPosition(idx, component, asn1Spec is None)
+            idx = idx + 1                
+        else:
+            raise error.SubstrateUnderrunError(
+                'No EOO seen before substrate ends'
+                )
+        r.verifySizeSpec()
+        return r, substrate
+
+class SetDecoder(SequenceDecoder):
+    protoComponent = univ.Set()
+    def _getComponentTagMap(self, r, idx):
+        return r.getComponentTagMap()
+
+    def _getComponentPositionByType(self, r, t, idx):
+        nextIdx = r.getComponentPositionByType(t)
+        if nextIdx is None:
+            return idx
+        else:
+            return nextIdx
+    
+class SetOfDecoder(SequenceOfDecoder):
+    protoComponent = univ.SetOf()
+    
+class ChoiceDecoder(AbstractConstructedDecoder):
+    protoComponent = univ.Choice()
+    tagFormats = (tag.tagFormatSimple, tag.tagFormatConstructed)
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        r = self._createComponent(asn1Spec, tagSet)
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        if r.getTagSet() == tagSet: # explicitly tagged Choice
+            component, head = decodeFun(
+                head, r.getComponentTagMap()
+                )
+        else:
+            component, head = decodeFun(
+                head, r.getComponentTagMap(), tagSet, length, state
+                )
+        if isinstance(component, univ.Choice):
+            effectiveTagSet = component.getEffectiveTagSet()
+        else:
+            effectiveTagSet = component.getTagSet()
+        r.setComponentByType(effectiveTagSet, component, 0, asn1Spec is None)
+        return r, tail
+
+    def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        r = self._createComponent(asn1Spec, tagSet)
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        if r.getTagSet() == tagSet: # explicitly tagged Choice
+            component, substrate = decodeFun(substrate, r.getComponentTagMap())
+            # eat up EOO marker
+            eooMarker, substrate = decodeFun(substrate, allowEoo=True)
+            if not eoo.endOfOctets.isSameTypeWith(eooMarker) or \
+                    eooMarker != eoo.endOfOctets:
+                raise error.PyAsn1Error('No EOO seen before substrate ends')
+        else:
+            component, substrate= decodeFun(
+                substrate, r.getComponentTagMap(), tagSet, length, state
+            )
+        if isinstance(component, univ.Choice):
+            effectiveTagSet = component.getEffectiveTagSet()
+        else:
+            effectiveTagSet = component.getTagSet()
+        r.setComponentByType(effectiveTagSet, component, 0, asn1Spec is None)
+        return r, substrate
+
+class AnyDecoder(AbstractSimpleDecoder):
+    protoComponent = univ.Any()
+    tagFormats = (tag.tagFormatSimple, tag.tagFormatConstructed)
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                     length, state, decodeFun, substrateFun):
+        if asn1Spec is None or \
+               asn1Spec is not None and tagSet != asn1Spec.getTagSet():
+            # untagged Any container, recover inner header substrate
+            length = length + len(fullSubstrate) - len(substrate)
+            substrate = fullSubstrate
+        if substrateFun:
+            return substrateFun(self._createComponent(asn1Spec, tagSet),
+                                substrate, length)
+        head, tail = substrate[:length], substrate[length:]
+        return self._createComponent(asn1Spec, tagSet, value=head), tail
+
+    def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet,
+                             length, state, decodeFun, substrateFun):
+        if asn1Spec is not None and tagSet == asn1Spec.getTagSet():
+            # tagged Any type -- consume header substrate
+            header = ''
+        else:
+            # untagged Any, recover header substrate
+            header = fullSubstrate[:-len(substrate)]
+
+        r = self._createComponent(asn1Spec, tagSet, header)
+
+        # Any components do not inherit initial tag
+        asn1Spec = self.protoComponent
+        
+        if substrateFun:
+            return substrateFun(r, substrate, length)
+        while substrate:
+            component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True)
+            if eoo.endOfOctets.isSameTypeWith(component) and \
+                    component == eoo.endOfOctets:
+                break
+            r = r + component
+        else:
+            raise error.SubstrateUnderrunError(
+                'No EOO seen before substrate ends'
+                )
+        return r, substrate
+
+# character string types
+class UTF8StringDecoder(OctetStringDecoder):
+    protoComponent = char.UTF8String()
+class NumericStringDecoder(OctetStringDecoder):
+    protoComponent = char.NumericString()
+class PrintableStringDecoder(OctetStringDecoder):
+    protoComponent = char.PrintableString()
+class TeletexStringDecoder(OctetStringDecoder):
+    protoComponent = char.TeletexString()
+class VideotexStringDecoder(OctetStringDecoder):
+    protoComponent = char.VideotexString()
+class IA5StringDecoder(OctetStringDecoder):
+    protoComponent = char.IA5String()
+class GraphicStringDecoder(OctetStringDecoder):
+    protoComponent = char.GraphicString()
+class VisibleStringDecoder(OctetStringDecoder):
+    protoComponent = char.VisibleString()
+class GeneralStringDecoder(OctetStringDecoder):
+    protoComponent = char.GeneralString()
+class UniversalStringDecoder(OctetStringDecoder):
+    protoComponent = char.UniversalString()
+class BMPStringDecoder(OctetStringDecoder):
+    protoComponent = char.BMPString()
+
+# "useful" types
+class ObjectDescriptorDecoder(OctetStringDecoder):
+    protoComponent = useful.ObjectDescriptor()
+class GeneralizedTimeDecoder(OctetStringDecoder):
+    protoComponent = useful.GeneralizedTime()
+class UTCTimeDecoder(OctetStringDecoder):
+    protoComponent = useful.UTCTime()
+
+tagMap = {
+    univ.Integer.tagSet: IntegerDecoder(),
+    univ.Boolean.tagSet: BooleanDecoder(),
+    univ.BitString.tagSet: BitStringDecoder(),
+    univ.OctetString.tagSet: OctetStringDecoder(),
+    univ.Null.tagSet: NullDecoder(),
+    univ.ObjectIdentifier.tagSet: ObjectIdentifierDecoder(),
+    univ.Enumerated.tagSet: IntegerDecoder(),
+    univ.Real.tagSet: RealDecoder(),
+    univ.Sequence.tagSet: SequenceDecoder(),  # conflicts with SequenceOf
+    univ.Set.tagSet: SetDecoder(),            # conflicts with SetOf
+    univ.Choice.tagSet: ChoiceDecoder(),      # conflicts with Any
+    # character string types
+    char.UTF8String.tagSet: UTF8StringDecoder(),
+    char.NumericString.tagSet: NumericStringDecoder(),
+    char.PrintableString.tagSet: PrintableStringDecoder(),
+    char.TeletexString.tagSet: TeletexStringDecoder(),
+    char.VideotexString.tagSet: VideotexStringDecoder(),
+    char.IA5String.tagSet: IA5StringDecoder(),
+    char.GraphicString.tagSet: GraphicStringDecoder(),
+    char.VisibleString.tagSet: VisibleStringDecoder(),
+    char.GeneralString.tagSet: GeneralStringDecoder(),
+    char.UniversalString.tagSet: UniversalStringDecoder(),
+    char.BMPString.tagSet: BMPStringDecoder(),
+    # useful types
+    useful.ObjectDescriptor.tagSet: ObjectDescriptorDecoder(),
+    useful.GeneralizedTime.tagSet: GeneralizedTimeDecoder(),
+    useful.UTCTime.tagSet: UTCTimeDecoder()
+}
+
+# Type-to-codec map for ambiguous ASN.1 types
+typeMap = {
+    univ.Set.typeId: SetDecoder(),
+    univ.SetOf.typeId: SetOfDecoder(),
+    univ.Sequence.typeId: SequenceDecoder(),
+    univ.SequenceOf.typeId: SequenceOfDecoder(),
+    univ.Choice.typeId: ChoiceDecoder(),
+    univ.Any.typeId: AnyDecoder()
+}
+
+( stDecodeTag, stDecodeLength, stGetValueDecoder, stGetValueDecoderByAsn1Spec,
+  stGetValueDecoderByTag, stTryAsExplicitTag, stDecodeValue,
+  stDumpRawValue, stErrorCondition, stStop ) = [x for x in range(10)]
+
+class Decoder:
+    defaultErrorState = stErrorCondition
+#    defaultErrorState = stDumpRawValue
+    defaultRawDecoder = AnyDecoder()
+    supportIndefLength = True
+    def __init__(self, tagMap, typeMap={}):
+        self.__tagMap = tagMap
+        self.__typeMap = typeMap
+        # Tag & TagSet objects caches
+        self.__tagCache = {}
+        self.__tagSetCache = {}
+        
+    def __call__(self, substrate, asn1Spec=None, tagSet=None,
+                 length=None, state=stDecodeTag, recursiveFlag=1,
+                 substrateFun=None, allowEoo=False):
+        if debug.logger & debug.flagDecoder:
+            debug.logger('decoder called at scope %s with state %d, working with up to %d octets of substrate: %s' % (debug.scope, state, len(substrate), debug.hexdump(substrate)))
+        fullSubstrate = substrate
+        while state != stStop:
+            if state == stDecodeTag:
+                if not substrate:
+                    raise error.SubstrateUnderrunError(
+                        'Short octet stream on tag decoding'
+                        )
+                if not isOctetsType(substrate) and \
+                   not isinstance(substrate, univ.OctetString):
+                    raise error.PyAsn1Error('Bad octet stream type')
+                # Decode tag
+                firstOctet = substrate[0]
+                substrate = substrate[1:]
+                if firstOctet in self.__tagCache:
+                    lastTag = self.__tagCache[firstOctet]
+                else:
+                    t = oct2int(firstOctet)
+                    # Look for end-of-octets sentinel
+                    if t == 0:
+                        if substrate and oct2int(substrate[0]) == 0:
+                            if allowEoo and self.supportIndefLength:
+                                debug.logger and debug.logger & debug.flagDecoder and debug.logger('end-of-octets sentinel found')
+                                value, substrate = eoo.endOfOctets, substrate[1:]
+                                state = stStop
+                                continue
+                            else:
+                                raise error.PyAsn1Error('Unexpected end-of-contents sentinel')
+                        else:
+                            raise error.PyAsn1Error('Zero tag encountered')
+                    tagClass = t&0xC0
+                    tagFormat = t&0x20
+                    tagId = t&0x1F
+                    if tagId == 0x1F:
+                        tagId = 0
+                        while 1:
+                            if not substrate:
+                                raise error.SubstrateUnderrunError(
+                                    'Short octet stream on long tag decoding'
+                                    )
+                            t = oct2int(substrate[0])
+                            tagId = tagId << 7 | (t&0x7F)
+                            substrate = substrate[1:]
+                            if not t&0x80:
+                                break
+                    lastTag = tag.Tag(
+                        tagClass=tagClass, tagFormat=tagFormat, tagId=tagId
+                    )
+                    if tagId < 31:
+                        # cache short tags
+                        self.__tagCache[firstOctet] = lastTag
+                if tagSet is None:
+                    if firstOctet in self.__tagSetCache:
+                        tagSet = self.__tagSetCache[firstOctet]
+                    else:
+                        # base tag not recovered
+                        tagSet = tag.TagSet((), lastTag)
+                        if firstOctet in self.__tagCache:
+                            self.__tagSetCache[firstOctet] = tagSet
+                else:
+                    tagSet = lastTag + tagSet
+                state = stDecodeLength
+                debug.logger and debug.logger & debug.flagDecoder and debug.logger('tag decoded into %s, decoding length' % tagSet)
+            if state == stDecodeLength:
+                # Decode length
+                if not substrate:
+                    raise error.SubstrateUnderrunError(
+                        'Short octet stream on length decoding'
+                    )
+                firstOctet  = oct2int(substrate[0])
+                if firstOctet == 128:
+                    size = 1
+                    length = -1
+                elif firstOctet < 128:
+                    length, size = firstOctet, 1
+                else:
+                    size = firstOctet & 0x7F
+                    # encoded in size bytes
+                    length = 0
+                    lengthString = substrate[1:size+1]
+                    # missing check on maximum size, which shouldn't be a
+                    # problem, we can handle more than is possible
+                    if len(lengthString) != size:
+                        raise error.SubstrateUnderrunError(
+                            '%s<%s at %s' %
+                            (size, len(lengthString), tagSet)
+                            )
+                    for char in lengthString:
+                        length = (length << 8) | oct2int(char)
+                    size = size + 1
+                substrate = substrate[size:]
+                if length != -1 and len(substrate) < length:
+                    raise error.SubstrateUnderrunError(
+                        '%d-octet short' % (length - len(substrate))
+                        )
+                if length == -1 and not self.supportIndefLength:
+                    error.PyAsn1Error('Indefinite length encoding not supported by this codec')
+                state = stGetValueDecoder
+                debug.logger and debug.logger & debug.flagDecoder and debug.logger('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[:length])))
+            if state == stGetValueDecoder:
+                if asn1Spec is None:
+                    state = stGetValueDecoderByTag
+                else:
+                    state = stGetValueDecoderByAsn1Spec
+            #
+            # There're two ways of creating subtypes in ASN.1 what influences
+            # decoder operation. These methods are:
+            # 1) Either base types used in or no IMPLICIT tagging has been
+            #    applied on subtyping.
+            # 2) Subtype syntax drops base type information (by means of
+            #    IMPLICIT tagging.
+            # The first case allows for complete tag recovery from substrate
+            # while the second one requires original ASN.1 type spec for
+            # decoding.
+            #
+            # In either case a set of tags (tagSet) is coming from substrate
+            # in an incremental, tag-by-tag fashion (this is the case of
+            # EXPLICIT tag which is most basic). Outermost tag comes first
+            # from the wire.
+            #            
+            if state == stGetValueDecoderByTag:
+                if tagSet in self.__tagMap:
+                    concreteDecoder = self.__tagMap[tagSet]
+                else:
+                    concreteDecoder = None
+                if concreteDecoder:
+                    state = stDecodeValue
+                else:
+                    _k = tagSet[:1]
+                    if _k in self.__tagMap:
+                        concreteDecoder = self.__tagMap[_k]
+                    else:
+                        concreteDecoder = None
+                    if concreteDecoder:
+                        state = stDecodeValue
+                    else:
+                        state = stTryAsExplicitTag
+                if debug.logger and debug.logger & debug.flagDecoder:
+                    debug.logger('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag'))
+                    debug.scope.push(concreteDecoder is None and '?' or concreteDecoder.protoComponent.__class__.__name__)
+            if state == stGetValueDecoderByAsn1Spec:
+                if isinstance(asn1Spec, (dict, tagmap.TagMap)):
+                    if tagSet in asn1Spec:
+                        __chosenSpec = asn1Spec[tagSet]
+                    else:
+                        __chosenSpec = None
+                    if debug.logger and debug.logger & debug.flagDecoder:
+                        debug.logger('candidate ASN.1 spec is a map of:')
+                        for t, v in asn1Spec.getPosMap().items():
+                            debug.logger('  %s -> %s' % (t, v.__class__.__name__))
+                        if asn1Spec.getNegMap():
+                            debug.logger('but neither of: ')
+                            for t, v in asn1Spec.getNegMap().items():
+                                debug.logger('  %s -> %s' % (t, v.__class__.__name__))
+                        debug.logger('new candidate ASN.1 spec is %s, chosen by %s' % (__chosenSpec is None and '<none>' or __chosenSpec.prettyPrintType(), tagSet))
+                else:
+                    __chosenSpec = asn1Spec
+                    debug.logger and debug.logger & debug.flagDecoder and debug.logger('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__)
+                if __chosenSpec is not None and (
+                       tagSet == __chosenSpec.getTagSet() or \
+                       tagSet in __chosenSpec.getTagMap()
+                       ):
+                    # use base type for codec lookup to recover untagged types
+                    baseTagSet = __chosenSpec.baseTagSet
+                    if __chosenSpec.typeId is not None and \
+                           __chosenSpec.typeId in self.__typeMap:
+                        # ambiguous type
+                        concreteDecoder = self.__typeMap[__chosenSpec.typeId]
+                        debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen for an ambiguous type by type ID %s' % (__chosenSpec.typeId,))
+                    elif baseTagSet in self.__tagMap:
+                        # base type or tagged subtype
+                        concreteDecoder = self.__tagMap[baseTagSet]
+                        debug.logger and debug.logger & debug.flagDecoder and debug.logger('value decoder chosen by base %s' % (baseTagSet,))
+                    else:
+                        concreteDecoder = None
+                    if concreteDecoder:
+                        asn1Spec = __chosenSpec
+                        state = stDecodeValue
+                    else:
+                        state = stTryAsExplicitTag
+                else:
+                    concreteDecoder = None
+                    state = stTryAsExplicitTag
+                if debug.logger and debug.logger & debug.flagDecoder:
+                    debug.logger('codec %s chosen by ASN.1 spec, decoding %s' % (state == stDecodeValue and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as explicit tag'))
+                    debug.scope.push(__chosenSpec is None and '?' or __chosenSpec.__class__.__name__)
+            if state == stTryAsExplicitTag:
+                if tagSet and \
+                       tagSet[0][1] == tag.tagFormatConstructed and \
+                       tagSet[0][0] != tag.tagClassUniversal:
+                    # Assume explicit tagging
+                    concreteDecoder = explicitTagDecoder
+                    state = stDecodeValue
+                else:                    
+                    concreteDecoder = None
+                    state = self.defaultErrorState
+                debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or "<none>", state == stDecodeValue and 'value' or 'as failure'))
+            if state == stDumpRawValue:
+                concreteDecoder = self.defaultRawDecoder
+                debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__)
+                state = stDecodeValue
+            if state == stDecodeValue:
+                if recursiveFlag == 0 and not substrateFun: # legacy
+                    substrateFun = lambda a,b,c: (a,b[:c])
+                if length == -1:  # indef length
+                    value, substrate = concreteDecoder.indefLenValueDecoder(
+                        fullSubstrate, substrate, asn1Spec, tagSet, length,
+                        stGetValueDecoder, self, substrateFun
+                        )
+                else:
+                    value, substrate = concreteDecoder.valueDecoder(
+                        fullSubstrate, substrate, asn1Spec, tagSet, length,
+                        stGetValueDecoder, self, substrateFun
+                        )
+                state = stStop
+                debug.logger and debug.logger & debug.flagDecoder and debug.logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '<none>'))
+            if state == stErrorCondition:
+                raise error.PyAsn1Error(
+                    '%s not in asn1Spec: %s' % (tagSet, asn1Spec)
+                )
+        if debug.logger and debug.logger & debug.flagDecoder:
+            debug.scope.pop()
+            debug.logger('decoder left scope %s, call completed' % debug.scope)
+        return value, substrate
+            
+decode = Decoder(tagMap, typeMap)
+
+# XXX
+# non-recursive decoding; return position rather than substrate

+ 433 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/ber/encoder.py

@@ -0,0 +1,433 @@
+# BER encoder
+from pyasn1.type import base, tag, univ, char, useful
+from pyasn1.codec.ber import eoo
+from pyasn1.compat.octets import int2oct, oct2int, ints2octs, null, str2octs
+from pyasn1 import debug, error
+
+class Error(Exception): pass
+
+class AbstractItemEncoder:
+    supportIndefLenMode = 1
+    def encodeTag(self, t, isConstructed):
+        tagClass, tagFormat, tagId = t.asTuple()  # this is a hotspot
+        v = tagClass | tagFormat
+        if isConstructed:
+            v = v|tag.tagFormatConstructed
+        if tagId < 31:
+            return int2oct(v|tagId)
+        else:
+            s = int2oct(tagId&0x7f)
+            tagId = tagId >> 7
+            while tagId:
+                s = int2oct(0x80|(tagId&0x7f)) + s
+                tagId = tagId >> 7
+            return int2oct(v|0x1F) + s
+
+    def encodeLength(self, length, defMode):
+        if not defMode and self.supportIndefLenMode:
+            return int2oct(0x80)
+        if length < 0x80:
+            return int2oct(length)
+        else:
+            substrate = null
+            while length:
+                substrate = int2oct(length&0xff) + substrate
+                length = length >> 8
+            substrateLen = len(substrate)
+            if substrateLen > 126:
+                raise Error('Length octets overflow (%d)' % substrateLen)
+            return int2oct(0x80 | substrateLen) + substrate
+
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        raise Error('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
+            )
+        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
+
+class EndOfOctetsEncoder(AbstractItemEncoder):
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        return null, 0
+
+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
+
+class IntegerEncoder(AbstractItemEncoder):
+    supportIndefLenMode = 0
+    supportCompactZero = False
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        if value == 0:  # shortcut for zero value
+            if self.supportCompactZero:
+                # this seems to be a correct way for encoding zeros
+                return null, 0
+            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
+
+class BitStringEncoder(AbstractItemEncoder):
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        if not maxChunkSize or len(value) <= maxChunkSize*8:
+            out_len = (len(value) + 7) // 8
+            out_list = out_len * [0]
+            j = 7
+            i = -1
+            for val in value:
+                j += 1
+                if j == 8:
+                    i += 1
+                    j = 0
+                out_list[i] = out_list[i] | val << (7-j)
+            return int2oct(7-j) + ints2octs(out_list), 0
+        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
+
+class OctetStringEncoder(AbstractItemEncoder):
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        if not maxChunkSize or len(value) <= maxChunkSize:
+            return value.asOctets(), 0
+        else:
+            pos = 0; substrate = null
+            while 1:
+                v = value.clone(value[pos:pos+maxChunkSize])
+                if not v:
+                    break
+                substrate = substrate + encodeFun(v, defMode, maxChunkSize)
+                pos = pos + maxChunkSize
+            return substrate, 1
+
+class NullEncoder(AbstractItemEncoder):
+    supportIndefLenMode = 0
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        return null, 0
+
+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):    
+        oid = value.asTuple()
+        if oid[:5] in self.precomputedValues:
+            octets = self.precomputedValues[oid[:5]]
+            oid = oid[5:]
+        else:
+            if len(oid) < 2:
+                raise error.PyAsn1Error('Short OID %s' % (value,))
+
+            octets = ()
+
+            # Build the first twos
+            if oid[0] == 0 and 0 <= oid[1] <= 39:
+                oid = (oid[1],) + oid[2:]
+            elif oid[0] == 1 and 0 <= oid[1] <= 39:
+                oid = (oid[1] + 40,) + oid[2:]
+            elif oid[0] == 2:
+                oid = (oid[1] + 80,) + oid[2:]
+            else:
+                raise error.PyAsn1Error(
+                    'Impossible initial arcs %s at %s' % (oid[:2], value)
+                    )
+
+        # Cycle through subIds
+        for subId in oid:
+            if subId > -1 and subId < 128:
+                # Optimize for the common case
+                octets = octets + (subId & 0x7f,)
+            elif subId < 0:
+                raise error.PyAsn1Error(
+                    'Negative OID arc %s at %s' % (subId, value)
+                )
+            else:
+                # Pack large Sub-Object IDs
+                res = (subId & 0x7f,)
+                subId = subId >> 7
+                while subId > 0:
+                    res = (0x80 | (subId & 0x7f),) + res
+                    subId = subId >> 7 
+                # Add packed Sub-Object ID to resulted Object ID
+                octets += res
+
+        return ints2octs(octets), 0
+
+class RealEncoder(AbstractItemEncoder):
+    supportIndefLenMode = 0
+    binEncBase = 2 # set to None to choose encoding base automatically 
+    def _dropFloatingPoint(self, 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 = m*2**(abs(e) % 3 * es)
+            e = abs(e) // 3 * es
+        elif encbase == 16:
+            m = m*2**(abs(e) % 4 * es)
+            e = abs(e) // 4 * es
+
+        while 1:
+            if int(m) != m:
+                m *= encbase
+                e -= 1
+                continue
+            break
+        return ms, int(m), encbase, e
+
+    def _chooseEncBase(self, value):
+        m, b, e = value
+        base = [2, 8, 16]
+        if value.binEncBase in base:
+            return self._dropFloatingPoint(m, value.binEncBase, e)
+        elif self.binEncBase in base:
+            return self._dropFloatingPoint(m, self.binEncBase, e)
+        # auto choosing base 2/8/16 
+        mantissa = [m, m, m]
+        exponenta = [e, e, e]
+        encbase = 2 
+        e = float('inf')
+        for i in range(3):
+            sign, mantissa[i], base[i], exponenta[i] = \
+                self._dropFloatingPoint(mantissa[i], base[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 = base[i]
+        return sign, m, encbase, e
+
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        if value.isPlusInfinity():
+            return int2oct(0x40), 0
+        if value.isMinusInfinity():
+            return int2oct(0x41), 0
+        m, b, e = value
+        if not m:
+            return null, 0
+        if b == 10:
+            return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), 0
+        elif b == 2:
+            fo = 0x80 # binary encoding
+            ms, m, encbase, e = self._chooseEncBase(value)
+            if ms < 0: # mantissa sign
+                fo = 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
+                sf += 1
+            if sf > 3:
+                raise error.PyAsn1Error('Scale factor overflow') # bug if raised
+            fo |= sf << 2
+            eo = null
+            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')
+            if n == 1:
+                pass
+            elif n == 2:
+                fo |= 1
+            elif n == 3:
+                fo |= 2
+            else:
+                fo |= 3
+                eo = int2oct(n&0xff) + eo
+            po = null
+            while m:
+                po = int2oct(m&0xff) + po
+                m >>= 8
+            substrate = int2oct(fo) + eo + po
+            return substrate, 0
+        else:
+            raise error.PyAsn1Error('Prohibited Real base %s' % b)
+
+class SequenceEncoder(AbstractItemEncoder):
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        value.setDefaultComponents()
+        value.verifySizeSpec()
+        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
+
+class SequenceOfEncoder(AbstractItemEncoder):
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        value.verifySizeSpec()
+        substrate = null; idx = len(value)
+        while idx > 0:
+            idx = idx - 1
+            substrate = encodeFun(
+                value[idx], defMode, maxChunkSize
+                ) + substrate
+        return substrate, 1
+
+class ChoiceEncoder(AbstractItemEncoder):
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        return encodeFun(value.getComponent(), defMode, maxChunkSize), 1
+
+class AnyEncoder(OctetStringEncoder):
+    def encodeValue(self, encodeFun, value, defMode, maxChunkSize):
+        return value.asOctets(), defMode == 0
+
+tagMap = {
+    eoo.endOfOctets.tagSet: EndOfOctetsEncoder(),
+    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: OctetStringEncoder(),
+    char.NumericString.tagSet: OctetStringEncoder(),
+    char.PrintableString.tagSet: OctetStringEncoder(),
+    char.TeletexString.tagSet: OctetStringEncoder(),
+    char.VideotexString.tagSet: OctetStringEncoder(),
+    char.IA5String.tagSet: OctetStringEncoder(),
+    char.GraphicString.tagSet: OctetStringEncoder(),
+    char.VisibleString.tagSet: OctetStringEncoder(),
+    char.GeneralString.tagSet: OctetStringEncoder(),
+    char.UniversalString.tagSet: OctetStringEncoder(),
+    char.BMPString.tagSet: OctetStringEncoder(),
+    # 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: SequenceEncoder(),
+    univ.SetOf.typeId: SequenceOfEncoder(),
+    univ.Sequence.typeId: SequenceEncoder(),
+    univ.SequenceOf.typeId: SequenceOfEncoder(),
+    univ.Choice.typeId: ChoiceEncoder(),
+    univ.Any.typeId: AnyEncoder()
+    }
+
+class Encoder:
+    supportIndefLength = True
+    def __init__(self, tagMap, typeMap={}):
+        self.__tagMap = tagMap
+        self.__typeMap = typeMap
+
+    def __call__(self, value, defMode=True, maxChunkSize=0):
+        if not defMode and not self.supportIndefLength:
+            raise error.PyAsn1Error('Indefinite length encoding not supported by this codec')
+        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.prettyPrintType(), value.prettyPrint()))
+        tagSet = value.getTagSet()
+        if len(tagSet) > 1:
+            concreteEncoder = explicitlyTaggedItemEncoder
+        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 %s' % (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)))
+        return substrate
+
+encode = Encoder(tagMap, typeMap)

+ 8 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/ber/eoo.py

@@ -0,0 +1,8 @@
+from pyasn1.type import base, tag
+
+class EndOfOctets(base.AbstractSimpleAsn1Item):
+    defaultValue = 0
+    tagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x00)
+        )
+endOfOctets = EndOfOctets()

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/cer/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 35 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/cer/decoder.py

@@ -0,0 +1,35 @@
+# CER decoder
+from pyasn1.type import univ
+from pyasn1.codec.ber import decoder
+from pyasn1.compat.octets import oct2int
+from pyasn1 import error
+
+class BooleanDecoder(decoder.AbstractSimpleDecoder):
+    protoComponent = univ.Boolean(0)
+    def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length,
+                     state, decodeFun, substrateFun):
+        head, tail = substrate[:length], substrate[length:]
+        if not head:
+            raise error.PyAsn1Error('Empty substrate')
+        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 
+        # in http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+        if byte == 0xff:
+            value = 1
+        elif byte == 0x00:
+            value = 0
+        else:
+            raise error.PyAsn1Error('Boolean CER violation: %s' % byte)
+        return self._createComponent(asn1Spec, tagSet, value), tail
+
+tagMap = decoder.tagMap.copy()
+tagMap.update({
+    univ.Boolean.tagSet: BooleanDecoder()
+    })
+
+typeMap = decoder.typeMap
+
+class Decoder(decoder.Decoder): pass
+
+decode = Decoder(tagMap, decoder.typeMap)

+ 130 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/cer/encoder.py

@@ -0,0 +1,130 @@
+# CER encoder
+from pyasn1.type import univ
+from pyasn1.type import useful
+from pyasn1.codec.ber import encoder
+from pyasn1.compat.octets import int2oct, str2octs, null
+from pyasn1 import error
+
+class BooleanEncoder(encoder.IntegerEncoder):
+    def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
+        if client == 0:
+            substrate = int2oct(0)
+        else:
+            substrate = int2oct(255)
+        return substrate, 0
+
+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 GeneralStringEncoder here
+
+class GeneralizedTimeEncoder(OctetStringEncoder):
+    zchar = str2octs('Z')
+    pluschar = str2octs('+')
+    minuschar = str2octs('-')
+    zero = str2octs('0')
+    def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
+        octets = client.asOctets()
+# This breaks too many existing data items
+#        if '.' not in octets:
+#            raise error.PyAsn1Error('Format must include fraction of second: %r' % octets)
+        if len(octets) < 15:
+            raise error.PyAsn1Error('Bad UTC time length: %r' % octets)
+        if self.pluschar in octets or self.minuschar in octets:
+            raise error.PyAsn1Error('Must be UTC time: %r' % octets)
+        if octets[-1] != self.zchar[0]:
+            raise error.PyAsn1Error('Missing timezone specifier: %r' % octets)
+        return encoder.OctetStringEncoder.encodeValue(
+            self, encodeFun, client, defMode, 1000
+        )
+
+class UTCTimeEncoder(encoder.OctetStringEncoder):
+    zchar = str2octs('Z')
+    pluschar = str2octs('+')
+    minuschar = str2octs('-')
+    def encodeValue(self, encodeFun, client, defMode, maxChunkSize):
+        octets = client.asOctets()
+        if self.pluschar in octets or self.minuschar in octets:
+            raise error.PyAsn1Error('Must be UTC time: %r' % octets)
+        if octets and octets[-1] != self.zchar[0]:
+            client = client.clone(octets + self.zchar)
+        if len(client) != 13:
+            raise error.PyAsn1Error('Bad UTC time length: %r' % client)
+        return encoder.OctetStringEncoder.encodeValue(
+            self, encodeFun, client, defMode, 1000
+        )
+
+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
+            comps = []
+            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)
+        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
+
+tagMap = encoder.tagMap.copy()
+tagMap.update({
+    univ.Boolean.tagSet: BooleanEncoder(),
+    univ.BitString.tagSet: BitStringEncoder(),
+    univ.OctetString.tagSet: OctetStringEncoder(),
+    univ.Real.tagSet: RealEncoder(),
+    useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(),
+    useful.UTCTime.tagSet: UTCTimeEncoder(),
+    univ.SetOf().tagSet: SetOfEncoder()  # conflcts with Set
+})
+
+typeMap = encoder.typeMap.copy()
+typeMap.update({
+    univ.Set.typeId: SetOfEncoder(),
+    univ.SetOf.typeId: SetOfEncoder()
+})
+
+class Encoder(encoder.Encoder):
+    def __call__(self, client, defMode=False, maxChunkSize=0):
+        return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
+
+encode = Encoder(tagMap, typeMap)
+
+# EncoderFactory queries class instance and builds a map of tags -> encoders

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/der/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 9 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/der/decoder.py

@@ -0,0 +1,9 @@
+# DER decoder
+from pyasn1.codec.cer import decoder
+
+tagMap = decoder.tagMap
+typeMap = decoder.typeMap
+class Decoder(decoder.Decoder):
+    supportIndefLength = False
+
+decode = Decoder(tagMap, typeMap)

+ 32 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/codec/der/encoder.py

@@ -0,0 +1,32 @@
+# DER encoder
+from pyasn1.type import univ
+from pyasn1.codec.cer import encoder
+from pyasn1 import error
+
+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)
+
+tagMap = encoder.tagMap.copy()
+tagMap.update({
+    # Overload CER encoders 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()
+})
+
+typeMap = encoder.typeMap
+
+class Encoder(encoder.Encoder):
+    supportIndefLength = False
+    def __call__(self, client, defMode=True, maxChunkSize=0):
+        if not defMode:
+            raise error.PyAsn1Error('DER forbids indefinite length mode')
+        return encoder.Encoder.__call__(self, client, defMode, maxChunkSize)
+
+encode = Encoder(tagMap, typeMap)

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/compat/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 10 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/compat/binary.py

@@ -0,0 +1,10 @@
+from sys import version_info
+
+if version_info[0:2] < (2, 6):
+    def bin(x):
+        if x <= 1:
+            return '0b'+str(x)
+        else:
+            return bin(x>>1) + str(x&1)
+else:
+    bin = bin

+ 10 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/compat/iterfunc.py

@@ -0,0 +1,10 @@
+from sys import version_info
+
+if version_info[0] <= 2 and version_info[1] <= 4:
+    def all(iterable):
+        for element in iterable:
+            if not element:
+                return False
+        return True
+else:
+    all = all

+ 20 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/compat/octets.py

@@ -0,0 +1,20 @@
+from sys import version_info
+
+if version_info[0] <= 2:
+    int2oct = chr
+    ints2octs = lambda s: ''.join([ int2oct(x) for x in s ])
+    null = ''
+    oct2int = ord
+    octs2ints = lambda s: [ oct2int(x) for x in s ]
+    str2octs = lambda x: x
+    octs2str = lambda x: x
+    isOctetsType = lambda s: isinstance(s, str)
+else:
+    ints2octs = bytes
+    int2oct = lambda x: ints2octs((x,))
+    null = ints2octs()
+    oct2int = lambda x: x
+    octs2ints = lambda s: [ x for x in s ]
+    str2octs = lambda x: x.encode()
+    octs2str = lambda x: x.decode()
+    isOctetsType = lambda s: isinstance(s, bytes)

+ 110 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/debug.py

@@ -0,0 +1,110 @@
+import time
+import logging
+from pyasn1.compat.octets import octs2ints
+from pyasn1 import error
+from pyasn1 import __version__
+
+flagNone     = 0x0000
+flagEncoder  = 0x0001
+flagDecoder  = 0x0002
+flagAll      = 0xffff
+
+flagMap = {
+    'encoder': flagEncoder,
+    'decoder': flagDecoder,
+    'all': flagAll
+    }
+
+class Printer:
+    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 built-in 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:
+    defaultPrinter = None
+    def __init__(self, *flags, **options):
+        self._flags = flagNone
+        if options.get('printer') is not None:
+            self._printer = options.get('printer')
+        elif self.defaultPrinter is not None:
+            self._printer = self.defaultPrinter
+        if 'loggerName' in options: 
+            # route our logs to parent logger
+            self._printer = Printer(
+                logger=logging.getLogger(options['loggerName']),
+                handler=NullHandler()
+            )
+        else:
+            self._printer = Printer()
+        self('running pyasn1 version %s' % __version__)
+        for f in flags:
+            inverse = f and f[0] in ('!', '~')
+            if inverse:
+                f = f[1:]
+            try:
+                if inverse:
+                    self._flags &= ~flagMap[f]
+                else:
+                    self._flags |= flagMap[f]
+            except KeyError:
+                raise error.PyAsn1Error('bad debug flag %s' % f)
+  
+            self('debug category \'%s\' %s' % (f, inverse and 'disabled' or 'enabled'))
+
+    def __str__(self):
+        return 'logger %s, flags %x' % (self._printer, self._flags)
+    
+    def __call__(self, msg):
+        self._printer(msg)
+
+    def __and__(self, flag):
+        return self._flags & flag
+
+    def __rand__(self, flag):
+        return flag & self._flags
+
+logger = 0
+
+def setLogger(l):
+    global logger
+    logger = l
+
+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)) ]
+        )
+
+class Scope:
+    def __init__(self):
+        self._list = []
+
+    def __str__(self): return '.'.join(self._list)
+
+    def push(self, token):
+        self._list.append(token)
+
+    def pop(self):
+        return self._list.pop()
+
+scope = Scope()

+ 3 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/error.py

@@ -0,0 +1,3 @@
+class PyAsn1Error(Exception): pass
+class ValueConstraintError(PyAsn1Error): pass
+class SubstrateUnderrunError(PyAsn1Error): pass

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 277 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/base.py

@@ -0,0 +1,277 @@
+# Base classes for ASN.1 types
+import sys
+from pyasn1.type import constraint, tagmap, tag
+from pyasn1 import error
+
+class Asn1Item: pass
+
+class Asn1ItemBase(Asn1Item):
+    # Set of tags for this ASN.1 type
+    tagSet = tag.TagSet()
+    
+    # A list of constraint.Constraint instances for checking values
+    subtypeSpec = constraint.ConstraintsIntersection()
+
+    # Used for ambiguous 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 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, matchTags=True, matchConstraints=True):
+        return self is other or \
+               (not matchTags or \
+                self._tagSet == other.getTagSet()) and \
+               (not matchConstraints or \
+                self._subtypeSpec==other.getSubtypeSpec())
+
+    def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
+        """Returns true if argument is a ASN1 subtype of ourselves"""
+        return (not matchTags or  \
+                self._tagSet.isSuperTagSetOf(other.getTagSet())) and \
+               (not matchConstraints or \
+                (self._subtypeSpec.isSuperTypeOf(other.getSubtypeSpec())))
+
+class NoValue:
+    def __getattr__(self, attr):
+        raise error.PyAsn1Error('No value for %s()' % attr)
+    def __getitem__(self, i):
+        raise error.PyAsn1Error('No value')
+    def __repr__(self): return '%s()' % self.__class__.__name__
+    
+noValue = NoValue()
+
+# Base class for "simple" ASN.1 objects. These are immutable.
+class AbstractSimpleAsn1Item(Asn1ItemBase):    
+    defaultValue = noValue
+    def __init__(self, value=None, tagSet=None, subtypeSpec=None):
+        Asn1ItemBase.__init__(self, tagSet, subtypeSpec)
+        if value is None or value is noValue:
+            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)
+        self._value = value
+        self._len = None
+        
+    def __repr__(self):
+        r = []
+        if self._value is not self.defaultValue:
+            r.append(self.prettyOut(self._value))
+        if self._tagSet is not self.tagSet:
+            r.append('tagSet=%r' % (self._tagSet,))
+        if self._subtypeSpec is not self.subtypeSpec:
+            r.append('subtypeSpec=%r' % (self._subtypeSpec,))
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(r))
+
+    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
+    if sys.version_info[0] <= 2:
+        def __nonzero__(self): return bool(self._value)
+    else:
+        def __bool__(self): return bool(self._value)
+    def __hash__(self): return self.__hashedValue
+
+    def hasValue(self):
+        return not isinstance(self._value, NoValue)
+
+    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 subtype(self, value=None, implicitTag=None, explicitTag=None,
+                subtypeSpec=None):
+        if value is None:
+            value = self._value
+        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)
+
+    def prettyIn(self, value): return value
+    def prettyOut(self, value): return str(value)
+
+    def prettyPrint(self, scope=0):
+        if self.hasValue():
+            return self.prettyOut(self._value)
+        else:
+            return '<no value>'
+
+    # XXX Compatibility stub
+    def prettyPrinter(self, scope=0): return self.prettyPrint(scope)
+    
+    def prettyPrintType(self, scope=0):
+        return '%s -> %s' % (self.getTagSet(), self.__class__.__name__)
+
+#
+# Constructed types:
+# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice
+# * ASN1 types and values are represened by Python class instances
+# * Value initialization is made for defaulted components only
+# * Primary method of component addressing is by-position. Data model for base
+#   type is Python sequence. Additional type-specific addressing methods
+#   may be implemented for particular types.
+# * SequenceOf and SetOf types do not implement any additional methods
+# * Sequence, Set and Choice types also implement by-identifier addressing
+# * Sequence, Set and Choice types also implement by-asn1-type (tag) addressing
+# * Sequence and Set types may include optional and defaulted
+#   components
+# * Constructed types hold a reference to component types used for value
+#   verification and ordering.
+# * Component type is a scalar type for SequenceOf/SetOf types and a list
+#   of types for Sequence/Set/Choice.
+#
+
+class AbstractConstructedAsn1Item(Asn1ItemBase):
+    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
+        self._componentValues = []
+        self._componentValuesSet = 0
+
+    def __repr__(self):
+        r = []
+        if self._componentType is not self.componentType:
+            r.append('componentType=%r' % (self._componentType,))
+        if self._tagSet is not self.tagSet:
+            r.append('tagSet=%r' % (self._tagSet,))
+        if self._subtypeSpec is not self.subtypeSpec:
+            r.append('subtypeSpec=%r' % (self._subtypeSpec,))
+        r = '%s(%s)' % (self.__class__.__name__, ', '.join(r))
+        if self._componentValues:
+            r += '.setComponents(%s)' % ', '.join([repr(x) for x in self._componentValues])
+        return r
+
+    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
+    if sys.version_info[0] <= 2:
+        def __nonzero__(self): return bool(self._componentValues)
+    else:
+        def __bool__(self): return bool(self._componentValues)
+
+    def getComponentTagMap(self):
+        raise error.PyAsn1Error('Method not implemented')
+
+    def _cloneComponentValues(self, myClone, cloneValueFlag): pass
+
+    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
+
+    def subtype(self, implicitTag=None, explicitTag=None, subtypeSpec=None,
+                sizeSpec=None, cloneValueFlag=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)
+        if cloneValueFlag:
+            self._cloneComponentValues(r, cloneValueFlag)
+        return r
+
+    def _verifyComponent(self, idx, value): pass
+
+    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 setComponents(self, *args, **kwargs):
+        for idx in range(len(args)):
+            self[idx] = args[idx]
+        for k in kwargs:
+            self[k] = kwargs[k]
+        return self
+
+    def getComponentType(self): return self._componentType
+
+    def setDefaultComponents(self): pass
+
+    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 clear(self):
+        self._componentValues = []
+        self._componentValuesSet = 0
+

+ 64 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/char.py

@@ -0,0 +1,64 @@
+# ASN.1 "character string" types
+from pyasn1.type import univ, tag
+
+class NumericString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18)
+        )
+
+class PrintableString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 19)
+        )
+
+class TeletexString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20)
+        )
+
+class T61String(TeletexString): pass
+
+class VideotexString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 21)
+        )
+
+class IA5String(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 22)
+        )
+
+class GraphicString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 25)
+        )
+
+class VisibleString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26)
+        )
+
+class ISO646String(VisibleString): pass
+
+class GeneralString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27)
+        )
+
+class UniversalString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 28)
+        )
+    encoding = "utf-32-be"
+
+class BMPString(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30)
+        )
+    encoding = "utf-16-be"
+
+class UTF8String(univ.OctetString):
+    tagSet = univ.OctetString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
+        )
+    encoding = "utf-8"

+ 200 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/constraint.py

@@ -0,0 +1,200 @@
+#
+#   ASN.1 subtype constraints classes.
+#
+#   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.
+#
+#   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.
+#
+import sys
+from pyasn1.type import error
+
+class AbstractConstraint:
+    """Abstract base-class for constraint objects
+
+       Constraints should be stored in a simple sequence in the
+       namespace of their client Asn1Item sub-classes.
+    """
+    def __init__(self, *values):
+        self._valueMap = {}
+        self._setValues(values)
+        self.__hashedValues = None
+    def __call__(self, value, idx=None):
+        try:
+            self._testValue(value, idx)
+        except error.ValueConstraintError:
+            raise error.ValueConstraintError(
+               '%s failed at: \"%s\"' % (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
+    if sys.version_info[0] <= 2:
+        def __nonzero__(self): return bool(self._values)
+    else:
+        def __bool__(self): return bool(self._values)
+
+    def __hash__(self):
+        if self.__hashedValues is None:
+            self.__hashedValues = hash((self.__class__.__name__, self._values))
+        return self.__hashedValues
+
+    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 isSuperTypeOf(self, otherConstraint):
+        return self in otherConstraint.getValueMap() or \
+               otherConstraint is self or otherConstraint == self
+    def isSubTypeOf(self, otherConstraint):
+        return otherConstraint in self._valueMap or \
+               otherConstraint is self or otherConstraint == self
+
+class SingleValueConstraint(AbstractConstraint):
+    """Value must be part of defined values constraint"""
+    def _testValue(self, value, idx):
+        # XXX index vals for performance?
+        if value not in self._values:
+            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)
+
+    def _setValues(self, values):
+        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(
+                '%s: screwed constraint values (start > stop): %s > %s' % (
+                    self.__class__.__name__,
+                    self.start, self.stop
+                )
+            )
+        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:
+            raise error.ValueConstraintError(value)
+
+class PermittedAlphabetConstraint(SingleValueConstraint):
+    def _setValues(self, values):
+        self._values = ()
+        for v in values:
+            self._values = self._values + tuple(v)
+
+    def _testValue(self, value, idx):
+        for v in value:
+            if v not in self._values:
+                raise error.ValueConstraintError(value)
+
+# This is a bit kludgy, meaning two op modes within a single constraing
+class InnerTypeConstraint(AbstractConstraint):
+    """Value must satisfy type and presense constraints"""
+    def _testValue(self, value, idx):
+        if self.__singleTypeConstraint:
+            self.__singleTypeConstraint(value)
+        elif self.__multipleTypeConstraint:
+            if idx not in self.__multipleTypeConstraint:
+                raise error.ValueConstraintError(value)
+            constraint, status = self.__multipleTypeConstraint[idx]
+            if status == 'ABSENT':   # XXX presense is not checked!
+                raise error.ValueConstraintError(value)
+            constraint(value)
+
+    def _setValues(self, values):
+        self.__multipleTypeConstraint = {}
+        self.__singleTypeConstraint = None
+        for v in values:
+            if isinstance(v, tuple):
+                self.__multipleTypeConstraint[v[0]] = v[1], v[2]
+            else:
+                self.__singleTypeConstraint = v
+        AbstractConstraint._setValues(self, values)
+
+# 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)
+        except error.ValueConstraintError:
+            return
+        else:
+            raise error.ValueConstraintError(value)
+
+    def _setValues(self, values):
+        if len(values) != 1:
+            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 __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())
+
+class ConstraintsIntersection(AbstractConstraintSet):
+    """Value must satisfy all constraints"""
+    def _testValue(self, value, idx):
+        for v in self._values:
+            v(value, idx)
+
+class ConstraintsUnion(AbstractConstraintSet):
+    """Value must satisfy at least one constraint"""
+    def _testValue(self, value, idx):
+        for v in self._values:
+            try:
+                v(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

+ 3 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/error.py

@@ -0,0 +1,3 @@
+from pyasn1.error import PyAsn1Error
+
+class ValueConstraintError(PyAsn1Error): pass

+ 149 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/namedtype.py

@@ -0,0 +1,149 @@
+# NamedType specification for constructed types
+import sys
+from pyasn1.type import 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(%r, %r)' % (
+        self.__class__.__name__, self.__name, self.__type
+        )
+    def __eq__(self, other): return tuple(self) == tuple(other)
+    def __ne__(self, other): return tuple(self) != tuple(other)
+    def __lt__(self, other): return tuple(self) < tuple(other)
+    def __le__(self, other): return tuple(self) <= tuple(other)
+    def __gt__(self, other): return tuple(self) > tuple(other)
+    def __ge__(self, other): return tuple(self) >= tuple(other)
+    def __hash__(self): return hash(tuple(self))
+ 
+    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 = {}
+
+    def __repr__(self):
+        return '%s(%s)' % (
+            self.__class__.__name__,
+            ', '.join([ repr(x) for x in self.__namedTypes ])
+        )
+    def __eq__(self, other): return tuple(self) == tuple(other)
+    def __ne__(self, other): return tuple(self) != tuple(other)
+    def __lt__(self, other): return tuple(self) < tuple(other)
+    def __le__(self, other): return tuple(self) <= tuple(other)
+    def __gt__(self, other): return tuple(self) > tuple(other)
+    def __ge__(self, other): return tuple(self) >= tuple(other)
+    def __hash__(self): return hash(tuple(self))
+   
+    def __getitem__(self, idx): return self.__namedTypes[idx]
+
+    if sys.version_info[0] <= 2:
+        def __nonzero__(self): return bool(self.__namedTypesLen)
+    else:
+        def __bool__(self): return bool(self.__namedTypesLen)
+    def __len__(self): return self.__namedTypesLen
+   
+    def clone(self): return self.__class__(*self.__namedTypes)
+     
+    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 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
+        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()
+        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
+        try:
+            return self.__nameToPosIdx[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()
+        try:
+            return self.__ambigiousTypes[idx].getTagMap()
+        except KeyError:
+            raise error.PyAsn1Error('Type position out of range')
+
+    def getPositionNearType(self, tagSet, idx):
+        if not self.__ambigiousTypes: self.__buildAmbigiousTagMap()
+        try:
+            return idx+self.__ambigiousTypes[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
+        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]

+ 58 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/namedval.py

@@ -0,0 +1,58 @@
+# ASN.1 named integers
+from pyasn1 import error
+
+__all__ = [ 'NamedValues' ]
+
+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 __repr__(self):
+        return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(x) for x in self.namedValues]))
+
+    def __str__(self): return str(self.namedValues)
+
+    def __eq__(self, other): return tuple(self) == tuple(other)
+    def __ne__(self, other): return tuple(self) != tuple(other)
+    def __lt__(self, other): return tuple(self) < tuple(other)
+    def __le__(self, other): return tuple(self) <= tuple(other)
+    def __gt__(self, other): return tuple(self) > tuple(other)
+    def __ge__(self, other): return tuple(self) >= tuple(other)
+    def __hash__(self): return hash(tuple(self))
+    
+    def getName(self, value):
+        if value in self.valToNameIdx:
+            return self.valToNameIdx[value]
+
+    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)
+
+    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)
+
+# XXX clone/subtype?

+ 128 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/tag.py

@@ -0,0 +1,128 @@
+# ASN.1 types tags
+from operator import getitem
+from pyasn1 import error
+
+tagClassUniversal = 0x00
+tagClassApplication = 0x40
+tagClassContext = 0x80
+tagClassPrivate = 0xC0
+
+tagFormatSimple = 0x00
+tagFormatConstructed = 0x20
+
+tagCategoryImplicit = 0x01
+tagCategoryExplicit = 0x02
+tagCategoryUntagged = 0x04
+
+class Tag:
+    def __init__(self, tagClass, tagFormat, tagId):
+        if tagId < 0:
+            raise error.PyAsn1Error(
+                'Negative tag ID (%s) not allowed' % (tagId,)
+                )
+        self.__tag = (tagClass, tagFormat, tagId)
+        self.uniq = (tagClass, tagId)
+        self.__hashedUniqTag = hash(self.uniq)
+
+    def __str__(self):
+        return '[%s:%s:%s]' % self.__tag
+
+    def __repr__(self):
+        return '%s(tagClass=%s, tagFormat=%s, tagId=%s)' % (
+            (self.__class__.__name__,) + self.__tag
+            )
+    # These is really a hotspot -- expose public "uniq" attribute to save on
+    # function calls
+    def __eq__(self, other): return self.uniq == other.uniq
+    def __ne__(self, other): return self.uniq != other.uniq
+    def __lt__(self, other): return self.uniq < other.uniq
+    def __le__(self, other): return self.uniq <= other.uniq
+    def __gt__(self, other): return self.uniq > other.uniq
+    def __ge__(self, other): return self.uniq >= other.uniq
+    def __hash__(self): return self.__hashedUniqTag
+    def __getitem__(self, idx): return self.__tag[idx]
+    def __and__(self, otherTag):
+        (tagClass, tagFormat, tagId) = otherTag
+        return self.__class__(
+            self.__tag&tagClass, self.__tag&tagFormat, self.__tag&tagId
+            )
+    def __or__(self, otherTag):
+        (tagClass, tagFormat, tagId) = otherTag
+        return self.__class__(
+            self.__tag[0]|tagClass,
+            self.__tag[1]|tagFormat,
+            self.__tag[2]|tagId
+            )
+    def asTuple(self): return self.__tag  # __getitem__() is slow
+    
+class TagSet:
+    def __init__(self, baseTag=(), *superTags):
+        self.__baseTag = baseTag
+        self.__superTags = superTags
+        self.__hashedSuperTags = hash(superTags)
+        _uniq = ()
+        for t in superTags:
+            _uniq = _uniq + t.uniq
+        self.uniq = _uniq
+        self.__lenOfSuperTags = len(superTags)
+
+    def __str__(self):
+        return self.__superTags and '+'.join([str(x) for x in self.__superTags]) or '[untagged]'
+ 
+    def __repr__(self):
+        return '%s(%s)' % (
+            self.__class__.__name__,
+            '(), ' + ', '.join([repr(x) for x in self.__superTags])
+            )
+
+    def __add__(self, superTag):
+        return self.__class__(
+            self.__baseTag, *self.__superTags + (superTag,)
+            )
+    def __radd__(self, superTag):
+        return self.__class__(
+            self.__baseTag, *(superTag,) + self.__superTags
+            )
+
+    def tagExplicitly(self, superTag):
+        tagClass, tagFormat, tagId = superTag
+        if tagClass == tagClassUniversal:
+            raise error.PyAsn1Error(
+                'Can\'t tag with UNIVERSAL-class tag'
+                )
+        if tagFormat != tagFormatConstructed:
+            superTag = Tag(tagClass, tagFormatConstructed, tagId)
+        return self + superTag
+
+    def tagImplicitly(self, superTag):
+        tagClass, tagFormat, tagId = superTag
+        if self.__superTags:
+            superTag = Tag(tagClass, self.__superTags[-1][1], tagId)
+        return self[:-1] + superTag
+
+    def getBaseTag(self): return self.__baseTag
+    def __getitem__(self, idx):
+        if isinstance(idx, slice):
+            return self.__class__(
+               self.__baseTag, *getitem(self.__superTags, idx)
+            )
+        return self.__superTags[idx]
+    def __eq__(self, other): return self.uniq == other.uniq
+    def __ne__(self, other): return self.uniq != other.uniq
+    def __lt__(self, other): return self.uniq < other.uniq
+    def __le__(self, other): return self.uniq <= other.uniq
+    def __gt__(self, other): return self.uniq > other.uniq
+    def __ge__(self, other): return self.uniq >= other.uniq
+    def __hash__(self): return self.__hashedSuperTags
+    def __len__(self): return self.__lenOfSuperTags
+    def isSuperTagSetOf(self, tagSet):
+        if len(tagSet) < self.__lenOfSuperTags:
+            return
+        idx = self.__lenOfSuperTags - 1
+        while idx >= 0:
+            if self.__superTags[idx] != tagSet[idx]:
+                return
+            idx = idx - 1
+        return 1
+    
+def initTagSet(tag): return TagSet(tag, tag)

+ 66 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/tagmap.py

@@ -0,0 +1,66 @@
+from pyasn1 import error
+
+class TagMap:
+    def __init__(self, posMap={}, negMap={}, defType=None):
+        self.__posMap = posMap.copy()
+        self.__negMap = negMap.copy()
+        self.__defType = defType
+        
+    def __contains__(self, tagSet):
+        return tagSet in self.__posMap or \
+               self.__defType is not None and tagSet not in self.__negMap
+
+    def __getitem__(self, tagSet):
+        if tagSet in self.__posMap:
+            return self.__posMap[tagSet]
+        elif tagSet in self.__negMap:
+            raise error.PyAsn1Error('Key in negative map')
+        elif self.__defType is not None:
+            return self.__defType
+        else:
+            raise KeyError()
+
+    def __repr__(self):
+        s = self.__class__.__name__ + '('
+        if self.__posMap:
+            s = s + 'posMap=%r, ' % (self.__posMap,)
+        if self.__negMap:
+            s = s + 'negMap=%r, ' % (self.__negMap,)
+        if self.__defType is not None:
+            s = s + 'defType=%r' % (self.__defType,)
+        return s + ')'
+
+    def __str__(self):
+        s = self.__class__.__name__ + ':\n'
+        if self.__posMap:
+            s = s + 'posMap:\n%s, ' % ',\n '.join([ x.prettyPrintType() for x in self.__posMap.values()])
+        if self.__negMap:
+            s = s + 'negMap:\n%s, ' % ',\n '.join([ x.prettyPrintType() for x in self.__negMap.values()])
+        if self.__defType is not None:
+            s = s + 'defType:\n%s, ' % self.__defType.prettyPrintType()
+        return s
+
+    def clone(self, parentType, tagMap, uniq=False):
+        if self.__defType is not None and tagMap.getDef() is not None:
+            raise error.PyAsn1Error('Duplicate default value at %s' % (self,))
+        if tagMap.getDef() is not None:
+            defType = tagMap.getDef()
+        else:
+            defType = self.__defType
+            
+        posMap = self.__posMap.copy()
+        for k in tagMap.getPosMap():
+            if uniq and k in posMap:
+                raise error.PyAsn1Error('Duplicate positive key %s' % (k,))
+            posMap[k] = parentType
+
+        negMap = self.__negMap.copy()
+        negMap.update(tagMap.getNegMap())
+        
+        return self.__class__(
+            posMap, negMap, defType,
+            )
+
+    def getPosMap(self): return self.__posMap.copy()
+    def getNegMap(self): return self.__negMap.copy()
+    def getDef(self): return self.__defType

+ 1156 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/univ.py

@@ -0,0 +1,1156 @@
+# ASN.1 "universal" data types
+import operator, sys, math
+from pyasn1.type import base, tag, constraint, namedtype, namedval, tagmap
+from pyasn1.codec.ber import eoo
+from pyasn1.compat import octets
+from pyasn1 import error
+
+# "Simple" ASN.1 types (yet incomplete)
+
+class Integer(base.AbstractSimpleAsn1Item):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02)
+        )
+    namedValues = namedval.NamedValues()
+    def __init__(self, value=None, tagSet=None, subtypeSpec=None,
+                 namedValues=None):
+        if namedValues is None:
+            self.__namedValues = self.namedValues
+        else:
+            self.__namedValues = namedValues
+        base.AbstractSimpleAsn1Item.__init__(
+            self, value, tagSet, subtypeSpec
+            )
+
+    def __repr__(self):
+        if self.__namedValues is not self.namedValues:
+            return '%s, %r)' % (base.AbstractSimpleAsn1Item.__repr__(self)[:-1], self.__namedValues)
+        else:
+            return base.AbstractSimpleAsn1Item.__repr__(self)
+
+    def __and__(self, value): return self.clone(self._value & value)
+    def __rand__(self, value): return self.clone(value & self._value)
+    def __or__(self, value): return self.clone(self._value | value)
+    def __ror__(self, value): return self.clone(value | self._value)
+    def __xor__(self, value): return self.clone(self._value ^ value)
+    def __rxor__(self, value): return self.clone(value ^ self._value)
+    def __lshift__(self, value): return self.clone(self._value << value)
+    def __rshift__(self, value): return self.clone(self._value >> value)
+
+    def __add__(self, value): return self.clone(self._value + value)
+    def __radd__(self, value): return self.clone(value + self._value)
+    def __sub__(self, value): return self.clone(self._value - value)
+    def __rsub__(self, value): return self.clone(value - self._value)
+    def __mul__(self, value): return self.clone(self._value * value)
+    def __rmul__(self, value): return self.clone(value * self._value)
+    def __mod__(self, value): return self.clone(self._value % value)
+    def __rmod__(self, value): return self.clone(value % self._value)
+    def __pow__(self, value, modulo=None): return self.clone(pow(self._value, value, modulo))
+    def __rpow__(self, value): return self.clone(pow(value, self._value))
+
+    if sys.version_info[0] <= 2:
+        def __div__(self, value):  return self.clone(self._value // value)
+        def __rdiv__(self, value):  return self.clone(value // self._value)
+    else:
+        def __truediv__(self, value):  return self.clone(self._value / value)
+        def __rtruediv__(self, value):  return self.clone(value / self._value)
+        def __divmod__(self, value):  return self.clone(self._value // value)
+        def __rdivmod__(self, value):  return self.clone(value // self._value)
+
+        __hash__ = base.AbstractSimpleAsn1Item.__hash__
+
+    def __int__(self): return int(self._value)
+    if sys.version_info[0] <= 2:
+        def __long__(self): return long(self._value)
+    def __float__(self): return float(self._value)    
+    def __abs__(self): return self.clone(abs(self._value))
+    def __index__(self): return int(self._value)
+    def __pos__(self): return self.clone(+self._value)
+    def __neg__(self): return self.clone(-self._value)
+    def __invert__(self): return self.clone(~self._value)
+    def __round__(self, n=0):
+        r = round(self._value, n)
+        if n:
+            return self.clone(r)
+        else:
+            return r
+    def __floor__(self): return math.floor(self._value)
+    def __ceil__(self): return math.ceil(self._value)
+    if sys.version_info[0:2] > (2, 5):
+        def __trunc__(self): return self.clone(math.trunc(self._value))
+
+    def __lt__(self, value): return self._value < value
+    def __le__(self, value): return self._value <= value
+    def __eq__(self, value): return self._value == value
+    def __ne__(self, value): return self._value != value
+    def __gt__(self, value): return self._value > value
+    def __ge__(self, value): return self._value >= value
+
+    def prettyIn(self, value):
+        if not isinstance(value, str):
+            try:
+                return int(value)
+            except:
+                raise error.PyAsn1Error(
+                    'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
+                    )
+        r = self.__namedValues.getValue(value)
+        if r is not None:
+            return r
+        try:
+            return int(value)
+        except:
+            raise error.PyAsn1Error(
+                'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1])
+                )
+
+    def prettyOut(self, value):
+        r = self.__namedValues.getName(value)
+        return r is None and str(value) or repr(r)
+
+    def getNamedValues(self): return self.__namedValues
+
+    def clone(self, value=None, tagSet=None, subtypeSpec=None,
+              namedValues=None):
+        if value is None and tagSet is None and subtypeSpec is None \
+               and namedValues 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
+        if namedValues is None:
+            namedValues = self.__namedValues
+        return self.__class__(value, tagSet, subtypeSpec, namedValues)
+
+    def subtype(self, value=None, implicitTag=None, explicitTag=None,
+                subtypeSpec=None, namedValues=None):
+        if value is None:
+            value = self._value
+        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 namedValues is None:
+            namedValues = self.__namedValues
+        else:
+            namedValues = namedValues + self.__namedValues
+        return self.__class__(value, tagSet, subtypeSpec, namedValues)
+
+class Boolean(Integer):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01),
+        )
+    subtypeSpec = Integer.subtypeSpec+constraint.SingleValueConstraint(0,1)
+    namedValues = Integer.namedValues.clone(('False', 0), ('True', 1))
+
+class BitString(base.AbstractSimpleAsn1Item):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03)
+        )
+    namedValues = namedval.NamedValues()
+    def __init__(self, value=None, tagSet=None, subtypeSpec=None,
+                 namedValues=None):
+        if namedValues is None:
+            self.__namedValues = self.namedValues
+        else:
+            self.__namedValues = namedValues
+        base.AbstractSimpleAsn1Item.__init__(
+            self, value, tagSet, subtypeSpec
+            )
+
+    def clone(self, value=None, tagSet=None, subtypeSpec=None,
+              namedValues=None):
+        if value is None and tagSet is None and subtypeSpec is None \
+               and namedValues 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
+        if namedValues is None:
+            namedValues = self.__namedValues
+        return self.__class__(value, tagSet, subtypeSpec, namedValues)
+
+    def subtype(self, value=None, implicitTag=None, explicitTag=None,
+                subtypeSpec=None, namedValues=None):
+        if value is None:
+            value = self._value
+        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 namedValues is None:
+            namedValues = self.__namedValues
+        else:
+            namedValues = namedValues + self.__namedValues
+        return self.__class__(value, tagSet, subtypeSpec, namedValues)
+
+    def __str__(self): return str(tuple(self))
+
+    # Immutable sequence object protocol
+
+    def __len__(self):
+        if self._len is None:
+            self._len = len(self._value)
+        return self._len
+    def __getitem__(self, i):
+        if isinstance(i, slice):
+            return self.clone(operator.getitem(self._value, i))
+        else:
+            return self._value[i]
+
+    def __add__(self, value): return self.clone(self._value + value)
+    def __radd__(self, value): return self.clone(value + self._value)
+    def __mul__(self, value): return self.clone(self._value * value)
+    def __rmul__(self, value): return self * value
+
+    def prettyIn(self, value):
+        r = []
+        if not value:
+            return ()
+        elif isinstance(value, str):
+            if value[0] == '\'':
+                if value[-2:] == '\'B':
+                    for v in value[1:-2]:
+                        if v == '0':
+                            r.append(0)
+                        elif v == '1':
+                            r.append(1)
+                        else:
+                            raise error.PyAsn1Error(
+                                'Non-binary BIT STRING initializer %s' % (v,)
+                                )
+                    return tuple(r)
+                elif value[-2:] == '\'H':
+                    for v in value[1:-2]:
+                        i = 4
+                        v = int(v, 16)
+                        while i:
+                            i = i - 1
+                            r.append((v>>i)&0x01)
+                    return tuple(r)
+                else:
+                    raise error.PyAsn1Error(
+                        'Bad BIT STRING value notation %s' % (value,)
+                        )                
+            else:
+                for i in value.split(','):
+                    j = self.__namedValues.getValue(i)
+                    if j is None:
+                        raise error.PyAsn1Error(
+                            'Unknown bit identifier \'%s\'' % (i,)
+                            )
+                    if j >= len(r):
+                        r.extend([0]*(j-len(r)+1))
+                    r[j] = 1
+                return tuple(r)
+        elif isinstance(value, (tuple, list)):
+            r = tuple(value)
+            for b in r:
+                if b and b != 1:
+                    raise error.PyAsn1Error(
+                        'Non-binary BitString initializer \'%s\'' % (r,)
+                        )
+            return r
+        elif isinstance(value, BitString):
+            return tuple(value)
+        else:
+            raise error.PyAsn1Error(
+                'Bad BitString initializer type \'%s\'' % (value,)
+                )
+
+    def prettyOut(self, value):
+        return '\"\'%s\'B\"' % ''.join([str(x) for x in value])
+
+try:
+    all
+except NameError:  # Python 2.4
+    def all(iterable):
+        for element in iterable:
+            if not element:
+                return False
+        return True
+
+class OctetString(base.AbstractSimpleAsn1Item):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04)
+        )
+    defaultBinValue = defaultHexValue = base.noValue
+    encoding = 'us-ascii'
+    def __init__(self, value=None, tagSet=None, subtypeSpec=None,
+                 encoding=None, binValue=None, hexValue=None):
+        if encoding is None:
+            self._encoding = self.encoding
+        else:
+            self._encoding = encoding
+        if binValue is not None:
+            value = self.fromBinaryString(binValue)
+        if hexValue is not None:
+            value = self.fromHexString(hexValue)
+        if value is None or value is base.noValue:
+            value = self.defaultHexValue
+        if value is None or value is base.noValue:
+            value = self.defaultBinValue
+        self.__asNumbersCache = None
+        base.AbstractSimpleAsn1Item.__init__(self, value, tagSet, subtypeSpec)
+
+    def clone(self, value=None, tagSet=None, subtypeSpec=None,
+              encoding=None, binValue=None, hexValue=None):
+        if value is None and tagSet is None and subtypeSpec is None and \
+               encoding is None and binValue is None and hexValue is None:
+            return self
+        if value is None and binValue is None and hexValue is None:
+            value = self._value
+        if tagSet is None:
+            tagSet = self._tagSet
+        if subtypeSpec is None:
+            subtypeSpec = self._subtypeSpec
+        if encoding is None:
+            encoding = self._encoding
+        return self.__class__(
+            value, tagSet, subtypeSpec, encoding, binValue, hexValue
+            )
+   
+    if sys.version_info[0] <= 2:
+        def prettyIn(self, value):
+            if isinstance(value, str):
+                return value
+            elif isinstance(value, unicode):
+                try:
+                    return value.encode(self._encoding)
+                except (LookupError, UnicodeEncodeError):
+                    raise error.PyAsn1Error(
+                        'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding)
+                    )
+            elif isinstance(value, (tuple, list)):
+                try:
+                    return ''.join([ chr(x) for x in value ])
+                except ValueError:
+                    raise error.PyAsn1Error(
+                        'Bad OctetString initializer \'%s\'' % (value,)
+                    )                
+            else:
+                return str(value)
+    else:
+        def prettyIn(self, value):
+            if isinstance(value, bytes):
+                return value
+            elif isinstance(value, str):
+                try:
+                    return value.encode(self._encoding)
+                except UnicodeEncodeError:
+                    raise error.PyAsn1Error(
+                        'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding)
+                    )
+            elif isinstance(value, OctetString):
+                return value.asOctets()
+            elif isinstance(value, (tuple, list, map)):
+                try:
+                    return bytes(value)
+                except ValueError:
+                    raise error.PyAsn1Error(
+                        'Bad OctetString initializer \'%s\'' % (value,)
+                    )
+            else:
+                try:
+                    return str(value).encode(self._encoding)
+                except UnicodeEncodeError:
+                    raise error.PyAsn1Error(
+                        'Can\'t encode string \'%s\' with \'%s\' codec' % (value, self._encoding)
+                    )
+                        
+
+    def fromBinaryString(self, value):
+        bitNo = 8; byte = 0; r = ()
+        for v in value:
+            if bitNo:
+                bitNo = bitNo - 1
+            else:
+                bitNo = 7
+                r = r + (byte,)
+                byte = 0
+            if v == '0':
+                v = 0
+            elif v == '1':
+                v = 1
+            else:
+                raise error.PyAsn1Error(
+                    'Non-binary OCTET STRING initializer %s' % (v,)
+                    )
+            byte = byte | (v << bitNo)
+        return octets.ints2octs(r + (byte,))
+        
+    def fromHexString(self, value):            
+        r = p = ()
+        for v in value:
+            if p:
+                r = r + (int(p+v, 16),)
+                p = ()
+            else:
+                p = v
+        if p:
+            r = r + (int(p+'0', 16),)
+        return octets.ints2octs(r)
+
+    def prettyOut(self, value):
+        if sys.version_info[0] <= 2:
+            numbers = tuple(( ord(x) for x in value ))
+        else:
+            numbers = tuple(value)
+        if all(x >= 32 and x <= 126 for x in numbers):
+            return str(value)
+        else:
+            return '0x' + ''.join(( '%.2x' % x for x in numbers ))
+
+    def __repr__(self):
+        r = []
+        doHex = False
+        if self._value is not self.defaultValue:
+            for x in self.asNumbers():
+                if x < 32 or x > 126:
+                    doHex = True
+                    break
+            if not doHex:
+                r.append('%r' % (self._value,))
+        if self._tagSet is not self.tagSet:
+            r.append('tagSet=%r' % (self._tagSet,))
+        if self._subtypeSpec is not self.subtypeSpec:
+            r.append('subtypeSpec=%r' % (self._subtypeSpec,))
+        if self.encoding is not self._encoding:
+            r.append('encoding=%r' % (self._encoding,))
+        if doHex:
+            r.append('hexValue=%r' % ''.join([ '%.2x' % x for x in self.asNumbers() ]))
+        return '%s(%s)' % (self.__class__.__name__, ', '.join(r))
+                                
+    if sys.version_info[0] <= 2:
+        def __str__(self): return str(self._value)
+        def __unicode__(self):
+            return self._value.decode(self._encoding, 'ignore')
+        def asOctets(self): return self._value
+        def asNumbers(self):
+            if self.__asNumbersCache is None:
+                self.__asNumbersCache = tuple([ ord(x) for x in self._value ])
+            return self.__asNumbersCache
+    else:
+        def __str__(self): return self._value.decode(self._encoding, 'ignore')
+        def __bytes__(self): return self._value
+        def asOctets(self): return self._value
+        def asNumbers(self):
+            if self.__asNumbersCache is None:
+                self.__asNumbersCache = tuple(self._value)
+            return self.__asNumbersCache
+ 
+    # Immutable sequence object protocol
+    
+    def __len__(self):
+        if self._len is None:
+            self._len = len(self._value)
+        return self._len
+    def __getitem__(self, i):
+        if isinstance(i, slice):
+            return self.clone(operator.getitem(self._value, i))
+        else:
+            return self._value[i]
+
+    def __add__(self, value): return self.clone(self._value + self.prettyIn(value))
+    def __radd__(self, value): return self.clone(self.prettyIn(value) + self._value)
+    def __mul__(self, value): return self.clone(self._value * value)
+    def __rmul__(self, value): return self * value
+    def __int__(self): return int(self._value)
+    def __float__(self): return float(self._value)
+    
+class Null(OctetString):
+    defaultValue = ''.encode()  # This is tightly constrained
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05)
+        )
+    subtypeSpec = OctetString.subtypeSpec+constraint.SingleValueConstraint(''.encode())
+    
+if sys.version_info[0] <= 2:
+    intTypes = (int, long)
+else:
+    intTypes = (int,)
+
+numericTypes = intTypes + (float,)
+
+class ObjectIdentifier(base.AbstractSimpleAsn1Item):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06)
+        )
+    def __add__(self, other): return self.clone(self._value + other)
+    def __radd__(self, other): return self.clone(other + self._value)
+
+    def asTuple(self): return self._value
+    
+    # Sequence object protocol
+    
+    def __len__(self):
+        if self._len is None:
+            self._len = len(self._value)
+        return self._len
+    def __getitem__(self, i):
+        if isinstance(i, slice):
+            return self.clone(
+                operator.getitem(self._value, i)
+                )
+        else:
+            return self._value[i]
+
+    def __str__(self): return self.prettyPrint()
+    def __repr__(self):
+        return '%s(%r)' % (self.__class__.__name__, self.prettyPrint())
+
+    def index(self, suboid): return self._value.index(suboid)
+
+    def isPrefixOf(self, value):
+        """Returns true if argument OID resides deeper in the OID tree"""
+        l = len(self)
+        if l <= len(value):
+            if self._value[:l] == value[:l]:
+                return 1
+        return 0
+
+    def prettyIn(self, value):
+        """Dotted -> tuple of numerics OID converter"""
+        if isinstance(value, tuple):
+            pass
+        elif isinstance(value, ObjectIdentifier):
+            return tuple(value)        
+        elif isinstance(value, str):
+            r = []
+            for element in [ x for x in value.split('.') if x != '' ]:
+                try:
+                    r.append(int(element, 0))
+                except ValueError:
+                    raise error.PyAsn1Error(
+                        'Malformed Object ID %s at %s: %s' %
+                        (str(value), self.__class__.__name__, sys.exc_info()[1])
+                        )
+            value = tuple(r)
+        else:
+            try:
+                value = tuple(value)
+            except TypeError:
+                raise error.PyAsn1Error(
+                        'Malformed Object ID %s at %s: %s' %
+                        (str(value), self.__class__.__name__,sys.exc_info()[1])
+                        )
+
+        for x in value:
+            if not isinstance(x, intTypes) or x < 0:
+                raise error.PyAsn1Error(
+                    'Invalid sub-ID in %s at %s' % (value, self.__class__.__name__)
+                    )
+    
+        return value
+
+    def prettyOut(self, value): return '.'.join([ str(x) for x in value ])
+    
+class Real(base.AbstractSimpleAsn1Item):
+    binEncBase = None # binEncBase = 16 is recommended for large numbers
+    try:
+        _plusInf = float('inf')
+        _minusInf = float('-inf')
+        _inf = (_plusInf, _minusInf)
+    except ValueError:
+        # Infinity support is platform and Python dependent
+        _plusInf = _minusInf = None
+        _inf = ()
+
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09)
+        )
+
+    def __normalizeBase10(self, value):
+        m, b, e = value
+        while m and m % 10 == 0:
+            m = m / 10
+            e = e + 1
+        return m, b, e
+
+    def prettyIn(self, value):
+        if isinstance(value, tuple) and len(value) == 3:
+            if not isinstance(value[0], numericTypes) or \
+                    not isinstance(value[1], intTypes) or \
+                    not isinstance(value[2], intTypes):
+                raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,))
+            if isinstance(value[0], float) and \
+                self._inf and value[0] in self._inf:
+                return value[0]
+            if value[1] not in (2, 10):
+                raise error.PyAsn1Error(
+                    'Prohibited base for Real value: %s' % (value[1],)
+                    )
+            if value[1] == 10:
+                value = self.__normalizeBase10(value)
+            return value
+        elif isinstance(value, intTypes):
+            return self.__normalizeBase10((value, 10, 0))
+        elif isinstance(value, (str, float)):
+            if isinstance(value, str):
+                try:
+                    value = float(value)
+                except ValueError:
+                    raise error.PyAsn1Error(
+                        'Bad real value syntax: %s' % (value,)
+                    )
+            if self._inf and value in self._inf:
+                return value
+            else:
+                e = 0
+                while int(value) != value:
+                    value = value * 10
+                    e = e - 1
+                return self.__normalizeBase10((int(value), 10, e))
+        elif isinstance(value, Real):
+            return tuple(value)
+        raise error.PyAsn1Error(
+            'Bad real value syntax: %s' % (value,)
+            )
+        
+    def prettyOut(self, value):
+        if value in self._inf:
+            return '\'%s\'' % value
+        else:
+            return str(value)
+
+    def prettyPrint(self, scope=0):
+        if self.isInfinity():
+            return self.prettyOut(self._value)
+        else:
+            return str(float(self))
+
+    def isPlusInfinity(self): return self._value == self._plusInf
+    def isMinusInfinity(self): return self._value == self._minusInf
+    def isInfinity(self): return self._value in self._inf
+    
+    def __str__(self): return str(float(self))
+    
+    def __add__(self, value): return self.clone(float(self) + value)
+    def __radd__(self, value): return self + value
+    def __mul__(self, value): return self.clone(float(self) * value)
+    def __rmul__(self, value): return self * value
+    def __sub__(self, value): return self.clone(float(self) - value)
+    def __rsub__(self, value): return self.clone(value - float(self))
+    def __mod__(self, value): return self.clone(float(self) % value)
+    def __rmod__(self, value): return self.clone(value % float(self))
+    def __pow__(self, value, modulo=None): return self.clone(pow(float(self), value, modulo))
+    def __rpow__(self, value): return self.clone(pow(value, float(self)))
+
+    if sys.version_info[0] <= 2:
+        def __div__(self, value): return self.clone(float(self) / value)
+        def __rdiv__(self, value): return self.clone(value / float(self))
+    else:
+        def __truediv__(self, value): return self.clone(float(self) / value)
+        def __rtruediv__(self, value): return self.clone(value / float(self))
+        def __divmod__(self, value): return self.clone(float(self) // value)
+        def __rdivmod__(self, value): return self.clone(value // float(self))
+
+    def __int__(self): return int(float(self))
+    if sys.version_info[0] <= 2:
+        def __long__(self): return long(float(self))
+    def __float__(self):
+        if self._value in self._inf:
+            return self._value
+        else:
+            return float(
+                self._value[0] * pow(self._value[1], self._value[2])
+            )
+    def __abs__(self): return self.clone(abs(float(self)))
+    def __pos__(self): return self.clone(+float(self))
+    def __neg__(self): return self.clone(-float(self))
+    def __round__(self, n=0):
+        r = round(float(self), n)
+        if n:
+            return self.clone(r)
+        else:
+            return r
+    def __floor__(self): return self.clone(math.floor(float(self)))
+    def __ceil__(self): return self.clone(math.ceil(float(self)))
+    if sys.version_info[0:2] > (2, 5):
+        def __trunc__(self): return self.clone(math.trunc(float(self)))
+
+    def __lt__(self, value): return float(self) < value
+    def __le__(self, value): return float(self) <= value
+    def __eq__(self, value): return float(self) == value
+    def __ne__(self, value): return float(self) != value
+    def __gt__(self, value): return float(self) > value
+    def __ge__(self, value): return float(self) >= value
+
+    if sys.version_info[0] <= 2:
+        def __nonzero__(self): return bool(float(self))
+    else:
+        def __bool__(self): return bool(float(self))
+        __hash__ = base.AbstractSimpleAsn1Item.__hash__
+
+    def __getitem__(self, idx):
+        if self._value in self._inf:
+            raise error.PyAsn1Error('Invalid infinite value operation')
+        else:
+            return self._value[idx]
+    
+class Enumerated(Integer):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0A)
+        )
+
+# "Structured" ASN.1 types
+
+class SetOf(base.AbstractConstructedAsn1Item):
+    componentType = None
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
+        )
+    typeId = 1
+    strictConstraints = False
+
+    def _cloneComponentValues(self, myClone, cloneValueFlag):
+        idx = 0; l = len(self._componentValues)
+        while idx < l:
+            c = self._componentValues[idx]
+            if c is not None:
+                if isinstance(c, base.AbstractConstructedAsn1Item):
+                    myClone.setComponentByPosition(
+                        idx, c.clone(cloneValueFlag=cloneValueFlag)
+                        )
+                else:
+                    myClone.setComponentByPosition(idx, c.clone())
+            idx = idx + 1
+        
+    def _verifyComponent(self, idx, value):
+        t = self._componentType
+        if t is None:
+            return
+        if not t.isSameTypeWith(value,matchConstraints=self.strictConstraints):
+            raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, t))
+        if self.strictConstraints and \
+                not t.isSuperTypeOf(value, matchTags=False):
+            raise error.PyAsn1Error('Component value is constraints-incompatible: %r vs %r' % (value, t))
+
+    def getComponentByPosition(self, idx): return self._componentValues[idx]
+    def setComponentByPosition(self, idx, value=None, verifyConstraints=True):
+        l = len(self._componentValues)
+        if idx >= l:
+            self._componentValues = self._componentValues + (idx-l+1)*[None]
+        if value is None:
+            if self._componentValues[idx] is None:
+                if self._componentType is None:
+                    raise error.PyAsn1Error('Component type not defined')
+                self._componentValues[idx] = self._componentType.clone()
+                self._componentValuesSet = self._componentValuesSet + 1
+            return self
+        elif not isinstance(value, base.Asn1Item):
+            if self._componentType is None:
+                raise error.PyAsn1Error('Component type not defined')
+            if isinstance(self._componentType, base.AbstractSimpleAsn1Item):
+                value = self._componentType.clone(value=value)
+            else:
+                raise error.PyAsn1Error('Instance value required')
+        if verifyConstraints:
+            if self._componentType is not None:
+                self._verifyComponent(idx, value)
+            self._verifySubtypeSpec(value, idx)            
+        if self._componentValues[idx] is None:
+            self._componentValuesSet = self._componentValuesSet + 1
+        self._componentValues[idx] = value
+        return self
+
+    def getComponentTagMap(self):
+        if self._componentType is not None:
+            return self._componentType.getTagMap()
+
+    def prettyPrint(self, scope=0):
+        scope = scope + 1
+        r = self.__class__.__name__ + ':\n'        
+        for idx in range(len(self._componentValues)):
+            r = r + ' '*scope
+            if self._componentValues[idx] is None:
+                r = r + '<empty>'
+            else:
+                r = r + self._componentValues[idx].prettyPrint(scope)
+        return r
+
+    def prettyPrintType(self, scope=0):
+        scope = scope + 1
+        r = '%s -> %s {\n' % (self.getTagSet(), self.__class__.__name__)
+        if self._componentType is not None:
+            r = r + ' '*scope
+            r = r + self._componentType.prettyPrintType(scope)
+        return r + '\n' + ' '*(scope-1) + '}'
+
+class SequenceOf(SetOf):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
+        )
+    typeId = 2
+
+class SequenceAndSetBase(base.AbstractConstructedAsn1Item):
+    componentType = namedtype.NamedTypes()
+    strictConstraints = False
+    def __init__(self, componentType=None, tagSet=None,
+                 subtypeSpec=None, sizeSpec=None):
+        if componentType is None:
+            componentType = self.componentType
+        base.AbstractConstructedAsn1Item.__init__(
+            self, componentType.clone(), tagSet, subtypeSpec, sizeSpec
+        )
+        self._componentTypeLen = len(self._componentType)
+
+    def __getitem__(self, idx):
+        if isinstance(idx, str):
+            return self.getComponentByName(idx)
+        else:
+            return base.AbstractConstructedAsn1Item.__getitem__(self, idx)
+
+    def __setitem__(self, idx, value):
+        if isinstance(idx, str):
+            self.setComponentByName(idx, value)
+        else:
+            base.AbstractConstructedAsn1Item.__setitem__(self, idx, value)
+        
+    def _cloneComponentValues(self, myClone, cloneValueFlag):
+        idx = 0; l = len(self._componentValues)
+        while idx < l:
+            c = self._componentValues[idx]
+            if c is not None:
+                if isinstance(c, base.AbstractConstructedAsn1Item):
+                    myClone.setComponentByPosition(
+                        idx, c.clone(cloneValueFlag=cloneValueFlag)
+                        )
+                else:
+                    myClone.setComponentByPosition(idx, c.clone())
+            idx = idx + 1
+
+    def _verifyComponent(self, idx, value):
+        if idx >= self._componentTypeLen:
+            raise error.PyAsn1Error(
+                'Component type error out of range'
+                )
+        t = self._componentType[idx].getType()
+        if not t.isSameTypeWith(value,matchConstraints=self.strictConstraints):
+            raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, t))
+        if self.strictConstraints and \
+                not t.isSuperTypeOf(value, matchTags=False):
+            raise error.PyAsn1Error('Component value is constraints-incompatible: %r vs %r' % (value, t))
+
+    def getComponentByName(self, name):
+        return self.getComponentByPosition(
+            self._componentType.getPositionByName(name)
+            )
+    def setComponentByName(self, name, value=None, verifyConstraints=True):
+        return self.setComponentByPosition(
+            self._componentType.getPositionByName(name),value,verifyConstraints
+        )
+
+    def getComponentByPosition(self, idx):
+        try:
+            return self._componentValues[idx]
+        except IndexError:
+            if idx < self._componentTypeLen:
+                return
+            raise
+    def setComponentByPosition(self, idx, value=None,
+                               verifyConstraints=True,
+                               exactTypes=False,
+                               matchTags=True,
+                               matchConstraints=True):
+        l = len(self._componentValues)
+        if idx >= l:
+            self._componentValues = self._componentValues + (idx-l+1)*[None]
+        if value is None:
+            if self._componentValues[idx] is None:
+                self._componentValues[idx] = self._componentType.getTypeByPosition(idx).clone()
+                self._componentValuesSet = self._componentValuesSet + 1
+            return self
+        elif not isinstance(value, base.Asn1Item):
+            t = self._componentType.getTypeByPosition(idx)
+            if isinstance(t, base.AbstractSimpleAsn1Item):
+                value = t.clone(value=value)
+            else:
+                raise error.PyAsn1Error('Instance value required')
+        if verifyConstraints:
+            if self._componentTypeLen:
+                self._verifyComponent(idx, value)
+            self._verifySubtypeSpec(value, idx)            
+        if self._componentValues[idx] is None:
+            self._componentValuesSet = self._componentValuesSet + 1
+        self._componentValues[idx] = value
+        return self
+
+    def getNameByPosition(self, idx):
+        if self._componentTypeLen:
+            return self._componentType.getNameByPosition(idx)
+
+    def getDefaultComponentByPosition(self, idx):
+        if self._componentTypeLen and self._componentType[idx].isDefaulted:
+            return self._componentType[idx].getType()
+
+    def getComponentType(self):
+        if self._componentTypeLen:
+            return self._componentType
+    
+    def setDefaultComponents(self):
+        if self._componentTypeLen == self._componentValuesSet:
+            return
+        idx = self._componentTypeLen
+        while idx:
+            idx = idx - 1
+            if self._componentType[idx].isDefaulted:
+                if self.getComponentByPosition(idx) is None:
+                    self.setComponentByPosition(idx)
+            elif not self._componentType[idx].isOptional:
+                if self.getComponentByPosition(idx) is None:
+                    raise error.PyAsn1Error(
+                        'Uninitialized component #%s at %r' % (idx, self)
+                        )
+
+    def prettyPrint(self, scope=0):
+        scope = scope + 1
+        r = self.__class__.__name__ + ':\n'
+        for idx in range(len(self._componentValues)):
+            if self._componentValues[idx] is not None:
+                r = r + ' '*scope
+                componentType = self.getComponentType()
+                if componentType is None:
+                    r = r + '<no-name>'
+                else:
+                    r = r + componentType.getNameByPosition(idx)
+                r = '%s=%s\n' % (
+                    r, self._componentValues[idx].prettyPrint(scope)
+                    )
+        return r
+
+    def prettyPrintType(self, scope=0):
+        scope = scope + 1
+        r = '%s -> %s {\n' % (self.getTagSet(), self.__class__.__name__)
+        for idx in range(len(self.componentType)):
+            r = r + ' '*scope
+            r = r + '"%s"' % self.componentType.getNameByPosition(idx)
+            r = '%s = %s\n' % (
+                r, self._componentType.getTypeByPosition(idx).prettyPrintType(scope)
+            )
+        return r + '\n' + ' '*(scope-1) + '}'
+
+class Sequence(SequenceAndSetBase):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
+        )
+    typeId = 3
+
+    def getComponentTagMapNearPosition(self, idx):
+        if self._componentType:
+            return self._componentType.getTagMapNearPosition(idx)
+    
+    def getComponentPositionNearType(self, tagSet, idx):
+        if self._componentType:
+            return self._componentType.getPositionNearType(tagSet, idx)
+        else:
+            return idx
+    
+class Set(SequenceAndSetBase):
+    tagSet = baseTagSet = tag.initTagSet(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
+        )
+    typeId = 4
+
+    def getComponent(self, innerFlag=0): return self
+    
+    def getComponentByType(self, tagSet, innerFlag=0):
+        c = self.getComponentByPosition(
+            self._componentType.getPositionByType(tagSet)
+            )
+        if innerFlag and isinstance(c, Set):
+            # get inner component by inner tagSet
+            return c.getComponent(1)
+        else:
+            # get outer component by inner tagSet
+            return c
+        
+    def setComponentByType(self, tagSet, value=None, innerFlag=0,
+                           verifyConstraints=True):
+        idx = self._componentType.getPositionByType(tagSet)
+        t = self._componentType.getTypeByPosition(idx)
+        if innerFlag:  # set inner component by inner tagSet
+            if t.getTagSet():
+                return self.setComponentByPosition(
+                    idx, value, verifyConstraints
+                )
+            else:
+                t = self.setComponentByPosition(idx).getComponentByPosition(idx)
+                return t.setComponentByType(
+                    tagSet, value, innerFlag, verifyConstraints
+                )
+        else:  # set outer component by inner tagSet
+            return self.setComponentByPosition(
+                idx, value, verifyConstraints
+            )
+            
+    def getComponentTagMap(self):
+        if self._componentType:
+            return self._componentType.getTagMap(True)
+
+    def getComponentPositionByType(self, tagSet):
+        if self._componentType:
+            return self._componentType.getPositionByType(tagSet)
+
+class Choice(Set):
+    tagSet = baseTagSet = tag.TagSet()  # untagged
+    sizeSpec = constraint.ConstraintsIntersection(
+        constraint.ValueSizeConstraint(1, 1)
+        )
+    typeId = 5
+    _currentIdx = None
+
+    def __eq__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] == other
+        return NotImplemented
+    def __ne__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] != other
+        return NotImplemented
+    def __lt__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] < other
+        return NotImplemented
+    def __le__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] <= other
+        return NotImplemented
+    def __gt__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] > other
+        return NotImplemented
+    def __ge__(self, other):
+        if self._componentValues:
+            return self._componentValues[self._currentIdx] >= other
+        return NotImplemented
+    if sys.version_info[0] <= 2:
+        def __nonzero__(self): return bool(self._componentValues)
+    else:
+        def __bool__(self): return bool(self._componentValues)
+
+    def __len__(self): return self._currentIdx is not None and 1 or 0
+    
+    def verifySizeSpec(self):
+        if self._currentIdx is None:
+            raise error.PyAsn1Error('Component not chosen')
+        else:
+            self._sizeSpec(' ')
+
+    def _cloneComponentValues(self, myClone, cloneValueFlag):
+        try:
+            c = self.getComponent()
+        except error.PyAsn1Error:
+            pass
+        else:
+            if isinstance(c, Choice):
+                tagSet = c.getEffectiveTagSet()
+            else:
+                tagSet = c.getTagSet()
+            if isinstance(c, base.AbstractConstructedAsn1Item):
+                myClone.setComponentByType(
+                    tagSet, c.clone(cloneValueFlag=cloneValueFlag)
+                    )
+            else:
+                myClone.setComponentByType(tagSet, c.clone())
+
+    def setComponentByPosition(self, idx, value=None, verifyConstraints=True):
+        l = len(self._componentValues)
+        if idx >= l:
+            self._componentValues = self._componentValues + (idx-l+1)*[None]
+        if self._currentIdx is not None:
+            self._componentValues[self._currentIdx] = None
+        if value is None:
+            if self._componentValues[idx] is None:
+                self._componentValues[idx] = self._componentType.getTypeByPosition(idx).clone()
+                self._componentValuesSet = 1
+                self._currentIdx = idx
+            return self
+        elif not isinstance(value, base.Asn1Item):
+            value = self._componentType.getTypeByPosition(idx).clone(
+                value=value
+                )
+        if verifyConstraints:
+            if self._componentTypeLen:
+                self._verifyComponent(idx, value)
+            self._verifySubtypeSpec(value, idx)            
+        self._componentValues[idx] = value
+        self._currentIdx = idx
+        self._componentValuesSet = 1
+        return self
+
+    def getMinTagSet(self):
+        if self._tagSet:
+            return self._tagSet
+        else:
+            return self._componentType.genMinTagSet()
+
+    def getEffectiveTagSet(self):
+        if self._tagSet:
+            return self._tagSet
+        else:
+            c = self.getComponent()
+            if isinstance(c, Choice):
+                return c.getEffectiveTagSet()
+            else:
+                return c.getTagSet()
+
+    def getTagMap(self):
+        if self._tagSet:
+            return Set.getTagMap(self)
+        else:
+            return Set.getComponentTagMap(self)
+
+    def getComponent(self, innerFlag=0):
+        if self._currentIdx is None:
+            raise error.PyAsn1Error('Component not chosen')
+        else:
+            c = self._componentValues[self._currentIdx]
+            if innerFlag and isinstance(c, Choice):
+                return c.getComponent(innerFlag)
+            else:
+                return c
+
+    def getName(self, innerFlag=0):
+        if self._currentIdx is None:
+            raise error.PyAsn1Error('Component not chosen')
+        else:
+            if innerFlag:
+                c = self._componentValues[self._currentIdx]
+                if isinstance(c, Choice):
+                    return c.getName(innerFlag)
+            return self._componentType.getNameByPosition(self._currentIdx)
+
+    def setDefaultComponents(self): pass
+
+class Any(OctetString):
+    tagSet = baseTagSet = tag.TagSet()  # untagged
+    typeId = 6
+
+    def getTagMap(self):
+        return tagmap.TagMap(
+            { self.getTagSet(): self },
+            { eoo.endOfOctets.getTagSet(): eoo.endOfOctets },
+            self
+            )
+
+# XXX
+# coercion rules?

+ 17 - 0
desktop/core/ext-py/pyasn1-0.1.8/pyasn1/type/useful.py

@@ -0,0 +1,17 @@
+# ASN.1 "useful" types
+from pyasn1.type import char, tag
+
+class ObjectDescriptor(char.GraphicString):
+    tagSet = char.GraphicString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 7)
+        )
+
+class GeneralizedTime(char.VisibleString):
+    tagSet = char.VisibleString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24)
+        )
+
+class UTCTime(char.VisibleString):
+    tagSet = char.VisibleString.tagSet.tagImplicitly(
+        tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 23)
+        )

+ 5 - 0
desktop/core/ext-py/pyasn1-0.1.8/setup.cfg

@@ -0,0 +1,5 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+tag_svn_revision = 0
+

+ 104 - 0
desktop/core/ext-py/pyasn1-0.1.8/setup.py

@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+"""ASN.1 types and codecs
+
+   A pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208).
+"""
+
+import os
+import sys
+
+classifiers = """\
+Development Status :: 5 - Production/Stable
+Environment :: Console
+Intended Audience :: Developers
+Intended Audience :: Education
+Intended Audience :: Information Technology
+Intended Audience :: Science/Research
+Intended Audience :: System Administrators
+Intended Audience :: Telecommunications Industry
+License :: OSI Approved :: BSD License
+Natural Language :: English
+Operating System :: OS Independent
+Programming Language :: Python :: 2
+Programming Language :: Python :: 3
+Topic :: Communications
+Topic :: Security :: Cryptography
+Topic :: Software Development :: Libraries :: Python Modules
+"""
+
+def howto_install_setuptools():
+    print("""
+   Error: You need setuptools Python package!
+
+   It's very easy to install it, just type (as root on Linux):
+
+   wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
+   python ez_setup.py
+
+   Then you could make eggs from this package.
+""")
+
+if sys.version_info[:2] < (2, 4):
+    print("ERROR: this package requires Python 2.4 or later!")
+    sys.exit(1)
+
+try:
+    from setuptools import setup, Command
+    params = {
+        'zip_safe': True
+    }    
+except ImportError:
+    for arg in sys.argv:
+        if 'egg' in arg:
+            howto_install_setuptools()
+            sys.exit(1)
+    from distutils.core import setup, Command
+    params = {}
+
+doclines = [ x.strip() for x in __doc__.split('\n') if x ]
+
+params.update( {
+    'name': 'pyasn1',
+    'version': open(os.path.join('pyasn1','__init__.py')).read().split('\'')[1],
+    'description': doclines[0],
+    'long_description': ' '.join(doclines[1:]),
+    'maintainer': 'Ilya Etingof <ilya@glas.net>',
+    'author': 'Ilya Etingof',
+    'author_email': 'ilya@glas.net',
+    'url': 'http://sourceforge.net/projects/pyasn1/',
+    'platforms': ['any'],
+    'classifiers': [ x for x in classifiers.split('\n') if x ],
+    'license': 'BSD',
+    'packages': [ 'pyasn1',
+                  'pyasn1.type',
+                  'pyasn1.compat',
+                  'pyasn1.codec',
+                  'pyasn1.codec.ber',
+                  'pyasn1.codec.cer',
+                  'pyasn1.codec.der' ]
+} )
+
+# handle unittest discovery feature
+if sys.version_info[0:2] < (2, 7) or \
+   sys.version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        unittest = None
+else:
+    import unittest
+
+if unittest:
+    class PyTest(Command):
+        user_options = []
+
+        def initialize_options(self): pass
+        def finalize_options(self): pass
+
+        def run(self):
+            suite = unittest.defaultTestLoader.discover('.')
+            unittest.TextTestRunner(verbosity=2).run(suite)
+
+    params['cmdclass'] = { 'test': PyTest }
+
+setup(**params)

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/ber/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 22 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/ber/suite.py

@@ -0,0 +1,22 @@
+from sys import path, version_info
+from os.path import sep
+path.insert(1, path[0]+sep+'ber')
+import test_encoder, test_decoder
+from pyasn1.error import PyAsn1Error
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+suite = unittest.TestSuite()
+loader = unittest.TestLoader()
+for m in (test_encoder, test_decoder):
+    suite.addTest(loader.loadTestsFromModule(m))
+
+def runTests(): unittest.TextTestRunner(verbosity=2).run(suite)
+
+if __name__ == '__main__': runTests()

+ 727 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/ber/test_decoder.py

@@ -0,0 +1,727 @@
+from pyasn1.type import tag, namedtype, univ, char
+from pyasn1.codec.ber import decoder, eoo
+from pyasn1.compat.octets import ints2octs, str2octs, null
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class LargeTagDecoderTestCase(unittest.TestCase):
+    def testLargeTag(self):
+        assert decoder.decode(ints2octs((127, 141, 245, 182, 253, 47, 3, 2, 1, 1))) == (1, null)
+
+class IntegerDecoderTestCase(unittest.TestCase):
+    def testPosInt(self):
+        assert decoder.decode(ints2octs((2, 1, 12))) == (12, null)
+    def testNegInt(self):
+        assert decoder.decode(ints2octs((2, 1, 244))) == (-12, null)
+    def testZero(self):
+        assert decoder.decode(ints2octs((2, 0))) == (0, null)
+    def testZeroLong(self):
+        assert decoder.decode(ints2octs((2, 1, 0))) == (0, null)
+    def testMinusOne(self):
+        assert decoder.decode(ints2octs((2, 1, 255))) == (-1, null)
+    def testPosLong(self):
+        assert decoder.decode(
+            ints2octs((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255))
+            ) == (0xffffffffffffffff, null)
+    def testNegLong(self):
+        assert decoder.decode(
+            ints2octs((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1))
+            ) == (-0xffffffffffffffff, null)
+    def testSpec(self):
+        try:
+            decoder.decode(
+                ints2octs((2, 1, 12)), asn1Spec=univ.Null()
+                ) == (12, null)
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'wrong asn1Spec worked out'
+        assert decoder.decode(
+            ints2octs((2, 1, 12)), asn1Spec=univ.Integer()
+            ) == (12, null)
+    def testTagFormat(self):
+        try:
+            decoder.decode(ints2octs((34, 1, 12)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'wrong tagFormat worked out'
+
+class BooleanDecoderTestCase(unittest.TestCase):
+    def testTrue(self):
+        assert decoder.decode(ints2octs((1, 1, 1))) == (1, null)
+    def testTrueNeg(self):
+        assert decoder.decode(ints2octs((1, 1, 255))) == (1, null)
+    def testExtraTrue(self):
+        assert decoder.decode(ints2octs((1, 1, 1, 0, 120, 50, 50))) == (1, ints2octs((0, 120, 50, 50)))
+    def testFalse(self):
+        assert decoder.decode(ints2octs((1, 1, 0))) == (0, null)
+    def testTagFormat(self):
+        try:
+            decoder.decode(ints2octs((33, 1, 1)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'wrong tagFormat worked out'
+
+class BitStringDecoderTestCase(unittest.TestCase):
+    def testDefMode(self):
+        assert decoder.decode(
+            ints2octs((3, 3, 1, 169, 138))
+            ) == ((1,0,1,0,1,0,0,1,1,0,0,0,1,0,1), null)
+    def testIndefMode(self):
+        assert decoder.decode(
+            ints2octs((3, 3, 1, 169, 138))
+            ) == ((1,0,1,0,1,0,0,1,1,0,0,0,1,0,1), null)
+    def testDefModeChunked(self):
+        assert decoder.decode(
+            ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138))
+            ) == ((1,0,1,0,1,0,0,1,1,0,0,0,1,0,1), null)
+    def testIndefModeChunked(self):
+        assert decoder.decode(
+            ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0))
+            ) == ((1,0,1,0,1,0,0,1,1,0,0,0,1,0,1), null)
+    def testDefModeChunkedSubst(self):
+        assert decoder.decode(
+            ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)),
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138)), 8)
+    def testIndefModeChunkedSubst(self):
+        assert decoder.decode(
+            ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)),
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), -1)
+    def testTypeChecking(self):
+        try:
+            decoder.decode(ints2octs((35, 4, 2, 2, 42, 42)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'accepted mis-encoded bit-string constructed out of an integer'
+
+class OctetStringDecoderTestCase(unittest.TestCase):
+    def testDefMode(self):
+        assert decoder.decode(
+            ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120))
+            ) == (str2octs('Quick brown fox'), null)
+    def testIndefMode(self):
+        assert decoder.decode(
+            ints2octs((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0))
+            ) == (str2octs('Quick brown fox'), null)
+    def testDefModeChunked(self):
+        assert decoder.decode(
+            ints2octs((36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120))
+            ) == (str2octs('Quick brown fox'), null)
+    def testIndefModeChunked(self):
+        assert decoder.decode(
+            ints2octs((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0))
+            ) == (str2octs('Quick brown fox'), null)
+    def testDefModeChunkedSubst(self):
+        assert decoder.decode(
+            ints2octs((36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)),
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), 23)
+    def testIndefModeChunkedSubst(self):
+        assert decoder.decode(
+            ints2octs((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)),
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), -1)
+        
+class ExpTaggedOctetStringDecoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.o = univ.OctetString(
+            'Quick brown fox',
+            tagSet=univ.OctetString.tagSet.tagExplicitly(
+            tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 5)
+            ))
+
+    def testDefMode(self):
+        assert self.o.isSameTypeWith(decoder.decode(
+            ints2octs((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120))
+            )[0])
+
+    def testIndefMode(self):
+        v, s = decoder.decode(ints2octs((101, 128, 36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)))
+        assert self.o.isSameTypeWith(v)
+        assert not s
+
+    def testDefModeChunked(self):
+        v, s = decoder.decode(ints2octs((101, 25, 36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)))
+        assert self.o.isSameTypeWith(v)
+        assert not s
+
+    def testIndefModeChunked(self):
+        v, s = decoder.decode(ints2octs((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0, 0, 0)))
+        assert self.o.isSameTypeWith(v)
+        assert not s
+
+    def testDefModeSubst(self):
+        assert decoder.decode(
+            ints2octs((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)),
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), 17)
+
+    def testIndefModeSubst(self):
+        assert decoder.decode(
+            ints2octs((101, 128, 36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)),
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), -1)
+  
+class NullDecoderTestCase(unittest.TestCase):
+    def testNull(self):
+        assert decoder.decode(ints2octs((5, 0))) == (null, null)
+    def testTagFormat(self):
+        try:
+            decoder.decode(ints2octs((37, 0)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'wrong tagFormat worked out'
+
+# Useful analysis of OID encoding issues could be found here:
+# http://www.viathinksoft.de/~daniel-marschall/asn.1/oid_facts.html
+class ObjectIdentifierDecoderTestCase(unittest.TestCase):
+    def testOne(self):
+        assert decoder.decode(
+            ints2octs((6, 6, 43, 6, 0, 191, 255, 126))
+        ) == ((1,3,6,0,0xffffe), null)
+
+    def testEdge1(self):
+        assert decoder.decode(
+            ints2octs((6, 1, 39))
+        ) == ((0,39), null)
+
+    def testEdge2(self):
+        assert decoder.decode(
+            ints2octs((6, 1, 79))
+        ) == ((1,39), null)
+
+    def testEdge3(self):
+        assert decoder.decode(
+            ints2octs((6, 1, 120))
+        ) == ((2,40), null)
+
+    def testEdge4(self):
+        assert decoder.decode(
+            ints2octs((6,5,0x90,0x80,0x80,0x80,0x4F))
+        ) == ((2,0xffffffff), null)
+
+    def testEdge5(self):
+        assert decoder.decode(
+            ints2octs((6,1,0x7F))
+        ) == ((2,47), null)
+
+    def testEdge6(self):
+        assert decoder.decode(
+            ints2octs((6,2,0x81,0x00))
+        ) == ((2,48), null)
+
+
+    def testEdge7(self):
+        assert decoder.decode(
+            ints2octs((6,3,0x81,0x34,0x03))
+        ) == ((2,100,3), null)
+
+    def testEdge8(self):
+        assert decoder.decode(
+            ints2octs((6,2,133,0))
+        ) == ((2,560), null)
+
+    def testEdge9(self):
+        assert decoder.decode(
+            ints2octs((6,4,0x88,0x84,0x87,0x02))
+        ) == ((2,16843570), null)
+
+    def testNonLeading0x80(self):
+        assert decoder.decode(
+            ints2octs((6, 5, 85, 4, 129, 128, 0)),
+        ) == ((2, 5, 4, 16384), null)
+
+    def testLeading0x80Case1(self):
+        try:
+            decoder.decode(
+                ints2octs((6, 5, 85, 4, 128, 129, 0))
+            )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Leading 0x80 tolarated'
+
+    def testLeading0x80Case2(self):
+        try:
+            decoder.decode(
+                ints2octs((6,7,1,0x80,0x80,0x80,0x80,0x80,0x7F))
+            )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Leading 0x80 tolarated'
+
+    def testLeading0x80Case3(self):
+        try:
+            decoder.decode(
+                ints2octs((6,2,0x80,1))
+            )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Leading 0x80 tolarated'
+
+    def testLeading0x80Case4(self):
+        try:
+            decoder.decode(
+                ints2octs((6,2,0x80,0x7F))
+            )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Leading 0x80 tolarated'
+
+    def testTagFormat(self):
+        try:
+            decoder.decode(ints2octs((38, 1, 239)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'wrong tagFormat worked out'
+
+    def testZeroLength(self):
+        try:
+            decoder.decode(ints2octs((6, 0, 0)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'zero length tolarated'
+
+    def testIndefiniteLength(self):
+        try:
+            decoder.decode(ints2octs((6, 128, 0)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'indefinite length tolarated'
+
+    def testReservedLength(self):
+        try:
+            decoder.decode(ints2octs((6, 255, 0)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'reserved length tolarated'
+
+    def testReservedLength(self):
+        try:
+            decoder.decode(ints2octs((6, 255, 0)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'reserved length tolarated'
+
+    def testLarge1(self):
+        assert decoder.decode(
+            ints2octs((0x06,0x11,0x83,0xC6,0xDF,0xD4,0xCC,0xB3,0xFF,0xFF,0xFE,0xF0,0xB8,0xD6,0xB8,0xCB,0xE2,0xB7,0x17))
+        ) == ((2,18446744073709551535184467440737095), null)
+
+    def testLarge2(self):
+        assert decoder.decode(
+            ints2octs((0x06,0x13,0x88,0x37,0x83,0xC6,0xDF,0xD4,0xCC,0xB3,0xFF,0xFF,0xFE,0xF0,0xB8,0xD6,0xB8,0xCB,0xE2,0xB6,0x47))
+        ) == ((2,999,18446744073709551535184467440737095), null)
+
+class RealDecoderTestCase(unittest.TestCase):
+    def testChar(self):
+        assert decoder.decode(
+            ints2octs((9, 7, 3, 49, 50, 51, 69, 49, 49))
+        ) == (univ.Real((123, 10, 11)), null)
+
+    def testBin1(self): # check base = 2
+        assert decoder.decode( # (0.5, 2, 0) encoded with base = 2
+            ints2octs((9, 3, 128, 255, 1))
+        ) == (univ.Real((1, 2, -1)), null)
+
+    def testBin2(self): # check base = 2 and scale factor
+        assert decoder.decode( # (3.25, 2, 0) encoded with base = 8
+            ints2octs((9, 3, 148, 255, 13))
+        ) == (univ.Real((26, 2, -3)), null)
+
+    def testBin3(self): # check base = 16
+        assert decoder.decode( # (0.00390625, 2, 0) encoded with base = 16
+            ints2octs((9, 3, 160, 254, 1))
+        ) == (univ.Real((1, 2, -8)), null)
+    
+    def testBin4(self): # check exponenta = 0
+        assert decoder.decode( # (1, 2, 0) encoded with base = 2
+            ints2octs((9, 3, 128, 0, 1))
+        ) == (univ.Real((1, 2, 0)), null)
+
+    def testBin5(self): # case of 2 octs for exponenta and negative exponenta
+        assert decoder.decode( # (3, 2, -1020) encoded with base = 16
+            ints2octs((9, 4, 161, 255, 1, 3))
+        ) == (univ.Real((3, 2, -1020)), null)
+
+    def testPlusInf(self):
+        assert decoder.decode(
+            ints2octs((9, 1, 64))
+        ) == (univ.Real('inf'), null)
+ 
+    def testMinusInf(self):
+        assert decoder.decode(
+            ints2octs((9, 1, 65))
+        ) == (univ.Real('-inf'), null)
+
+    def testEmpty(self):
+        assert decoder.decode(
+            ints2octs((9, 0))
+        ) == (univ.Real(0.0), null)
+ 
+    def testTagFormat(self):
+        try:
+            decoder.decode(ints2octs((41, 0)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'wrong tagFormat worked out'
+
+    def testShortEncoding(self):
+        try:
+            decoder.decode(ints2octs((9, 1, 131)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'accepted too-short real'
+
+if version_info[0:2] > (2, 5):
+    class UniversalStringDecoderTestCase(unittest.TestCase):
+        def testDecoder(self):
+             assert decoder.decode(ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99))) == (char.UniversalString(version_info[0] == 3 and 'abc' or unicode('abc')), null)
+
+class BMPStringDecoderTestCase(unittest.TestCase):
+    def testDecoder(self):
+        assert decoder.decode(ints2octs((30, 6, 0, 97, 0, 98, 0, 99))) == (char.BMPString(version_info[0] == 3 and 'abc' or unicode('abc')), null)
+
+class UTF8StringDecoderTestCase(unittest.TestCase):
+    def testDecoder(self):
+        assert decoder.decode(ints2octs((12, 3, 97, 98, 99))) == (char.UTF8String(version_info[0] == 3 and 'abc' or unicode('abc')), null)
+
+class SequenceDecoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.s = univ.Sequence(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('place-holder', univ.Null(null)),
+            namedtype.NamedType('first-name', univ.OctetString(null)),
+            namedtype.NamedType('age', univ.Integer(33)),
+            ))
+        self.s.setComponentByPosition(0, univ.Null(null))
+        self.s.setComponentByPosition(1, univ.OctetString('quick brown'))
+        self.s.setComponentByPosition(2, univ.Integer(1))
+        self.s.setDefaultComponents()
+        
+    def testWithOptionalAndDefaultedDefMode(self):
+        assert decoder.decode(
+            ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1))
+            ) == (self.s, null)
+        
+    def testWithOptionalAndDefaultedIndefMode(self):
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0))
+            ) == (self.s, null)
+
+    def testWithOptionalAndDefaultedDefModeChunked(self):
+        assert decoder.decode(
+            ints2octs((48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1))
+            ) == (self.s, null)
+
+    def testWithOptionalAndDefaultedIndefModeChunked(self):
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0))
+            ) == (self.s, null)
+
+    def testWithOptionalAndDefaultedDefModeSubst(self):
+        assert decoder.decode(
+            ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)),
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), 18)
+        
+    def testWithOptionalAndDefaultedIndefModeSubst(self):
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)),
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), -1)
+
+    def testTagFormat(self):
+        try:
+            decoder.decode(
+                ints2octs((16, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1))
+            )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'wrong tagFormat worked out'
+
+class GuidedSequenceDecoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.s = univ.Sequence(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('place-holder', univ.Null(null)),
+            namedtype.OptionalNamedType('first-name', univ.OctetString(null)),
+            namedtype.DefaultedNamedType('age', univ.Integer(33)),
+            ))
+
+    def __init(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0, univ.Null(null))
+        self.s.setDefaultComponents()
+        
+    def __initWithOptional(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0, univ.Null(null))
+        self.s.setComponentByPosition(1, univ.OctetString('quick brown'))
+        self.s.setDefaultComponents()
+
+    def __initWithDefaulted(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0, univ.Null(null))
+        self.s.setComponentByPosition(2, univ.Integer(1))
+        self.s.setDefaultComponents()
+        
+    def __initWithOptionalAndDefaulted(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0, univ.Null(null))
+        self.s.setComponentByPosition(1, univ.OctetString('quick brown'))
+        self.s.setComponentByPosition(2, univ.Integer(1))
+        self.s.setDefaultComponents()
+        
+    def testDefMode(self):
+        self.__init()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 0, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+        
+    def testIndefMode(self):
+        self.__init()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 0, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testDefModeChunked(self):
+        self.__init()
+        assert decoder.decode(
+            ints2octs((48, 2, 5, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testIndefModeChunked(self):
+        self.__init()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 0, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithOptionalDefMode(self):
+        self.__initWithOptional()
+        assert decoder.decode(
+            ints2octs((48, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s
+            ) == (self.s, null)
+        
+    def testWithOptionaIndefMode(self):
+        self.__initWithOptional()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)),
+            asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithOptionalDefModeChunked(self):
+        self.__initWithOptional()
+        assert decoder.decode(
+            ints2octs((48, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)),
+            asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithOptionalIndefModeChunked(self):
+        self.__initWithOptional()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)),
+            asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithDefaultedDefMode(self):
+        self.__initWithDefaulted()
+        assert decoder.decode(
+            ints2octs((48, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s
+            ) == (self.s, null)
+        
+    def testWithDefaultedIndefMode(self):
+        self.__initWithDefaulted()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithDefaultedDefModeChunked(self):
+        self.__initWithDefaulted()
+        assert decoder.decode(
+            ints2octs((48, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithDefaultedIndefModeChunked(self):
+        self.__initWithDefaulted()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithOptionalAndDefaultedDefMode(self):
+        self.__initWithOptionalAndDefaulted()
+        assert decoder.decode(
+            ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), asn1Spec=self.s
+            ) == (self.s, null)
+        
+    def testWithOptionalAndDefaultedIndefMode(self):
+        self.__initWithOptionalAndDefaulted()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithOptionalAndDefaultedDefModeChunked(self):
+        self.__initWithOptionalAndDefaulted()
+        assert decoder.decode(
+            ints2octs((48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithOptionalAndDefaultedIndefModeChunked(self):
+        self.__initWithOptionalAndDefaulted()
+        assert decoder.decode(
+            ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+
+class ChoiceDecoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.s = univ.Choice(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('place-holder', univ.Null(null)),
+            namedtype.NamedType('number', univ.Integer(0)),
+            namedtype.NamedType('string', univ.OctetString())
+            ))
+
+    def testBySpec(self):
+        self.s.setComponentByPosition(0, univ.Null(null))
+        assert decoder.decode(
+            ints2octs((5, 0)), asn1Spec=self.s
+            ) == (self.s, null)
+
+    def testWithoutSpec(self):
+        self.s.setComponentByPosition(0, univ.Null(null))
+        assert decoder.decode(ints2octs((5, 0))) == (self.s, null)
+        assert decoder.decode(ints2octs((5, 0))) == (univ.Null(null), null)
+
+    def testUndefLength(self):
+        self.s.setComponentByPosition(2, univ.OctetString('abcdefgh'))
+        assert decoder.decode(ints2octs((36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0)), asn1Spec=self.s) == (self.s, null)
+
+    def testExplicitTag(self):
+        s = self.s.subtype(explicitTag=tag.Tag(tag.tagClassContext,
+                           tag.tagFormatConstructed, 4))
+        s.setComponentByPosition(0, univ.Null(null))
+        assert decoder.decode(ints2octs((164, 2, 5, 0)), asn1Spec=s) == (s, null)
+
+    def testExplicitTagUndefLength(self):
+        s = self.s.subtype(explicitTag=tag.Tag(tag.tagClassContext,
+                           tag.tagFormatConstructed, 4))
+        s.setComponentByPosition(0, univ.Null(null))
+        assert decoder.decode(ints2octs((164, 128, 5, 0, 0, 0)), asn1Spec=s) == (s, null)
+
+class AnyDecoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.s = univ.Any()
+
+    def testByUntagged(self):
+        assert decoder.decode(
+            ints2octs((4, 3, 102, 111, 120)), asn1Spec=self.s
+            ) == (univ.Any('\004\003fox'), null)
+
+    def testTaggedEx(self):
+        s = univ.Any('\004\003fox').subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))
+        assert decoder.decode(ints2octs((164, 5, 4, 3, 102, 111, 120)), asn1Spec=s) == (s, null)
+                
+    def testTaggedIm(self):
+        s = univ.Any('\004\003fox').subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))
+        assert decoder.decode(ints2octs((132, 5, 4, 3, 102, 111, 120)), asn1Spec=s) == (s, null)
+
+    def testByUntaggedIndefMode(self):
+        assert decoder.decode(
+            ints2octs((4, 3, 102, 111, 120)), asn1Spec=self.s
+            ) == (univ.Any('\004\003fox'), null)
+
+    def testTaggedExIndefMode(self):
+        s = univ.Any('\004\003fox').subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))
+        assert decoder.decode(ints2octs((164, 128, 4, 3, 102, 111, 120, 0, 0)), asn1Spec=s) == (s, null)
+                
+    def testTaggedImIndefMode(self):
+        s = univ.Any('\004\003fox').subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))
+        assert decoder.decode(ints2octs((164, 128, 4, 3, 102, 111, 120, 0, 0)), asn1Spec=s) == (s, null)
+
+    def testByUntaggedSubst(self):
+        assert decoder.decode(
+            ints2octs((4, 3, 102, 111, 120)),
+            asn1Spec=self.s,
+            substrateFun=lambda a,b,c: (b,c)
+            ) == (ints2octs((4, 3, 102, 111, 120)), 5)
+
+    def testTaggedExSubst(self):
+        assert decoder.decode(
+            ints2octs((164, 5, 4, 3, 102, 111, 120)),
+            asn1Spec=self.s,
+            substrateFun=lambda a,b,c: (b,c)
+        ) == (ints2octs((164, 5, 4, 3, 102, 111, 120)), 7)
+
+class EndOfOctetsTestCase(unittest.TestCase):
+    def testUnexpectedEoo(self):
+        try:
+            decoder.decode(ints2octs((0, 0)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'end-of-contents octets accepted at top level'
+
+    def testExpectedEoo(self):
+        result, remainder = decoder.decode(ints2octs((0, 0)), allowEoo=True)
+        assert eoo.endOfOctets.isSameTypeWith(result) and result == eoo.endOfOctets
+        assert remainder == null
+
+    def testDefiniteNoEoo(self):
+        try:
+            decoder.decode(ints2octs((0x23, 0x02, 0x00, 0x00)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'end-of-contents octets accepted inside definite-length encoding'
+
+    def testIndefiniteEoo(self):
+        result, remainder = decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x00)))
+        assert result == () and remainder == null, 'incorrect decoding of indefinite length end-of-octets'
+
+    def testNoLongFormEoo(self):
+        try:
+            decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x81, 0x00)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'end-of-contents octets accepted with invalid long-form length'
+
+    def testNoConstructedEoo(self):
+        try:
+            decoder.decode(ints2octs((0x23, 0x80, 0x20, 0x00)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'end-of-contents octets accepted with invalid constructed encoding'
+
+    def testNoEooData(self):
+        try:
+            decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x01, 0x00)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'end-of-contents octets accepted with unexpected data'
+
+if __name__ == '__main__': unittest.main()

+ 483 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/ber/test_encoder.py

@@ -0,0 +1,483 @@
+from pyasn1.type import tag, namedtype, univ, char
+from pyasn1.codec.ber import encoder
+from pyasn1.compat.octets import ints2octs
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class LargeTagEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.o = univ.Integer().subtype(
+            value=1, explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0xdeadbeaf)
+            )
+    def testEncoder(self):
+        assert encoder.encode(self.o) == ints2octs((127, 141, 245, 182, 253, 47, 3, 2, 1, 1))
+        
+class IntegerEncoderTestCase(unittest.TestCase):
+    def testPosInt(self):
+        assert encoder.encode(univ.Integer(12)) == ints2octs((2, 1, 12))
+        
+    def testNegInt(self):
+        assert encoder.encode(univ.Integer(-12)) == ints2octs((2, 1, 244))
+        
+    def testZero(self):
+        assert encoder.encode(univ.Integer(0)) == ints2octs((2, 1, 0))
+
+    def testCompactZero(self):
+        encoder.IntegerEncoder.supportCompactZero = True
+        substrate = encoder.encode(univ.Integer(0))
+        encoder.IntegerEncoder.supportCompactZero = False
+        assert substrate == ints2octs((2, 0))
+        
+    def testMinusOne(self):
+        assert encoder.encode(univ.Integer(-1)) == ints2octs((2, 1, 255))
+        
+    def testPosLong(self):
+        assert encoder.encode(
+            univ.Integer(0xffffffffffffffff)
+            ) == ints2octs((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255))
+        
+    def testNegLong(self):
+        assert encoder.encode(
+            univ.Integer(-0xffffffffffffffff)
+            ) == ints2octs((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1))
+
+class BooleanEncoderTestCase(unittest.TestCase):
+    def testTrue(self):
+        assert encoder.encode(univ.Boolean(1)) == ints2octs((1, 1, 1))
+        
+    def testFalse(self):
+        assert encoder.encode(univ.Boolean(0)) == ints2octs((1, 1, 0))
+
+class BitStringEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.b = univ.BitString((1,0,1,0,1,0,0,1,1,0,0,0,1,0,1))
+        
+    def testDefMode(self):
+        assert encoder.encode(self.b) == ints2octs((3, 3, 1, 169, 138))
+        
+    def testIndefMode(self):
+        assert encoder.encode(
+            self.b, defMode=0
+            ) == ints2octs((3, 3, 1, 169, 138))
+        
+    def testDefModeChunked(self):
+        assert encoder.encode(
+            self.b, maxChunkSize=1
+            ) == ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138))
+        
+    def testIndefModeChunked(self):
+        assert encoder.encode(
+            self.b, defMode=0, maxChunkSize=1
+            ) == ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0))
+        
+    def testEmptyValue(self):
+        assert encoder.encode(univ.BitString(())) == ints2octs((3, 1, 0))
+        
+class OctetStringEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.o = univ.OctetString('Quick brown fox')
+        
+    def testDefMode(self):
+        assert encoder.encode(self.o) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120))
+        
+    def testIndefMode(self):
+        assert encoder.encode(
+            self.o, defMode=0
+            ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120))
+
+    def testDefModeChunked(self):
+        assert encoder.encode(
+            self.o, maxChunkSize=4
+            ) == ints2octs((36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120))
+
+    def testIndefModeChunked(self):
+        assert encoder.encode(
+            self.o, defMode=0, maxChunkSize=4
+            ) == ints2octs((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0))
+        
+class ExpTaggedOctetStringEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.o = univ.OctetString().subtype(
+            value='Quick brown fox',
+            explicitTag=tag.Tag(tag.tagClassApplication,tag.tagFormatSimple,5)
+            )
+    def testDefMode(self):
+        assert encoder.encode(self.o) == ints2octs((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120))
+
+    def testIndefMode(self):
+        assert encoder.encode(
+            self.o, defMode=0
+            ) == ints2octs((101, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0))
+        
+    def testDefModeChunked(self):
+        assert encoder.encode(
+            self.o, defMode=1, maxChunkSize=4
+            ) == ints2octs((101, 25, 36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120))
+        
+    def testIndefModeChunked(self):
+        assert encoder.encode(
+            self.o, defMode=0, maxChunkSize=4
+            ) == ints2octs((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0, 0, 0))
+
+class NullEncoderTestCase(unittest.TestCase):
+    def testNull(self):
+        assert encoder.encode(univ.Null('')) == ints2octs((5, 0))
+
+class ObjectIdentifierEncoderTestCase(unittest.TestCase):
+    def testOne(self):
+        assert encoder.encode(
+            univ.ObjectIdentifier((1,3,6,0,0xffffe))
+        ) == ints2octs((6, 6, 43, 6, 0, 191, 255, 126))
+
+    def testEdge1(self):
+        assert encoder.encode(
+            univ.ObjectIdentifier((0,39))
+        ) == ints2octs((6,1,39))
+
+    def testEdge2(self):
+        assert encoder.encode(
+            univ.ObjectIdentifier((1,39))
+        ) == ints2octs((6,1,79))
+
+    def testEdge3(self):
+        #01111111
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,40))
+        ) == ints2octs((6,1,120))
+
+    def testEdge4(self):
+        #10010000|10000000|10000000|10000000|01001111
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,0xffffffff))
+        ) == ints2octs((6,5,0x90,0x80,0x80,0x80,0x4F))
+
+    def testEdge5(self):
+        #01111111
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,47))
+        ) == ints2octs((6,1,0x7F))
+
+    def testEdge6(self):
+        #10000001|00000000
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,48))
+        ) == ints2octs((6,2,0x81,0x00))
+
+    def testEdge7(self):
+        #10000001|00110100|00000003
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,100,3))
+        ) == ints2octs((6,3,0x81,0x34,0x03))
+
+    def testEdge8(self):
+        #10000101|00000000
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,560))
+        ) == ints2octs((6,2,133,0))
+
+    def testEdge9(self):
+        #10001000|10000100|10000111|0000010
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,16843570))
+        ) == ints2octs((6,4,0x88,0x84,0x87,0x02))
+
+    def testImpossible1(self):
+        try:
+            encoder.encode(univ.ObjectIdentifier((3,1,2)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'impossible leading arc tolerated'
+
+    def testImpossible2(self):
+        try:
+            encoder.encode(univ.ObjectIdentifier((0,)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'single arc OID tolerated'
+
+    def testImpossible3(self):
+        try:
+            encoder.encode(univ.ObjectIdentifier((0,40)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'second arc overflow tolerated'
+
+    def testImpossible4(self):
+        try:
+            encoder.encode(univ.ObjectIdentifier((1,40)))
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'second arc overflow tolerated'
+
+    def testLarge1(self):
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,18446744073709551535184467440737095))
+        ) == ints2octs((0x06,0x11,0x83,0xC6,0xDF,0xD4,0xCC,0xB3,0xFF,0xFF,0xFE,0xF0,0xB8,0xD6,0xB8,0xCB,0xE2,0xB7,0x17))
+
+    def testLarge2(self):
+        assert encoder.encode(
+            univ.ObjectIdentifier((2,999,18446744073709551535184467440737095))
+        ) == ints2octs((0x06,0x13,0x88,0x37,0x83,0xC6,0xDF,0xD4,0xCC,0xB3,0xFF,0xFF,0xFE,0xF0,0xB8,0xD6,0xB8,0xCB,0xE2,0xB6,0x47))
+            
+
+class RealEncoderTestCase(unittest.TestCase):
+    def testChar(self):
+        assert encoder.encode(
+            univ.Real((123, 10, 11))
+            ) == ints2octs((9, 7, 3, 49, 50, 51, 69, 49, 49))
+
+    def testBin1(self):
+        assert encoder.encode( # default binEncBase = 2
+            univ.Real((0.5, 2, 0)) # check encbase = 2 and exponenta = -1
+            ) == ints2octs((9, 3, 128, 255, 1))
+
+    def testBin2(self):
+        r = univ.Real((3.25, 2, 0)) 
+        r.binEncBase = 8 # change binEncBase only for this instance of Real
+        assert encoder.encode(
+            r # check encbase = 8
+            ) == ints2octs((9, 3, 148, 255, 13))
+
+    def testBin3(self):
+        # change binEncBase in the RealEncoder instance => for all further Reals
+        encoder.tagMap[univ.Real.tagSet].binEncBase = 16
+        assert encoder.encode(
+            univ.Real((0.00390625, 2, 0)) # check encbase = 16
+            ) == ints2octs((9, 3, 160, 254, 1))
+
+    def testBin4(self):
+        # choose binEncBase automatically for all further Reals (testBin[4-7])
+        encoder.tagMap[univ.Real.tagSet].binEncBase = None 
+        assert encoder.encode(
+            univ.Real((1, 2, 0)) # check exponenta = 0
+            ) == ints2octs((9, 3, 128, 0, 1))
+
+    def testBin5(self):
+        assert encoder.encode(
+            univ.Real((3, 2, -1020)) # case of 2 octs for exponenta and
+                                     # negative exponenta and abs(exponenta) is
+                                     # all 1's and fills the whole octet(s) 
+            ) == ints2octs((9, 4, 161, 255, 1, 3))
+
+    def testBin6(self):
+        assert encoder.encode(
+            univ.Real((1, 2, 262140)) # case of 3 octs for exponenta and
+                                      # check that first 9 bits for exponenta
+                                      # are not all 1's
+            ) == ints2octs((9, 5, 162, 0, 255, 255, 1))
+
+    def testBin7(self):
+        assert encoder.encode(
+            univ.Real((-1, 2, 76354972)) # case of >3 octs for exponenta and
+                                         # mantissa < 0
+            ) == ints2octs((9, 7, 227, 4, 1, 35, 69, 103, 1))
+
+
+    def testPlusInf(self):
+        assert encoder.encode(univ.Real('inf')) == ints2octs((9, 1, 64))
+
+    def testMinusInf(self):
+        assert encoder.encode(univ.Real('-inf')) == ints2octs((9, 1, 65))
+        
+    def testZero(self):
+        assert encoder.encode(univ.Real(0)) == ints2octs((9, 0))
+
+if version_info[0:2] > (2, 5):
+    class UniversalStringEncoderTestCase(unittest.TestCase):
+        def testEncoding(self):
+            assert encoder.encode(char.UniversalString(version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99)), 'Incorrect encoding'
+        
+class BMPStringEncoderTestCase(unittest.TestCase):
+    def testEncoding(self):
+        assert encoder.encode(char.BMPString(version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs((30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding'
+
+class UTF8StringEncoderTestCase(unittest.TestCase):
+    def testEncoding(self):
+        assert encoder.encode(char.UTF8String(version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs((12, 3, 97, 98, 99)), 'Incorrect encoding'
+
+class SequenceEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.s = univ.Sequence(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('place-holder', univ.Null('')),
+            namedtype.OptionalNamedType('first-name', univ.OctetString('')),
+            namedtype.DefaultedNamedType('age', univ.Integer(33)),
+            ))
+
+    def __init(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0)
+        
+    def __initWithOptional(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0)
+        self.s.setComponentByPosition(1, 'quick brown')
+        
+    def __initWithDefaulted(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0)
+        self.s.setComponentByPosition(2, 1)
+        
+    def __initWithOptionalAndDefaulted(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0, univ.Null(''))
+        self.s.setComponentByPosition(1, univ.OctetString('quick brown'))
+        self.s.setComponentByPosition(2, univ.Integer(1))
+        
+    def testDefMode(self):
+        self.__init()
+        assert encoder.encode(self.s) == ints2octs((48, 2, 5, 0))
+        
+    def testIndefMode(self):
+        self.__init()
+        assert encoder.encode(
+            self.s, defMode=0
+            ) == ints2octs((48, 128, 5, 0, 0, 0))
+
+    def testDefModeChunked(self):
+        self.__init()
+        assert encoder.encode(
+            self.s, defMode=1, maxChunkSize=4
+            ) == ints2octs((48, 2, 5, 0))
+
+    def testIndefModeChunked(self):
+        self.__init()
+        assert encoder.encode(
+            self.s, defMode=0, maxChunkSize=4
+            ) == ints2octs((48, 128, 5, 0, 0, 0))
+
+    def testWithOptionalDefMode(self):
+        self.__initWithOptional()
+        assert encoder.encode(self.s) == ints2octs((48, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110))
+        
+    def testWithOptionalIndefMode(self):
+        self.__initWithOptional()
+        assert encoder.encode(
+            self.s, defMode=0
+            ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0))
+
+    def testWithOptionalDefModeChunked(self):
+        self.__initWithOptional()
+        assert encoder.encode(
+            self.s, defMode=1, maxChunkSize=4
+            ) == ints2octs((48, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110))
+
+    def testWithOptionalIndefModeChunked(self):
+        self.__initWithOptional()
+        assert encoder.encode(
+            self.s, defMode=0, maxChunkSize=4
+            ) == ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0))
+
+    def testWithDefaultedDefMode(self):
+        self.__initWithDefaulted()
+        assert encoder.encode(self.s) == ints2octs((48, 5, 5, 0, 2, 1, 1))
+        
+    def testWithDefaultedIndefMode(self):
+        self.__initWithDefaulted()
+        assert encoder.encode(
+            self.s, defMode=0
+            ) == ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0))
+
+    def testWithDefaultedDefModeChunked(self):
+        self.__initWithDefaulted()
+        assert encoder.encode(
+            self.s, defMode=1, maxChunkSize=4
+            ) == ints2octs((48, 5, 5, 0, 2, 1, 1))
+
+    def testWithDefaultedIndefModeChunked(self):
+        self.__initWithDefaulted()
+        assert encoder.encode(
+            self.s, defMode=0, maxChunkSize=4
+            ) == ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0))
+
+    def testWithOptionalAndDefaultedDefMode(self):
+        self.__initWithOptionalAndDefaulted()
+        assert encoder.encode(self.s) == ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1))
+        
+    def testWithOptionalAndDefaultedIndefMode(self):
+        self.__initWithOptionalAndDefaulted()
+        assert encoder.encode(
+            self.s, defMode=0
+            ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0))
+
+    def testWithOptionalAndDefaultedDefModeChunked(self):
+        self.__initWithOptionalAndDefaulted()
+        assert encoder.encode(
+            self.s, defMode=1, maxChunkSize=4
+            ) == ints2octs((48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1))
+
+    def testWithOptionalAndDefaultedIndefModeChunked(self):
+        self.__initWithOptionalAndDefaulted()
+        assert encoder.encode(
+            self.s, defMode=0, maxChunkSize=4
+            ) == ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0))
+
+class ChoiceEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.s = univ.Choice(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('place-holder', univ.Null('')),
+            namedtype.NamedType('number', univ.Integer(0)),
+            namedtype.NamedType('string', univ.OctetString())
+            ))
+
+    def testEmpty(self):
+        try:
+            encoder.encode(self.s)
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'encoded unset choice'
+        
+    def testFilled(self):
+        self.s.setComponentByPosition(0, univ.Null(''))
+        assert encoder.encode(self.s) == ints2octs((5, 0))
+
+    def testTagged(self):
+        s = self.s.subtype(
+            explicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatConstructed,4)
+        )
+        s.setComponentByPosition(0, univ.Null(''))
+        assert encoder.encode(s) == ints2octs((164, 2, 5, 0))
+
+    def testUndefLength(self):
+        self.s.setComponentByPosition(2, univ.OctetString('abcdefgh'))
+        assert encoder.encode(self.s, defMode=False, maxChunkSize=3) == ints2octs((36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0))
+
+    def testTaggedUndefLength(self):
+        s = self.s.subtype(
+            explicitTag=tag.Tag(tag.tagClassContext,tag.tagFormatConstructed,4)
+        )
+        s.setComponentByPosition(2, univ.OctetString('abcdefgh'))
+        assert encoder.encode(s, defMode=False, maxChunkSize=3) == ints2octs((164, 128, 36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0, 0, 0))
+
+class AnyEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.s = univ.Any(encoder.encode(univ.OctetString('fox')))
+        
+    def testUntagged(self):
+        assert encoder.encode(self.s) == ints2octs((4, 3, 102, 111, 120))
+            
+    def testTaggedEx(self):
+        s = self.s.subtype(
+            explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)
+            )
+        assert encoder.encode(s) == ints2octs((164, 5, 4, 3, 102, 111, 120))
+
+    def testTaggedIm(self):
+        s = self.s.subtype(
+            implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)
+            )
+        assert encoder.encode(s) == ints2octs((132, 5, 4, 3, 102, 111, 120))
+                    
+if __name__ == '__main__': unittest.main()

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/cer/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 22 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/cer/suite.py

@@ -0,0 +1,22 @@
+from sys import path, version_info
+from os.path import sep
+path.insert(1, path[0]+sep+'cer')
+import test_encoder, test_decoder
+from pyasn1.error import PyAsn1Error
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+suite = unittest.TestSuite()
+loader = unittest.TestLoader()
+for m in (test_encoder, test_decoder):
+    suite.addTest(loader.loadTestsFromModule(m))
+
+def runTests(): unittest.TextTestRunner(verbosity=2).run(suite)
+
+if __name__ == '__main__': runTests()

+ 31 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/cer/test_decoder.py

@@ -0,0 +1,31 @@
+from pyasn1.type import univ
+from pyasn1.codec.cer import decoder
+from pyasn1.compat.octets import ints2octs, str2octs, null
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class BooleanDecoderTestCase(unittest.TestCase):
+    def testTrue(self):
+        assert decoder.decode(ints2octs((1, 1, 255))) == (1, null)
+    def testFalse(self):
+        assert decoder.decode(ints2octs((1, 1, 0))) == (0, null)
+        
+class OctetStringDecoderTestCase(unittest.TestCase):
+    def testShortMode(self):
+        assert decoder.decode(
+            ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)),
+            ) == (str2octs('Quick brown fox'), null)
+    def testLongMode(self):
+        assert decoder.decode(
+            ints2octs((36, 128, 4, 130, 3, 232) + (81,)*1000 + (4, 1, 81, 0, 0))
+            ) == (str2octs('Q'*1001), null)
+
+if __name__ == '__main__': unittest.main()

+ 176 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/cer/test_encoder.py

@@ -0,0 +1,176 @@
+from pyasn1.type import namedtype, univ, useful
+from pyasn1.codec.cer import encoder
+from pyasn1.compat.octets import ints2octs
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class BooleanEncoderTestCase(unittest.TestCase):
+    def testTrue(self):
+        assert encoder.encode(univ.Boolean(1)) == ints2octs((1, 1, 255))
+    def testFalse(self):
+        assert encoder.encode(univ.Boolean(0)) == ints2octs((1, 1, 0))
+
+class BitStringEncoderTestCase(unittest.TestCase):
+    def testShortMode(self):
+        assert encoder.encode(
+            univ.BitString((1,0)*501)
+            ) == ints2octs((3, 127, 6) + (170,) * 125 + (128,))
+
+    def testLongMode(self):
+        assert encoder.encode(
+            univ.BitString((1,0)*501)
+            ) == ints2octs((3, 127, 6) + (170,) * 125 + (128,))
+        
+class OctetStringEncoderTestCase(unittest.TestCase):
+    def testShortMode(self):
+        assert encoder.encode(
+            univ.OctetString('Quick brown fox')
+            ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120))
+    def testLongMode(self):
+        assert encoder.encode(
+            univ.OctetString('Q'*1001)
+            ) == ints2octs((36, 128, 4, 130, 3, 232) + (81,)*1000 + (4, 1, 81, 0, 0))
+        
+class SetEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        self.s = univ.Set(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('place-holder', univ.Null('')),
+            namedtype.OptionalNamedType('first-name', univ.OctetString('')),
+            namedtype.DefaultedNamedType('age', univ.Integer(33))
+            ))
+
+    def __init(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0)
+    def __initWithOptional(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0)
+        self.s.setComponentByPosition(1, 'quick brown')
+        
+    def __initWithDefaulted(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0)
+        self.s.setComponentByPosition(2, 1)
+        
+    def __initWithOptionalAndDefaulted(self):
+        self.s.clear()
+        self.s.setComponentByPosition(0, univ.Null(''))
+        self.s.setComponentByPosition(1, univ.OctetString('quick brown'))
+        self.s.setComponentByPosition(2, univ.Integer(1))
+        
+    def testIndefMode(self):
+        self.__init()
+        assert encoder.encode(self.s) == ints2octs((49, 128, 5, 0, 0, 0))
+
+    def testWithOptionalIndefMode(self):
+        self.__initWithOptional()
+        assert encoder.encode(
+            self.s
+            ) == ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0))
+
+    def testWithDefaultedIndefMode(self):
+        self.__initWithDefaulted()
+        assert encoder.encode(
+            self.s
+            ) == ints2octs((49, 128, 2, 1, 1, 5, 0, 0, 0))
+
+    def testWithOptionalAndDefaultedIndefMode(self):
+        self.__initWithOptionalAndDefaulted()
+        assert encoder.encode(
+            self.s
+            ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0))
+
+class SetWithChoiceEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        c = univ.Choice(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('actual', univ.Boolean(0))
+            ))
+        self.s = univ.Set(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('place-holder', univ.Null('')),
+            namedtype.NamedType('status', c)
+            ))
+
+    def testIndefMode(self):
+        self.s.setComponentByPosition(0)
+        self.s.setComponentByName('status')
+        self.s.getComponentByName('status').setComponentByPosition(0, 1)
+        assert encoder.encode(self.s) == ints2octs((49, 128, 1, 1, 255, 5, 0, 0, 0))
+
+class GeneralizedTimeEncoderTestCase(unittest.TestCase):
+#    def testExtraZeroInSeconds(self):
+#        try:
+#            assert encoder.encode(
+#                useful.GeneralizedTime('20150501120112.10Z')
+#            )
+#        except PyAsn1Error:
+#            pass
+#        else:
+#            assert 0, 'Meaningless trailing zero in fraction part tolerated'
+ 
+    def testLocalTimezone(self):
+        try:
+            assert encoder.encode(
+                useful.GeneralizedTime('20150501120112.1+0200')
+            )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Local timezone tolerated'
+
+    def testMissingTimezone(self):
+        try:
+            assert encoder.encode(
+                    useful.GeneralizedTime('20150501120112.1')
+             )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Missing timezone tolerated'
+
+# When enabled, this breaks many existing encodings
+#
+#    def testDecimalPoint(self):
+#        try:
+#            assert encoder.encode(
+#                    useful.GeneralizedTime('20150501120112Z')
+#             )
+#        except PyAsn1Error:
+#            pass
+#        else:
+#            assert 0, 'Missing decimal point tolerated'
+
+class UTCTimeEncoderTestCase(unittest.TestCase):
+    def testFractionOfSecond(self):
+        try:
+            assert encoder.encode(
+                    useful.UTCTime('150501120112.10Z')
+             )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Decimal point tolerated'
+
+    def testMissingTimezone(self):
+        assert encoder.encode(
+            useful.UTCTime('150501120112')
+        ) == ints2octs((23, 13, 49, 53, 48, 53, 48, 49, 49, 50, 48, 49, 49, 50, 90)), 'Missing timezone not added'
+
+    def testLocalTimezone(self):
+        try:
+            assert encoder.encode(
+                useful.UTCTime('150501120112+0200')
+            )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Local timezone tolerated'
+
+if __name__ == '__main__': unittest.main()

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/der/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 22 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/der/suite.py

@@ -0,0 +1,22 @@
+from sys import path, version_info
+from os.path import sep
+path.insert(1, path[0]+sep+'der')
+import test_encoder, test_decoder
+from pyasn1.error import PyAsn1Error
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+suite = unittest.TestSuite()
+loader = unittest.TestLoader()
+for m in (test_encoder, test_decoder):
+    suite.addTest(loader.loadTestsFromModule(m))
+
+def runTests(): unittest.TextTestRunner(verbosity=2).run(suite)
+
+if __name__ == '__main__': runTests()

+ 31 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/der/test_decoder.py

@@ -0,0 +1,31 @@
+from pyasn1.type import univ
+from pyasn1.codec.der import decoder
+from pyasn1.compat.octets import ints2octs
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class OctetStringDecoderTestCase(unittest.TestCase):
+    def testShortMode(self):
+        assert decoder.decode(
+            '\004\017Quick brown fox'.encode()
+            ) == ('Quick brown fox'.encode(), ''.encode())
+
+    def testIndefMode(self):
+        try:
+            decoder.decode(
+                ints2octs((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0))
+            )
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'indefinite length encoding tolerated'
+
+if __name__ == '__main__': unittest.main()

+ 51 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/der/test_encoder.py

@@ -0,0 +1,51 @@
+from pyasn1.type import namedtype, univ
+from pyasn1.codec.der import encoder
+from pyasn1.compat.octets import ints2octs
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class OctetStringEncoderTestCase(unittest.TestCase):
+    def testShortMode(self):
+        assert encoder.encode(
+            univ.OctetString('Quick brown fox')
+            ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120))
+    def testIndefMode(self):
+        try:
+            assert encoder.encode(univ.OctetString('Quick brown'), defMode=0)
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Indefinite length encoding tolerated'
+
+class BitStringEncoderTestCase(unittest.TestCase):
+    def testShortMode(self):
+        assert encoder.encode(
+            univ.BitString((1,))
+            ) == ints2octs((3, 2, 7, 128))
+        
+class SetWithChoiceEncoderTestCase(unittest.TestCase):
+    def setUp(self):
+        c = univ.Choice(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('name', univ.OctetString('')),
+            namedtype.NamedType('amount', univ.Integer(0))
+            ))
+        self.s = univ.Set(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('place-holder', univ.Null('')),
+            namedtype.NamedType('status', c)
+            ))
+
+    def testDefMode(self):
+        self.s.setComponentByPosition(0)
+        self.s.setComponentByName('status')
+        self.s.getComponentByName('status').setComponentByPosition(0, 'ann')
+        assert encoder.encode(self.s) == ints2octs((49, 7, 4, 3, 97, 110, 110, 5, 0))
+
+if __name__ == '__main__': unittest.main()

+ 29 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/codec/suite.py

@@ -0,0 +1,29 @@
+from sys import path, version_info
+from os.path import sep
+path.insert(1, path[0]+sep+'codec'+sep+'ber')
+import ber.suite
+path.insert(1, path[0]+sep+'codec'+sep+'cer')
+import cer.suite
+path.insert(1, path[0]+sep+'codec'+sep+'der')
+import der.suite
+from pyasn1.error import PyAsn1Error
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+suite = unittest.TestSuite()
+for m in (
+    ber.suite,
+    cer.suite,
+    der.suite
+    ):
+    suite.addTest(getattr(m, 'suite'))
+
+def runTests(): unittest.TextTestRunner(verbosity=2).run(suite)
+
+if __name__ == '__main__': runTests()

+ 26 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/suite.py

@@ -0,0 +1,26 @@
+from sys import path, version_info
+from os.path import sep
+path.insert(1, path[0]+sep+'type')
+import type.suite
+path.insert(1, path[0]+sep+'codec')
+import codec.suite
+from pyasn1.error import PyAsn1Error
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+suite = unittest.TestSuite()
+for m in (
+    type.suite,
+    codec.suite
+    ):
+    suite.addTest(getattr(m, 'suite'))
+
+def runTests(): unittest.TextTestRunner(verbosity=2).run(suite)
+
+if __name__ == '__main__': runTests()

+ 1 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/type/__init__.py

@@ -0,0 +1 @@
+# This file is necessary to make this directory a package.

+ 20 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/type/suite.py

@@ -0,0 +1,20 @@
+import test_tag, test_constraint, test_namedtype, test_univ
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+suite = unittest.TestSuite()
+loader = unittest.TestLoader()
+for m in (test_tag, test_constraint, test_namedtype, test_univ):
+    suite.addTest(loader.loadTestsFromModule(m))
+
+def runTests(): unittest.TextTestRunner(verbosity=2).run(suite)
+
+if __name__ == '__main__': runTests()

+ 280 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/type/test_constraint.py

@@ -0,0 +1,280 @@
+from pyasn1.type import constraint, error
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class SingleValueConstraintTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.SingleValueConstraint(1,2)
+        self.c2 = constraint.SingleValueConstraint(3,4)
+
+    def testCmp(self): assert self.c1 == self.c1, 'comparation fails'
+    def testHash(self): assert hash(self.c1) != hash(self.c2), 'hash() fails'
+    def testGoodVal(self):
+        try:
+            self.c1(1)
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1(4)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+class ContainedSubtypeConstraintTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.ContainedSubtypeConstraint(
+            constraint.SingleValueConstraint(12)
+            )
+
+    def testGoodVal(self):
+        try:
+            self.c1(12)
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1(4)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+class ValueRangeConstraintTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.ValueRangeConstraint(1,4)
+
+    def testGoodVal(self):
+        try:
+            self.c1(1)
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1(-5)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+class ValueSizeConstraintTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.ValueSizeConstraint(1,2)
+
+    def testGoodVal(self):
+        try:
+            self.c1('a')
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1('abc')
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+class PermittedAlphabetConstraintTestCase(SingleValueConstraintTestCase):
+    def setUp(self):
+        self.c1 = constraint.PermittedAlphabetConstraint('A', 'B', 'C')
+        self.c2 = constraint.PermittedAlphabetConstraint('DEF')
+
+    def testGoodVal(self):
+        try:
+            self.c1('A')
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1('E')
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+class ConstraintsIntersectionTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.ConstraintsIntersection(
+            constraint.SingleValueConstraint(4),
+            constraint.ValueRangeConstraint(2, 4)
+            )
+
+    def testCmp1(self):
+        assert constraint.SingleValueConstraint(4) in self.c1, '__cmp__() fails'
+
+    def testCmp2(self):
+        assert constraint.SingleValueConstraint(5) not in self.c1, \
+               '__cmp__() fails'
+
+    def testCmp3(self):
+        c = constraint.ConstraintsUnion(constraint.ConstraintsIntersection(
+            constraint.SingleValueConstraint(4),
+            constraint.ValueRangeConstraint(2, 4)
+            ))
+        assert self.c1 in c, '__cmp__() fails'
+    def testCmp4(self):
+        c = constraint.ConstraintsUnion(
+            constraint.ConstraintsIntersection(constraint.SingleValueConstraint(5))
+            )
+        assert self.c1 not in c, '__cmp__() fails'
+        
+    def testGoodVal(self):
+        try:
+            self.c1(4)
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1(-5)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+class InnerTypeConstraintTestCase(unittest.TestCase):
+    def testConst1(self):
+        c = constraint.InnerTypeConstraint(
+            constraint.SingleValueConstraint(4)
+            )
+        try:
+            c(4, 32)
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+        try:
+            c(5, 32)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+    def testConst2(self):
+        c = constraint.InnerTypeConstraint(
+            (0, constraint.SingleValueConstraint(4), 'PRESENT'),
+            (1, constraint.SingleValueConstraint(4), 'ABSENT')
+            )
+        try:
+            c(4, 0)
+        except error.ValueConstraintError:
+            raise
+            assert 0, 'constraint check fails'            
+        try:
+            c(4, 1)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'            
+        try:
+            c(3, 0)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'            
+
+# Constraints compositions
+
+class ConstraintsIntersectionTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.ConstraintsIntersection(
+            constraint.ValueRangeConstraint(1, 9),
+            constraint.ValueRangeConstraint(2, 5)
+            )
+
+    def testGoodVal(self):
+        try:
+            self.c1(3)
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1(0)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+class ConstraintsUnionTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.ConstraintsUnion(
+            constraint.SingleValueConstraint(5),
+            constraint.ValueRangeConstraint(1, 3)
+            )
+
+    def testGoodVal(self):
+        try:
+            self.c1(2)
+            self.c1(5)
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1(-5)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+class ConstraintsExclusionTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.ConstraintsExclusion(
+            constraint.ValueRangeConstraint(2, 4)
+            )
+
+    def testGoodVal(self):
+        try:
+            self.c1(6)
+        except error.ValueConstraintError:
+            assert 0, 'constraint check fails'
+    def testBadVal(self):
+        try:
+            self.c1(2)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint check fails'
+
+# Constraints derivations
+
+class DirectDerivationTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.SingleValueConstraint(5)
+        self.c2 = constraint.ConstraintsUnion(
+            self.c1, constraint.ValueRangeConstraint(1, 3)
+            )
+
+    def testGoodVal(self):
+        assert self.c1.isSuperTypeOf(self.c2), 'isSuperTypeOf failed'
+        assert not self.c1.isSubTypeOf(self.c2) , 'isSubTypeOf failed'
+    def testBadVal(self):
+        assert not self.c2.isSuperTypeOf(self.c1) , 'isSuperTypeOf failed'
+        assert self.c2.isSubTypeOf(self.c1) , 'isSubTypeOf failed'
+
+class IndirectDerivationTestCase(unittest.TestCase):
+    def setUp(self):
+        self.c1 = constraint.ConstraintsIntersection(
+            constraint.ValueRangeConstraint(1, 30)
+            )
+        self.c2 = constraint.ConstraintsIntersection(
+            self.c1, constraint.ValueRangeConstraint(1, 20)
+            )
+        self.c2 = constraint.ConstraintsIntersection(
+            self.c2, constraint.ValueRangeConstraint(1, 10)
+            )
+
+    def testGoodVal(self):
+        assert self.c1.isSuperTypeOf(self.c2), 'isSuperTypeOf failed'
+        assert not self.c1.isSubTypeOf(self.c2) , 'isSubTypeOf failed'
+    def testBadVal(self):
+        assert not self.c2.isSuperTypeOf(self.c1) , 'isSuperTypeOf failed'
+        assert self.c2.isSubTypeOf(self.c1) , 'isSubTypeOf failed'
+        
+if __name__ == '__main__': unittest.main()
+
+# how to apply size constriants to constructed types?

+ 91 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/type/test_namedtype.py

@@ -0,0 +1,91 @@
+from pyasn1.type import namedtype, univ
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class NamedTypeCaseBase(unittest.TestCase):
+    def setUp(self):
+        self.e = namedtype.NamedType('age', univ.Integer(0))
+    def testIter(self):
+        n, t = self.e
+        assert n == 'age' or t == univ.Integer(), 'unpack fails'
+    def testRepr(self):
+        assert eval(repr(self.e), { 'NamedType': namedtype.NamedType, 'Integer': univ.Integer}) == self.e, 'repr() fails'
+
+class NamedTypesCaseBase(unittest.TestCase):
+    def setUp(self):
+        self.e = namedtype.NamedTypes(
+            namedtype.NamedType('first-name', univ.OctetString('')),
+            namedtype.OptionalNamedType('age', univ.Integer(0)),
+            namedtype.NamedType('family-name', univ.OctetString(''))
+            )
+    def testRepr(self):
+        assert eval(repr(self.e), { 'NamedTypes': namedtype.NamedTypes, 'NamedType': namedtype.NamedType, 'OptionalNamedType': namedtype.OptionalNamedType, 'Integer': univ.Integer, 'OctetString': univ.OctetString }) == self.e, 'repr() fails'
+    def testIter(self):
+        for t in self.e:
+            break
+        else:
+            assert 0, '__getitem__() fails'
+            
+    def testGetTypeByPosition(self):
+        assert self.e.getTypeByPosition(0) == univ.OctetString(''), \
+               'getTypeByPosition() fails'
+
+    def testGetNameByPosition(self):
+        assert self.e.getNameByPosition(0) == 'first-name', \
+               'getNameByPosition() fails'
+
+    def testGetPositionByName(self):
+        assert self.e.getPositionByName('first-name') == 0, \
+               'getPositionByName() fails'
+
+    def testGetTypesNearPosition(self):
+        assert self.e.getTagMapNearPosition(0).getPosMap() == {
+            univ.OctetString.tagSet: univ.OctetString('')
+            }
+        assert self.e.getTagMapNearPosition(1).getPosMap() == {
+            univ.Integer.tagSet: univ.Integer(0),
+            univ.OctetString.tagSet: univ.OctetString('')
+            }
+        assert self.e.getTagMapNearPosition(2).getPosMap() == {
+            univ.OctetString.tagSet: univ.OctetString('')
+            }
+
+    def testGetTagMap(self):
+        assert self.e.getTagMap().getPosMap() == {
+            univ.OctetString.tagSet: univ.OctetString(''),
+            univ.Integer.tagSet: univ.Integer(0)
+            }
+
+    def testGetTagMapWithDups(self):
+        try:
+            self.e.getTagMap(1)
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'Duped types not noticed'
+        
+    def testGetPositionNearType(self):
+        assert self.e.getPositionNearType(univ.OctetString.tagSet, 0) == 0
+        assert self.e.getPositionNearType(univ.Integer.tagSet, 1) == 1
+        assert self.e.getPositionNearType(univ.OctetString.tagSet, 2) == 2
+
+class OrderedNamedTypesCaseBase(unittest.TestCase):
+    def setUp(self):
+        self.e = namedtype.NamedTypes(
+            namedtype.NamedType('first-name', univ.OctetString('')),
+            namedtype.NamedType('age', univ.Integer(0))
+            )
+            
+    def testGetTypeByPosition(self):
+        assert self.e.getTypeByPosition(0) == univ.OctetString(''), \
+               'getTypeByPosition() fails'
+
+if __name__ == '__main__': unittest.main()

+ 22 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/type/test_namedval.py

@@ -0,0 +1,22 @@
+from pyasn1.type import namedval
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class NamedValuesCaseBase(unittest.TestCase):
+    def setUp(self):
+        self.e = namedval.NamedValues(('off', 0), ('on', 1))
+    def testIter(self):
+        off, on = self.e
+        assert off == ('off', 0) or of == ('on', 1), 'unpack fails'
+    def testRepr(self):
+        assert eval(repr(self.e), { 'NamedValues': namedval.NamedValues }) == self.e, 'repr() fails'
+
+if __name__ == '__main__': unittest.main()

+ 115 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/type/test_tag.py

@@ -0,0 +1,115 @@
+from pyasn1.type import tag
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class TagTestCaseBase(unittest.TestCase):
+    def setUp(self):
+        self.t1 = tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 3)
+        self.t2 = tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 3)
+
+class TagReprTestCase(TagTestCaseBase):
+    def testRepr(self):
+        assert eval(repr(self.t1), { 'Tag': tag.Tag }) == self.t1, 'repr() fails'
+
+class TagCmpTestCase(TagTestCaseBase):
+    def testCmp(self):
+        assert self.t1 == self.t2, 'tag comparation fails'
+
+    def testHash(self):
+        assert hash(self.t1) == hash(self.t2), 'tag hash comparation fails'
+
+    def testSequence(self):
+        assert self.t1[0] == self.t2[0] and \
+               self.t1[1] == self.t2[1] and \
+               self.t1[2] == self.t2[2], 'tag sequence protocol fails'
+
+class TagSetTestCaseBase(unittest.TestCase):
+    def setUp(self):
+        self.ts1 = tag.initTagSet(
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
+            )
+        self.ts2 = tag.initTagSet(
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
+            )
+
+class TagSetReprTestCase(TagSetTestCaseBase):
+    def testRepr(self):
+        assert eval(repr(self.ts1), { 'TagSet': tag.TagSet, 'Tag': tag.Tag }) == self.ts1, 'repr() fails'
+
+class TagSetCmpTestCase(TagSetTestCaseBase):
+    def testCmp(self):
+        assert self.ts1 == self.ts2, 'tag set comparation fails'
+
+    def testHash(self):
+        assert hash(self.ts1) == hash(self.ts2), 'tag set hash comp. fails'
+
+    def testLen(self):
+        assert len(self.ts1) == len(self.ts2), 'tag length comparation fails'
+
+class TaggingTestSuite(TagSetTestCaseBase):
+    def testImplicitTag(self):
+        t = self.ts1.tagImplicitly(
+            tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 14)
+            )
+        assert t == tag.TagSet(
+            tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 12),
+            tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 14)
+            ), 'implicit tagging went wrong'
+
+    def testExplicitTag(self):
+        t = self.ts1.tagExplicitly(
+            tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 32)
+            )
+        assert t == tag.TagSet(
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12),
+            tag.Tag(tag.tagClassPrivate, tag.tagFormatConstructed, 32)
+            ), 'explicit tagging went wrong'
+
+class TagSetAddTestSuite(TagSetTestCaseBase):
+    def testAdd(self):
+        t = self.ts1 + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2)
+        assert t == tag.TagSet(
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12),
+            tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2)
+            ), 'TagSet.__add__() fails'
+
+    def testRadd(self):
+        t = tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2) + self.ts1
+        assert t == tag.TagSet(
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12),
+            tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
+            ), 'TagSet.__radd__() fails'
+
+class SuperTagSetTestCase(TagSetTestCaseBase):
+    def testSuperTagCheck1(self):
+        assert self.ts1.isSuperTagSetOf(
+            tag.TagSet(
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)
+            )), 'isSuperTagSetOf() fails'
+
+    def testSuperTagCheck2(self):
+        assert not self.ts1.isSuperTagSetOf(
+            tag.TagSet(
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 13)
+            )), 'isSuperTagSetOf() fails'
+
+    def testSuperTagCheck3(self):
+        assert self.ts1.isSuperTagSetOf(
+            tag.TagSet((), tag.Tag(tag.tagClassUniversal,
+                                   tag.tagFormatSimple, 12))
+            ), 'isSuperTagSetOf() fails'
+    
+if __name__ == '__main__': unittest.main()

+ 596 - 0
desktop/core/ext-py/pyasn1-0.1.8/test/type/test_univ.py

@@ -0,0 +1,596 @@
+from pyasn1.type import univ, tag, constraint, namedtype, namedval, error
+from pyasn1.compat.octets import str2octs, ints2octs
+from pyasn1.error import PyAsn1Error
+from sys import version_info
+import math
+if version_info[0:2] < (2, 7) or \
+   version_info[0:2] in ( (3, 0), (3, 1) ):
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        import unittest
+else:
+    import unittest
+
+class IntegerTestCase(unittest.TestCase):
+    def testStr(self): assert str(univ.Integer(1)) in ('1','1L'),'str() fails'
+    def testRepr(self):
+        assert eval(repr(univ.Integer(123)), { 'Integer': univ.Integer}) == univ.Integer(123), 'repr() fails'
+    def testAnd(self): assert univ.Integer(1) & 0 == 0, '__and__() fails'
+    def testOr(self): assert univ.Integer(1) | 0 == 1, '__or__() fails'
+    def testXor(self): assert univ.Integer(1) ^ 0 == 1, '__xor__() fails'
+    def testRand(self): assert 0 & univ.Integer(1) == 0, '__rand__() fails'
+    def testRor(self): assert 0 | univ.Integer(1) == 1, '__ror__() fails'
+    def testRxor(self): assert 0 ^ univ.Integer(1) == 1, '__rxor__() fails'    
+    def testAdd(self): assert univ.Integer(-4) + 6 == 2, '__add__() fails'
+    def testRadd(self): assert 4 + univ.Integer(5) == 9, '__radd__() fails'
+    def testSub(self): assert univ.Integer(3) - 6 == -3, '__sub__() fails'
+    def testRsub(self): assert 6 - univ.Integer(3) == 3, '__rsub__() fails'
+    def testMul(self): assert univ.Integer(3) * -3 == -9, '__mul__() fails'
+    def testRmul(self): assert 2 * univ.Integer(3) == 6, '__rmul__() fails'
+    def testDiv(self): assert univ.Integer(3) / 2 == 1, '__div__() fails'
+    def testRdiv(self): assert 6 / univ.Integer(3) == 2, '__rdiv__() fails'
+    def testMod(self): assert univ.Integer(3) % 2 == 1, '__mod__() fails'
+    def testRmod(self): assert 4 % univ.Integer(3) == 1, '__rmod__() fails'
+    def testPow(self): assert univ.Integer(3) ** 2 == 9, '__pow__() fails'
+    def testRpow(self): assert 2 ** univ.Integer(2) == 4, '__rpow__() fails'
+    def testLshift(self): assert univ.Integer(1) << 1 == 2, '<< fails'
+    def testRshift(self): assert univ.Integer(2) >> 1 == 1, '>> fails'
+    def testInt(self): assert int(univ.Integer(3)) == 3, '__int__() fails'
+    def testLong(self): assert int(univ.Integer(8)) == 8, '__long__() fails'
+    def testFloat(self): assert float(univ.Integer(4))==4.0,'__float__() fails'
+    def testPos(self): assert +univ.Integer(1) == 1, '__pos__() fails'
+    def testNeg(self): assert -univ.Integer(1) == -1, '__neg__() fails'
+    def testInvert(self): assert ~univ.Integer(1) == -2, '__invert__() fails'
+    def testRound(self): 
+        assert round(univ.Integer(1), 3) == 1.0,'__round__() fails'
+    def testFloor(self): 
+        assert math.floor(univ.Integer(1)) == 1,'__floor__() fails'
+    def testCeil(self): 
+        assert math.ceil(univ.Integer(1)) == 1,'__ceil__() fails'
+    if version_info[0:2] > (2, 5):
+        def testTrunc(self): 
+            assert math.trunc(univ.Integer(1)) == 1,'__trunc__() fails'
+    def testPrettyIn(self): assert univ.Integer('3') == 3, 'prettyIn() fails'
+    def testTag(self):
+        assert univ.Integer().getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02)
+            )
+    def testNamedVals(self):
+        i = univ.Integer(
+            'asn1', namedValues=univ.Integer.namedValues.clone(('asn1', 1))
+            )
+        assert i == 1, 'named val fails'
+        assert str(i) != 'asn1', 'named val __str__() fails'
+
+class BooleanTestCase(unittest.TestCase):
+    def testTruth(self):
+        assert univ.Boolean(True) and univ.Boolean(1), 'Truth initializer fails'
+    def testFalse(self):
+        assert not univ.Boolean(False) and not univ.Boolean(0), 'False initializer fails'
+    def testStr(self):
+        assert str(univ.Boolean(1)) in ('1', '1L'), 'str() fails'
+    def testRepr(self):
+        assert eval(repr(univ.Boolean(1)), { 'Boolean': univ.Boolean}) == univ.Boolean(1), 'repr() fails'
+    def testTag(self):
+        assert univ.Boolean().getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01)
+            )
+    def testConstraints(self):
+        try:
+            univ.Boolean(2)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint fail'
+    def testSubtype(self):
+        assert univ.Integer().subtype(
+            value=1,
+            implicitTag=tag.Tag(tag.tagClassPrivate,tag.tagFormatSimple,2),
+            subtypeSpec=constraint.SingleValueConstraint(1,3)
+            ) == univ.Integer(
+            value=1,
+            tagSet=tag.TagSet(tag.Tag(tag.tagClassPrivate,
+                                        tag.tagFormatSimple,2)),
+            subtypeSpec=constraint.ConstraintsIntersection(constraint.SingleValueConstraint(1,3))
+            )
+
+class BitStringTestCase(unittest.TestCase):
+    def setUp(self):
+        self.b = univ.BitString(
+            namedValues=namedval.NamedValues(('Active', 0), ('Urgent', 1))
+            )
+    def testSet(self):
+        assert self.b.clone('Active') == (1,)
+        assert self.b.clone("'1010100110001010'B") == (1,0,1,0,1,0,0,1,1,0,0,0,1,0,1,0)
+        assert self.b.clone("'A98A'H") == (1,0,1,0,1,0,0,1,1,0,0,0,1,0,1,0)
+        assert self.b.clone((1,0,1)) == (1,0,1)
+    def testStr(self):
+        assert str(self.b.clone('Urgent,Active')) == '(1, 1)'
+    def testRepr(self):
+        assert eval(repr(self.b.clone('Urgent,Active')), { 'BitString': univ.BitString }) == self.b.clone('Urgent,Active'), 'repr() fails'
+    def testTag(self):
+        assert univ.BitString().getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03)
+            )
+    def testLen(self): assert len(self.b.clone("'A98A'H")) == 16
+    def testIter(self):
+        assert self.b.clone("'A98A'H")[0] == 1
+        assert self.b.clone("'A98A'H")[1] == 0
+        assert self.b.clone("'A98A'H")[2] == 1
+        
+class OctetStringTestCase(unittest.TestCase):
+    def testInit(self):
+        assert univ.OctetString(str2octs('abcd')) == str2octs('abcd'), '__init__() fails'
+    def testBinStr(self):
+        assert univ.OctetString(binValue="1000010111101110101111000000111011") == ints2octs((133, 238, 188, 14, 192)), 'bin init fails'
+    def testHexStr(self):
+        assert univ.OctetString(hexValue="FA9823C43E43510DE3422") == ints2octs((250, 152, 35, 196, 62, 67, 81, 13, 227, 66, 32)), 'hex init fails'
+    def testTuple(self):
+        assert univ.OctetString((1,2,3,4,5)) == ints2octs((1,2,3,4,5)), 'tuple init failed'
+    if version_info[0] <= 2:
+        def testUnicode(self):
+            assert univ.OctetString(unicode('q')) == 'q', 'unicode init fails'
+    else:
+        def testUnicode(self):
+            assert univ.OctetString('q') == str2octs('q'), 'unicode init fails'
+    def testStr(self):
+        assert str(univ.OctetString('q')) == 'q', '__str__() fails'
+    def testSeq(self):
+        assert univ.OctetString('q')[0] == str2octs('q')[0],'__getitem__() fails'
+    def testRepr(self):
+        assert eval(repr(univ.OctetString('abc')), { 'OctetString': univ.OctetString}) == univ.OctetString('abc'), 'repr() fails'
+    def testAsOctets(self):
+        assert univ.OctetString('abcd').asOctets() == str2octs('abcd'), 'testAsOctets() fails'
+    def testAsInts(self):
+        assert univ.OctetString('abcd').asNumbers() == (97, 98, 99, 100), 'testAsNumbers() fails'
+
+    def testEmpty(self):
+        try:
+            str(univ.OctetString())
+        except PyAsn1Error:
+            pass
+        else:
+            assert 0, 'empty OctetString() not reported'
+            
+    def testAdd(self):
+        assert univ.OctetString('') + 'q' == str2octs('q'), '__add__() fails'
+    def testRadd(self):
+        assert 'b' + univ.OctetString('q') == str2octs('bq'), '__radd__() fails'
+    def testMul(self):
+        assert univ.OctetString('a') * 2 == str2octs('aa'), '__mul__() fails'
+    def testRmul(self):
+        assert 2 * univ.OctetString('b') == str2octs('bb'), '__rmul__() fails'
+    def testTag(self):
+        assert univ.OctetString().getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04)
+            )
+
+class Null(unittest.TestCase):
+    def testStr(self): assert str(univ.Null('')) == '', 'str() fails'
+    def testRepr(self):
+        assert eval(repr(univ.Null()), { 'Null': univ.Null}) == univ.Null(), 'repr() fails'
+    def testTag(self):
+        assert univ.Null().getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05)
+            )
+    def testConstraints(self):
+        try:
+            univ.Null(2)
+        except error.ValueConstraintError:
+            pass
+        else:
+            assert 0, 'constraint fail'
+
+class RealTestCase(unittest.TestCase):
+    def testFloat4BinEnc(self): assert univ.Real((0.25, 2, 3)) == 2.0, 'float initializer for binary encoding fails'
+    def testStr(self): assert str(univ.Real(1.0)) == '1.0','str() fails'
+    def testRepr(self):
+        assert eval(repr(univ.Real(-4.1)), { 'Real': univ.Real}) == univ.Real(-4.1), 'repr() fails'
+        assert repr(univ.Real(-4.1)) == 'Real((-41, 10, -1))','repr() fails'
+        assert eval(repr(univ.Real('inf')), { 'Real': univ.Real}) == univ.Real('inf'), 'repr() fails'
+        assert repr(univ.Real('inf')) == 'Real(\'inf\')','repr() fails'
+    def testAdd(self): assert univ.Real(-4.1) + 1.4 == -2.7, '__add__() fails'
+    def testRadd(self): assert 4 + univ.Real(0.5) == 4.5, '__radd__() fails'
+    def testSub(self): assert univ.Real(3.9) - 1.7 == 2.2, '__sub__() fails'
+    def testRsub(self): assert 6.1 - univ.Real(0.1) == 6, '__rsub__() fails'
+    def testMul(self): assert univ.Real(3.0) * -3 == -9, '__mul__() fails'
+    def testRmul(self): assert 2 * univ.Real(3.0) == 6, '__rmul__() fails'
+    def testDiv(self): assert univ.Real(3.0) / 2 == 1.5, '__div__() fails'
+    def testRdiv(self): assert 6 / univ.Real(3.0) == 2, '__rdiv__() fails'
+    def testMod(self): assert univ.Real(3.0) % 2 == 1, '__mod__() fails'
+    def testRmod(self): assert 4 % univ.Real(3.0) == 1, '__rmod__() fails'
+    def testPow(self): assert univ.Real(3.0) ** 2 == 9, '__pow__() fails'
+    def testRpow(self): assert 2 ** univ.Real(2.0) == 4, '__rpow__() fails'
+    def testInt(self): assert int(univ.Real(3.0)) == 3, '__int__() fails'
+    def testLong(self): assert int(univ.Real(8.0)) == 8, '__long__() fails'
+    def testFloat(self): assert float(univ.Real(4.0))==4.0,'__float__() fails'
+    def testPrettyIn(self): assert univ.Real((3,10,0)) == 3, 'prettyIn() fails'
+    # infinite float values
+    def testStrInf(self):
+        assert str(univ.Real('inf')) == 'inf','str() fails'
+    def testAddInf(self):
+        assert univ.Real('inf') + 1 == float('inf'), '__add__() fails'
+    def testRaddInf(self):
+        assert 1 + univ.Real('inf') == float('inf'), '__radd__() fails'
+    def testIntInf(self):
+        try:
+            assert int(univ.Real('inf'))
+        except OverflowError:
+            pass
+        else:
+            assert 0, '__int__() fails'
+    def testLongInf(self):
+        try:
+            assert int(univ.Real('inf'))
+        except OverflowError:
+            pass
+        else:
+            assert 0, '__long__() fails'        
+        assert int(univ.Real(8.0)) == 8, '__long__() fails'
+    def testFloatInf(self):
+        assert float(univ.Real('-inf')) == float('-inf'),'__float__() fails'
+    def testPrettyInInf(self):
+        assert univ.Real(float('inf')) == float('inf'), 'prettyIn() fails'
+    def testPlusInf(self):
+        assert univ.Real('inf').isPlusInfinity(), 'isPlusInfinity failed'
+    def testMinusInf(self):
+        assert univ.Real('-inf').isMinusInfinity(), 'isMinusInfinity failed'
+
+    def testPos(self): assert +univ.Real(1.0) == 1.0, '__pos__() fails'
+    def testNeg(self): assert -univ.Real(1.0) == -1.0, '__neg__() fails'
+    def testRound(self): 
+        assert round(univ.Real(1.123), 2) == 1.12,'__round__() fails'
+    def testFloor(self): 
+        assert math.floor(univ.Real(1.6)) == 1.0,'__floor__() fails'
+    def testCeil(self): 
+        assert math.ceil(univ.Real(1.2)) == 2.0,'__ceil__() fails'
+    if version_info[0:2] > (2, 5):
+        def testTrunc(self): 
+            assert math.trunc(univ.Real(1.1)) == 1.0,'__trunc__() fails'
+ 
+    def testTag(self):
+        assert univ.Real().getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09)
+            )
+
+class ObjectIdentifier(unittest.TestCase):
+    def testStr(self):
+        assert str(univ.ObjectIdentifier((1,3,6))) == '1.3.6', 'str() fails'
+    def testRepr(self):
+        assert eval(repr(univ.ObjectIdentifier('1.3.6')), { 'ObjectIdentifier': univ.ObjectIdentifier}) == univ.ObjectIdentifier('1.3.6'), 'repr() fails'
+    def testEq(self):
+        assert univ.ObjectIdentifier((1,3,6)) == (1,3,6), '__cmp__() fails'
+    def testAdd(self):
+        assert univ.ObjectIdentifier((1,3)) + (6,)==(1,3,6),'__add__() fails'
+    def testRadd(self):
+        assert (1,) + univ.ObjectIdentifier((3,6))==(1,3,6),'__radd__() fails'
+    def testLen(self):
+        assert len(univ.ObjectIdentifier((1,3))) == 2,'__len__() fails'
+    def testPrefix(self):
+        o = univ.ObjectIdentifier('1.3.6')
+        assert o.isPrefixOf((1,3,6)), 'isPrefixOf() fails'
+        assert o.isPrefixOf((1,3,6,1)), 'isPrefixOf() fails'
+        assert not o.isPrefixOf((1,3)), 'isPrefixOf() fails'        
+    def testInput1(self):
+        assert univ.ObjectIdentifier('1.3.6')==(1,3,6),'prettyIn() fails'
+    def testInput2(self):
+        assert univ.ObjectIdentifier((1,3,6))==(1,3,6),'prettyIn() fails'
+    def testInput3(self):
+        assert univ.ObjectIdentifier(univ.ObjectIdentifier('1.3') + (6,))==(1,3,6),'prettyIn() fails'
+    def testTag(self):
+        assert univ.ObjectIdentifier().getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06)
+            )
+
+class SequenceOf(unittest.TestCase):
+    def setUp(self):
+        self.s1 = univ.SequenceOf(
+            componentType=univ.OctetString('')
+            )
+        self.s2 = self.s1.clone()
+    def testRepr(self):
+        assert eval(repr(self.s1.clone().setComponents('a', 'b')), { 'SequenceOf': univ.SequenceOf, 'OctetString': univ.OctetString }) == self.s1.clone().setComponents('a', 'b'), 'repr() fails'
+    def testTag(self):
+        assert self.s1.getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
+            ), 'wrong tagSet'
+    def testSeq(self):
+        self.s1.setComponentByPosition(0, univ.OctetString('abc'))
+        assert self.s1[0] == str2octs('abc'), 'set by idx fails'
+        self.s1[0] = 'cba'
+        assert self.s1[0] == str2octs('cba'), 'set by idx fails'
+    def testCmp(self):
+        self.s1.clear()
+        self.s1.setComponentByPosition(0, 'abc')
+        self.s2.clear()
+        self.s2.setComponentByPosition(0, univ.OctetString('abc'))
+        assert self.s1 == self.s2, '__cmp__() fails'
+    def testSubtypeSpec(self):
+        s = self.s1.clone(subtypeSpec=constraint.ConstraintsUnion(
+            constraint.SingleValueConstraint(str2octs('abc'))
+            ))
+        try:
+            s.setComponentByPosition(0, univ.OctetString('abc'))
+        except:
+            assert 0, 'constraint fails'
+        try:
+            s.setComponentByPosition(1, univ.OctetString('Abc'))
+        except:
+            try:
+                s.setComponentByPosition(1, univ.OctetString('Abc'),
+                                         verifyConstraints=False)
+            except:
+                assert 0, 'constraint failes with verifyConstraints=True'
+        else:
+            assert 0, 'constraint fails'
+    def testComponentTagsMatching(self):
+        s = self.s1.clone()
+        o = univ.OctetString('abc').subtype(explicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 12))
+        try:
+            s.setComponentByPosition(0, o)
+        except:
+            pass
+        else:
+            assert 0, 'inner supertype tag allowed'
+    def testComponentConstraintsMatching(self):
+        s = self.s1.clone()
+        o = univ.OctetString().subtype(subtypeSpec=constraint.ConstraintsUnion(constraint.SingleValueConstraint(str2octs('cba'))))
+        s.strictConstraints = True
+        try:
+            s.setComponentByPosition(0, o.clone('cba'))
+        except:
+            pass
+        else:
+            assert 0, 'inner supertype constraint allowed'
+        s.strictConstraints = False
+        try:
+            s.setComponentByPosition(0, o.clone('cba'))
+        except:
+            assert 0, 'inner supertype constraint disallowed'
+        else:
+            pass
+    def testSizeSpec(self):
+        s = self.s1.clone(sizeSpec=constraint.ConstraintsUnion(
+            constraint.ValueSizeConstraint(1,1)
+            ))
+        s.setComponentByPosition(0, univ.OctetString('abc'))
+        try:
+            s.verifySizeSpec()
+        except:
+            assert 0, 'size spec fails'
+        s.setComponentByPosition(1, univ.OctetString('abc'))
+        try:
+            s.verifySizeSpec()
+        except:
+            pass
+        else:
+            assert 0, 'size spec fails'
+    def testGetComponentTagMap(self):
+        assert self.s1.getComponentTagMap().getPosMap() == {
+            univ.OctetString.tagSet: univ.OctetString('')
+            }
+    def testSubtype(self):
+        self.s1.clear()
+        assert self.s1.subtype(
+            implicitTag=tag.Tag(tag.tagClassPrivate,tag.tagFormatSimple,2),
+            subtypeSpec=constraint.SingleValueConstraint(1,3),
+            sizeSpec=constraint.ValueSizeConstraint(0,1)
+            ) == self.s1.clone(
+            tagSet=tag.TagSet(tag.Tag(tag.tagClassPrivate,
+                                        tag.tagFormatSimple,2)),
+            subtypeSpec=constraint.ConstraintsIntersection(constraint.SingleValueConstraint(1,3)),
+            sizeSpec=constraint.ValueSizeConstraint(0,1)
+            )
+    def testClone(self):
+        self.s1.setComponentByPosition(0, univ.OctetString('abc'))
+        s = self.s1.clone()
+        assert len(s) == 0
+        s = self.s1.clone(cloneValueFlag=1)
+        assert len(s) == 1
+        assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0)
+    def testSetComponents(self):
+        assert self.s1.clone().setComponents('abc', 'def') == \
+            self.s1.setComponentByPosition(0, 'abc').setComponentByPosition(1, 'def')
+                
+class Sequence(unittest.TestCase):
+    def setUp(self):
+        self.s1 = univ.Sequence(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('name', univ.OctetString('')),
+            namedtype.OptionalNamedType('nick', univ.OctetString('')),
+            namedtype.DefaultedNamedType('age', univ.Integer(34))
+            ))
+    def testRepr(self):
+        assert eval(repr(self.s1.clone().setComponents('a', 'b')), { 'Sequence': univ.Sequence, 'OctetString': univ.OctetString, 'Integer': univ.Integer, 'NamedTypes': namedtype.NamedTypes, 'NamedType': namedtype.NamedType, 'OptionalNamedType': namedtype.OptionalNamedType, 'DefaultedNamedType': namedtype.DefaultedNamedType }) == self.s1.clone().setComponents('a', 'b'), 'repr() fails'
+    def testTag(self):
+        assert self.s1.getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10)
+            ), 'wrong tagSet'
+    def testById(self):
+        self.s1.setComponentByName('name', univ.OctetString('abc'))
+        assert self.s1.getComponentByName('name') == str2octs('abc'), 'set by name fails'
+    def testByKey(self):
+        self.s1['name'] = 'abc'
+        assert self.s1['name'] == str2octs('abc'), 'set by key fails'
+    def testGetNearPosition(self):
+        assert self.s1.getComponentTagMapNearPosition(1).getPosMap() == {
+            univ.OctetString.tagSet: univ.OctetString(''),
+            univ.Integer.tagSet: univ.Integer(34)
+            }
+        assert self.s1.getComponentPositionNearType(
+            univ.OctetString.tagSet, 1
+            ) == 1
+    def testGetDefaultComponentByPosition(self):
+        self.s1.clear()
+        assert self.s1.getDefaultComponentByPosition(0) == None
+        assert self.s1.getDefaultComponentByPosition(2) == univ.Integer(34)
+    def testSetDefaultComponents(self):
+        self.s1.clear()
+        assert self.s1.getComponentByPosition(2) == None
+        self.s1.setComponentByPosition(0, univ.OctetString('Ping'))
+        self.s1.setComponentByPosition(1, univ.OctetString('Pong'))
+        self.s1.setDefaultComponents()
+        assert self.s1.getComponentByPosition(2) == 34
+    def testClone(self):
+        self.s1.setComponentByPosition(0, univ.OctetString('abc'))
+        self.s1.setComponentByPosition(1, univ.OctetString('def'))
+        self.s1.setComponentByPosition(2, univ.Integer(123))
+        s = self.s1.clone()
+        assert s.getComponentByPosition(0) != self.s1.getComponentByPosition(0)
+        assert s.getComponentByPosition(1) != self.s1.getComponentByPosition(1)
+        assert s.getComponentByPosition(2) != self.s1.getComponentByPosition(2)
+        s = self.s1.clone(cloneValueFlag=1)
+        assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0)
+        assert s.getComponentByPosition(1) == self.s1.getComponentByPosition(1)
+        assert s.getComponentByPosition(2) == self.s1.getComponentByPosition(2)
+    def testComponentTagsMatching(self):
+        s = self.s1.clone()
+        o = univ.OctetString('abc').subtype(explicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 12))
+        try:
+            s.setComponentByName('name', o)
+        except:
+            pass
+        else:
+            assert 0, 'inner supertype tag allowed'
+    def testComponentConstraintsMatching(self):
+        s = self.s1.clone()
+        o = univ.OctetString().subtype(subtypeSpec=constraint.ConstraintsUnion(constraint.SingleValueConstraint(str2octs('cba'))))
+        s.strictConstraints = True
+        try:
+            s.setComponentByName('name', o.clone('cba'))
+        except:
+            pass
+        else:
+            assert 0, 'inner supertype constraint allowed'
+        s.strictConstraints = False
+        try:
+            s.setComponentByName('name', o.clone('cba'))
+        except:
+            assert 0, 'inner supertype constraint disallowed'
+        else:
+            pass
+    def testSetComponents(self):
+        assert self.s1.clone().setComponents(name='a', nick='b', age=1) == \
+            self.s1.setComponentByPosition(0, 'a').setComponentByPosition(1, 'b').setComponentByPosition(2, 1)
+
+class SetOf(unittest.TestCase):
+    def setUp(self):
+        self.s1 = univ.SetOf(componentType=univ.OctetString(''))
+    def testTag(self):
+        assert self.s1.getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
+            ), 'wrong tagSet'
+    def testSeq(self):
+        self.s1.setComponentByPosition(0, univ.OctetString('abc'))
+        assert self.s1[0] == str2octs('abc'), 'set by idx fails'
+        self.s1.setComponentByPosition(0, self.s1[0].clone('cba'))
+        assert self.s1[0] == str2octs('cba'), 'set by idx fails'
+
+class Set(unittest.TestCase):
+    def setUp(self):
+        self.s1 = univ.Set(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('name', univ.OctetString('')),
+            namedtype.OptionalNamedType('null', univ.Null('')),
+            namedtype.DefaultedNamedType('age', univ.Integer(34))
+            ))
+        self.s2 = self.s1.clone()
+    def testTag(self):
+        assert self.s1.getTagSet() == tag.TagSet(
+            (),
+            tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11)
+            ), 'wrong tagSet'
+    def testByTypeWithPythonValue(self):
+        self.s1.setComponentByType(univ.OctetString.tagSet, 'abc')
+        assert self.s1.getComponentByType(
+            univ.OctetString.tagSet
+            ) == str2octs('abc'), 'set by name fails'
+    def testByTypeWithInstance(self):
+        self.s1.setComponentByType(univ.OctetString.tagSet, univ.OctetString('abc'))
+        assert self.s1.getComponentByType(
+            univ.OctetString.tagSet
+            ) == str2octs('abc'), 'set by name fails'
+    def testGetTagMap(self):
+        assert self.s1.getTagMap().getPosMap() == {
+            univ.Set.tagSet: univ.Set()
+            }
+    def testGetComponentTagMap(self):
+        assert self.s1.getComponentTagMap().getPosMap() == {
+            univ.OctetString.tagSet: univ.OctetString(''),
+            univ.Null.tagSet: univ.Null(''),
+            univ.Integer.tagSet: univ.Integer(34)
+            }
+    def testGetPositionByType(self):
+        assert self.s1.getComponentPositionByType(
+            univ.Null().getTagSet()
+            ) == 1
+
+class Choice(unittest.TestCase):
+    def setUp(self):
+        innerComp = univ.Choice(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('count', univ.Integer()),
+            namedtype.NamedType('flag', univ.Boolean())
+            ))
+        self.s1 = univ.Choice(componentType=namedtype.NamedTypes(
+            namedtype.NamedType('name', univ.OctetString()),
+            namedtype.NamedType('sex', innerComp)
+            ))
+    def testTag(self):
+        assert self.s1.getTagSet() == tag.TagSet(), 'wrong tagSet'
+    def testRepr(self):
+        assert eval(repr(self.s1.clone().setComponents('a')), { 'Choice': univ.Choice, 'OctetString': univ.OctetString, 'Integer': univ.Integer, 'Boolean': univ.Boolean, 'NamedTypes': namedtype.NamedTypes, 'NamedType': namedtype.NamedType }) == self.s1.clone().setComponents('a'), 'repr() fails'
+        assert eval(repr(self.s1.clone().setComponents(sex=self.s1.setComponentByPosition(1).getComponentByPosition(1).clone().setComponents(count=univ.Integer(123)))), { 'Choice': univ.Choice, 'OctetString': univ.OctetString, 'Integer': univ.Integer, 'Boolean': univ.Boolean, 'NamedTypes': namedtype.NamedTypes, 'NamedType': namedtype.NamedType }) == self.s1.clone().setComponents(sex=self.s1.setComponentByPosition(1).getComponentByPosition(1).clone().setComponents(count=univ.Integer(123))), 'repr() fails'
+    def testOuterByTypeWithPythonValue(self):
+        self.s1.setComponentByType(univ.OctetString.tagSet, 'abc')
+        assert self.s1.getComponentByType(
+            univ.OctetString.tagSet
+            ) == str2octs('abc')
+    def testOuterByTypeWithInstanceValue(self):
+        self.s1.setComponentByType(
+            univ.OctetString.tagSet, univ.OctetString('abc')
+            )
+        assert self.s1.getComponentByType(
+            univ.OctetString.tagSet
+            ) == str2octs('abc')
+    def testInnerByTypeWithPythonValue(self):
+        self.s1.setComponentByType(univ.Integer.tagSet, 123, 1)
+        assert self.s1.getComponentByType(
+            univ.Integer.tagSet, 1
+            ) == 123
+    def testInnerByTypeWithInstanceValue(self):
+        self.s1.setComponentByType(
+            univ.Integer.tagSet, univ.Integer(123), 1
+            )
+        assert self.s1.getComponentByType(
+            univ.Integer.tagSet, 1
+            ) == 123
+    def testCmp(self):
+        self.s1.setComponentByName('name', univ.OctetString('abc'))
+        assert self.s1 == str2octs('abc'), '__cmp__() fails'
+    def testGetComponent(self):
+        self.s1.setComponentByType(univ.OctetString.tagSet, 'abc')
+        assert self.s1.getComponent() == str2octs('abc'), 'getComponent() fails'
+    def testGetName(self):
+        self.s1.setComponentByType(univ.OctetString.tagSet, 'abc')
+        assert self.s1.getName() == 'name', 'getName() fails'
+    def testSetComponentByPosition(self):
+        self.s1.setComponentByPosition(0, univ.OctetString('Jim'))
+        assert self.s1 == str2octs('Jim')
+    def testClone(self):
+        self.s1.setComponentByPosition(0, univ.OctetString('abc'))
+        s = self.s1.clone()
+        assert len(s) == 0
+        s = self.s1.clone(cloneValueFlag=1)
+        assert len(s) == 1
+        assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0)
+        
+if __name__ == '__main__': unittest.main()