import _thread as thread, marshal, struct, sys, zlib
CRYPT_BLOCK_SIZE = 16

class Cipher:
    __doc__ = '\n    This class is used only to decrypt Python modules.\n    '

    def __init__(self):
        import pyimod00_crypto_key
        key = pyimod00_crypto_key.key
        if not type(key) is str:
            raise AssertionError
        elif len(key) > CRYPT_BLOCK_SIZE:
            self.key = key[0:CRYPT_BLOCK_SIZE]
        else:
            self.key = key.zfill(CRYPT_BLOCK_SIZE)
        assert len(self.key) == CRYPT_BLOCK_SIZE
        import tinyaes
        self._aesmod = tinyaes
        del sys.modules['tinyaes']

    def __create_cipher(self, iv):
        return self._aesmod.AES(self.key.encode(), iv)

    def decrypt(self, data):
        cipher = self._Cipher__create_cipher(data[:CRYPT_BLOCK_SIZE])
        return cipher.CTR_xcrypt_buffer(data[CRYPT_BLOCK_SIZE:])


class ZlibArchiveReader(ArchiveReader):
    __doc__ = '\n    ZlibArchive - an archive with compressed entries. Archive is read from the executable created by PyInstaller.\n\n    This archive is used for bundling python modules inside the executable.\n\n    NOTE: The whole ZlibArchive (PYZ) is compressed, so it is not necessary to compress individual modules.\n    '
    MAGIC = b'PYZ\x00'
    TOCPOS = 8
    HDRLEN = ArchiveReader.HDRLEN + 5

    def __init__(self, path=None, offset=None):
        if path is None:
            offset = 0
        else:
            if offset is None:
                for i in range(len(path) - 1, -1, -1):
                    if path[i] == '?':
                        try:
                            offset = int(path[i + 1:])
                        except ValueError:
                            continue

                        path = path[:i]
                        break
                else:
                    offset = 0

            else:
                super().__init__(path, offset)
                try:
                    import pyimod00_crypto_key
                    self.cipher = Cipher()
                except ImportError:
                    self.cipher = None

    def is_package(self, name):
        typ, pos, length = self.toc.get(name, (0, None, 0))
        if pos is None:
            return
        return typ in (PYZ_TYPE_PKG, PYZ_TYPE_NSPKG)

    def is_pep420_namespace_package(self, name):
        typ, pos, length = self.toc.get(name, (0, None, 0))
        if pos is None:
            return
        return typ == PYZ_TYPE_NSPKG

    def extract(self, name):
        typ, pos, length = self.toc.get(name, (0, None, 0))
        if pos is None:
            return
        with self.lib:
            self.lib.seek(self.start + pos)
            obj = self.lib.read(length)
        try:
            if self.cipher:
                obj = self.cipher.decrypt(obj)
            obj = zlib.decompress(obj)
            if typ in (PYZ_TYPE_MODULE, PYZ_TYPE_PKG, PYZ_TYPE_NSPKG):
                obj = marshal.loads(obj)
        except EOFError as e:
            try:
                raise ImportError("PYZ entry '%s' failed to unmarshal" % name) from e
            finally:
                e = None
                del e

        return (
         typ, obj)