ZIP archive file: C++/STL parsing library

ZIP is a popular archive file format, introduced in 1989 by Phil Katz and originally implemented in PKZIP utility by PKWARE.

Thanks to solid support of it in most desktop environments and operating systems, and algorithms / specs availability in public domain, it quickly became tool of choice for implementing file containers.

For example, Java .jar files, OpenDocument, Office Open XML, EPUB files are actually ZIP archives.

File extension

zip

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of ZIP archive file using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (std::istream). One can open local file for that, or use existing std::string or char* buffer.
    #include <fstream>
    
    std::ifstream is("path/to/local/file.zip", std::ifstream::binary);
    #include <sstream>
    
    std::istringstream is(str);
    #include <sstream>
    
    const char buf[] = { ... };
    std::string str(buf, sizeof buf);
    std::istringstream is(str);
  2. We need to wrap our input stream into Kaitai stream:
    #include <kaitai/kaitaistream.h>
    
    kaitai::kstream ks(&is);
  3. And finally, we can invoke the parsing:
    zip_t data(&ks);

After that, one can get various attributes from the structure by invoking getter methods like:

data.sections() // => get sections

C++/STL source code to parse ZIP archive file

zip.h

#ifndef ZIP_H_
#define ZIP_H_

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "kaitai/kaitaistruct.h"

#include <stdint.h>
#include <vector>

#if KAITAI_STRUCT_VERSION < 7000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.7 or later is required"
#endif

/**
 * ZIP is a popular archive file format, introduced in 1989 by Phil Katz
 * and originally implemented in PKZIP utility by PKWARE.
 * 
 * Thanks to solid support of it in most desktop environments and
 * operating systems, and algorithms / specs availability in public
 * domain, it quickly became tool of choice for implementing file
 * containers.
 * 
 * For example, Java .jar files, OpenDocument, Office Open XML, EPUB files
 * are actually ZIP archives.
 * \sa Source
 */

class zip_t : public kaitai::kstruct {

public:
    class local_file_t;
    class data_descriptor_t;
    class extra_field_t;
    class central_dir_entry_t;
    class pk_section_t;
    class extras_t;
    class local_file_header_t;
    class end_of_central_dir_t;

    enum compression_t {
        COMPRESSION_NONE = 0,
        COMPRESSION_SHRUNK = 1,
        COMPRESSION_REDUCED_1 = 2,
        COMPRESSION_REDUCED_2 = 3,
        COMPRESSION_REDUCED_3 = 4,
        COMPRESSION_REDUCED_4 = 5,
        COMPRESSION_IMPLODED = 6,
        COMPRESSION_DEFLATED = 8,
        COMPRESSION_ENHANCED_DEFLATED = 9,
        COMPRESSION_PKWARE_DCL_IMPLODED = 10,
        COMPRESSION_BZIP2 = 12,
        COMPRESSION_LZMA = 14,
        COMPRESSION_IBM_TERSE = 18,
        COMPRESSION_IBM_LZ77_Z = 19,
        COMPRESSION_PPMD = 98
    };

    enum extra_codes_t {
        EXTRA_CODES_ZIP64 = 1,
        EXTRA_CODES_AV_INFO = 7,
        EXTRA_CODES_OS2 = 9,
        EXTRA_CODES_NTFS = 10,
        EXTRA_CODES_OPENVMS = 12,
        EXTRA_CODES_PKWARE_UNIX = 13,
        EXTRA_CODES_FILE_STREAM_AND_FORK_DESCRIPTORS = 14,
        EXTRA_CODES_PATCH_DESCRIPTOR = 15,
        EXTRA_CODES_PKCS7 = 20,
        EXTRA_CODES_X509_CERT_ID_AND_SIGNATURE_FOR_FILE = 21,
        EXTRA_CODES_X509_CERT_ID_FOR_CENTRAL_DIR = 22,
        EXTRA_CODES_STRONG_ENCRYPTION_HEADER = 23,
        EXTRA_CODES_RECORD_MANAGEMENT_CONTROLS = 24,
        EXTRA_CODES_PKCS7_ENC_RECIP_CERT_LIST = 25,
        EXTRA_CODES_IBM_S390_UNCOMP = 101,
        EXTRA_CODES_IBM_S390_COMP = 102,
        EXTRA_CODES_POSZIP_4690 = 18064,
        EXTRA_CODES_EXTENDED_TIMESTAMP = 21589,
        EXTRA_CODES_INFOZIP_UNIX = 30805,
        EXTRA_CODES_INFOZIP_UNIX_VAR_SIZE = 30837
    };

    zip_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, zip_t* p__root = 0);

private:
    void _read();

public:
    ~zip_t();

    class local_file_t : public kaitai::kstruct {

    public:

        local_file_t(kaitai::kstream* p__io, zip_t::pk_section_t* p__parent = 0, zip_t* p__root = 0);

    private:
        void _read();

    public:
        ~local_file_t();

    private:
        local_file_header_t* m_header;
        std::string m_body;
        zip_t* m__root;
        zip_t::pk_section_t* m__parent;

    public:
        local_file_header_t* header() const { return m_header; }
        std::string body() const { return m_body; }
        zip_t* _root() const { return m__root; }
        zip_t::pk_section_t* _parent() const { return m__parent; }
    };

    class data_descriptor_t : public kaitai::kstruct {

    public:

        data_descriptor_t(kaitai::kstream* p__io, zip_t::pk_section_t* p__parent = 0, zip_t* p__root = 0);

    private:
        void _read();

    public:
        ~data_descriptor_t();

    private:
        uint32_t m_crc32;
        uint32_t m_len_body_compressed;
        uint32_t m_len_body_uncompressed;
        zip_t* m__root;
        zip_t::pk_section_t* m__parent;

    public:
        uint32_t crc32() const { return m_crc32; }
        uint32_t len_body_compressed() const { return m_len_body_compressed; }
        uint32_t len_body_uncompressed() const { return m_len_body_uncompressed; }
        zip_t* _root() const { return m__root; }
        zip_t::pk_section_t* _parent() const { return m__parent; }
    };

    class extra_field_t : public kaitai::kstruct {

    public:
        class ntfs_t;
        class extended_timestamp_t;
        class infozip_unix_var_size_t;

        extra_field_t(kaitai::kstream* p__io, zip_t::extras_t* p__parent = 0, zip_t* p__root = 0);

    private:
        void _read();

    public:
        ~extra_field_t();

        /**
         * \sa Source
         */

        class ntfs_t : public kaitai::kstruct {

        public:
            class attribute_t;
            class attribute_1_t;

            ntfs_t(kaitai::kstream* p__io, zip_t::extra_field_t* p__parent = 0, zip_t* p__root = 0);

        private:
            void _read();

        public:
            ~ntfs_t();

            class attribute_t : public kaitai::kstruct {

            public:

                attribute_t(kaitai::kstream* p__io, zip_t::extra_field_t::ntfs_t* p__parent = 0, zip_t* p__root = 0);

            private:
                void _read();

            public:
                ~attribute_t();

            private:
                uint16_t m_tag;
                uint16_t m_len_body;
                attribute_1_t* m_body;
                bool n_body;

            public:
                bool _is_null_body() { body(); return n_body; };

            private:
                zip_t* m__root;
                zip_t::extra_field_t::ntfs_t* m__parent;
                std::string m__raw_body;
                kaitai::kstream* m__io__raw_body;

            public:
                uint16_t tag() const { return m_tag; }
                uint16_t len_body() const { return m_len_body; }
                attribute_1_t* body() const { return m_body; }
                zip_t* _root() const { return m__root; }
                zip_t::extra_field_t::ntfs_t* _parent() const { return m__parent; }
                std::string _raw_body() const { return m__raw_body; }
                kaitai::kstream* _io__raw_body() const { return m__io__raw_body; }
            };

            class attribute_1_t : public kaitai::kstruct {

            public:

                attribute_1_t(kaitai::kstream* p__io, zip_t::extra_field_t::ntfs_t::attribute_t* p__parent = 0, zip_t* p__root = 0);

            private:
                void _read();

            public:
                ~attribute_1_t();

            private:
                uint64_t m_last_mod_time;
                uint64_t m_last_access_time;
                uint64_t m_creation_time;
                zip_t* m__root;
                zip_t::extra_field_t::ntfs_t::attribute_t* m__parent;

            public:
                uint64_t last_mod_time() const { return m_last_mod_time; }
                uint64_t last_access_time() const { return m_last_access_time; }
                uint64_t creation_time() const { return m_creation_time; }
                zip_t* _root() const { return m__root; }
                zip_t::extra_field_t::ntfs_t::attribute_t* _parent() const { return m__parent; }
            };

        private:
            uint32_t m_reserved;
            std::vector<attribute_t*>* m_attributes;
            zip_t* m__root;
            zip_t::extra_field_t* m__parent;

        public:
            uint32_t reserved() const { return m_reserved; }
            std::vector<attribute_t*>* attributes() const { return m_attributes; }
            zip_t* _root() const { return m__root; }
            zip_t::extra_field_t* _parent() const { return m__parent; }
        };

        /**
         * \sa Source
         */

        class extended_timestamp_t : public kaitai::kstruct {

        public:

            extended_timestamp_t(kaitai::kstream* p__io, zip_t::extra_field_t* p__parent = 0, zip_t* p__root = 0);

        private:
            void _read();

        public:
            ~extended_timestamp_t();

        private:
            uint8_t m_flags;
            uint32_t m_mod_time;
            uint32_t m_access_time;
            bool n_access_time;

        public:
            bool _is_null_access_time() { access_time(); return n_access_time; };

        private:
            uint32_t m_create_time;
            bool n_create_time;

        public:
            bool _is_null_create_time() { create_time(); return n_create_time; };

        private:
            zip_t* m__root;
            zip_t::extra_field_t* m__parent;

        public:
            uint8_t flags() const { return m_flags; }
            uint32_t mod_time() const { return m_mod_time; }
            uint32_t access_time() const { return m_access_time; }
            uint32_t create_time() const { return m_create_time; }
            zip_t* _root() const { return m__root; }
            zip_t::extra_field_t* _parent() const { return m__parent; }
        };

        /**
         * \sa Source
         */

        class infozip_unix_var_size_t : public kaitai::kstruct {

        public:

            infozip_unix_var_size_t(kaitai::kstream* p__io, zip_t::extra_field_t* p__parent = 0, zip_t* p__root = 0);

        private:
            void _read();

        public:
            ~infozip_unix_var_size_t();

        private:
            uint8_t m_version;
            uint8_t m_len_uid;
            std::string m_uid;
            uint8_t m_len_gid;
            std::string m_gid;
            zip_t* m__root;
            zip_t::extra_field_t* m__parent;

        public:

            /**
             * Version of this extra field, currently 1
             */
            uint8_t version() const { return m_version; }

            /**
             * Size of UID field
             */
            uint8_t len_uid() const { return m_len_uid; }

            /**
             * UID (User ID) for a file
             */
            std::string uid() const { return m_uid; }

            /**
             * Size of GID field
             */
            uint8_t len_gid() const { return m_len_gid; }

            /**
             * GID (Group ID) for a file
             */
            std::string gid() const { return m_gid; }
            zip_t* _root() const { return m__root; }
            zip_t::extra_field_t* _parent() const { return m__parent; }
        };

    private:
        extra_codes_t m_code;
        uint16_t m_len_body;
        kaitai::kstruct* m_body;
        bool n_body;

    public:
        bool _is_null_body() { body(); return n_body; };

    private:
        zip_t* m__root;
        zip_t::extras_t* m__parent;
        std::string m__raw_body;
        kaitai::kstream* m__io__raw_body;

    public:
        extra_codes_t code() const { return m_code; }
        uint16_t len_body() const { return m_len_body; }
        kaitai::kstruct* body() const { return m_body; }
        zip_t* _root() const { return m__root; }
        zip_t::extras_t* _parent() const { return m__parent; }
        std::string _raw_body() const { return m__raw_body; }
        kaitai::kstream* _io__raw_body() const { return m__io__raw_body; }
    };

    /**
     * \sa - 4.3.12
     */

    class central_dir_entry_t : public kaitai::kstruct {

    public:

        central_dir_entry_t(kaitai::kstream* p__io, zip_t::pk_section_t* p__parent = 0, zip_t* p__root = 0);

    private:
        void _read();

    public:
        ~central_dir_entry_t();

    private:
        bool f_local_header;
        pk_section_t* m_local_header;

    public:
        pk_section_t* local_header();

    private:
        uint16_t m_version_made_by;
        uint16_t m_version_needed_to_extract;
        uint16_t m_flags;
        compression_t m_compression_method;
        uint16_t m_last_mod_file_time;
        uint16_t m_last_mod_file_date;
        uint32_t m_crc32;
        uint32_t m_len_body_compressed;
        uint32_t m_len_body_uncompressed;
        uint16_t m_len_file_name;
        uint16_t m_len_extra;
        uint16_t m_len_comment;
        uint16_t m_disk_number_start;
        uint16_t m_int_file_attr;
        uint32_t m_ext_file_attr;
        int32_t m_ofs_local_header;
        std::string m_file_name;
        extras_t* m_extra;
        std::string m_comment;
        zip_t* m__root;
        zip_t::pk_section_t* m__parent;
        std::string m__raw_extra;
        kaitai::kstream* m__io__raw_extra;

    public:
        uint16_t version_made_by() const { return m_version_made_by; }
        uint16_t version_needed_to_extract() const { return m_version_needed_to_extract; }
        uint16_t flags() const { return m_flags; }
        compression_t compression_method() const { return m_compression_method; }
        uint16_t last_mod_file_time() const { return m_last_mod_file_time; }
        uint16_t last_mod_file_date() const { return m_last_mod_file_date; }
        uint32_t crc32() const { return m_crc32; }
        uint32_t len_body_compressed() const { return m_len_body_compressed; }
        uint32_t len_body_uncompressed() const { return m_len_body_uncompressed; }
        uint16_t len_file_name() const { return m_len_file_name; }
        uint16_t len_extra() const { return m_len_extra; }
        uint16_t len_comment() const { return m_len_comment; }
        uint16_t disk_number_start() const { return m_disk_number_start; }
        uint16_t int_file_attr() const { return m_int_file_attr; }
        uint32_t ext_file_attr() const { return m_ext_file_attr; }
        int32_t ofs_local_header() const { return m_ofs_local_header; }
        std::string file_name() const { return m_file_name; }
        extras_t* extra() const { return m_extra; }
        std::string comment() const { return m_comment; }
        zip_t* _root() const { return m__root; }
        zip_t::pk_section_t* _parent() const { return m__parent; }
        std::string _raw_extra() const { return m__raw_extra; }
        kaitai::kstream* _io__raw_extra() const { return m__io__raw_extra; }
    };

    class pk_section_t : public kaitai::kstruct {

    public:

        pk_section_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, zip_t* p__root = 0);

    private:
        void _read();

    public:
        ~pk_section_t();

    private:
        std::string m_magic;
        uint16_t m_section_type;
        kaitai::kstruct* m_body;
        bool n_body;

    public:
        bool _is_null_body() { body(); return n_body; };

    private:
        zip_t* m__root;
        kaitai::kstruct* m__parent;

    public:
        std::string magic() const { return m_magic; }
        uint16_t section_type() const { return m_section_type; }
        kaitai::kstruct* body() const { return m_body; }
        zip_t* _root() const { return m__root; }
        kaitai::kstruct* _parent() const { return m__parent; }
    };

    class extras_t : public kaitai::kstruct {

    public:

        extras_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, zip_t* p__root = 0);

    private:
        void _read();

    public:
        ~extras_t();

    private:
        std::vector<extra_field_t*>* m_entries;
        zip_t* m__root;
        kaitai::kstruct* m__parent;

    public:
        std::vector<extra_field_t*>* entries() const { return m_entries; }
        zip_t* _root() const { return m__root; }
        kaitai::kstruct* _parent() const { return m__parent; }
    };

    class local_file_header_t : public kaitai::kstruct {

    public:

        local_file_header_t(kaitai::kstream* p__io, zip_t::local_file_t* p__parent = 0, zip_t* p__root = 0);

    private:
        void _read();

    public:
        ~local_file_header_t();

    private:
        uint16_t m_version;
        uint16_t m_flags;
        compression_t m_compression_method;
        uint16_t m_file_mod_time;
        uint16_t m_file_mod_date;
        uint32_t m_crc32;
        uint32_t m_len_body_compressed;
        uint32_t m_len_body_uncompressed;
        uint16_t m_len_file_name;
        uint16_t m_len_extra;
        std::string m_file_name;
        extras_t* m_extra;
        zip_t* m__root;
        zip_t::local_file_t* m__parent;
        std::string m__raw_extra;
        kaitai::kstream* m__io__raw_extra;

    public:
        uint16_t version() const { return m_version; }
        uint16_t flags() const { return m_flags; }
        compression_t compression_method() const { return m_compression_method; }
        uint16_t file_mod_time() const { return m_file_mod_time; }
        uint16_t file_mod_date() const { return m_file_mod_date; }
        uint32_t crc32() const { return m_crc32; }
        uint32_t len_body_compressed() const { return m_len_body_compressed; }
        uint32_t len_body_uncompressed() const { return m_len_body_uncompressed; }
        uint16_t len_file_name() const { return m_len_file_name; }
        uint16_t len_extra() const { return m_len_extra; }
        std::string file_name() const { return m_file_name; }
        extras_t* extra() const { return m_extra; }
        zip_t* _root() const { return m__root; }
        zip_t::local_file_t* _parent() const { return m__parent; }
        std::string _raw_extra() const { return m__raw_extra; }
        kaitai::kstream* _io__raw_extra() const { return m__io__raw_extra; }
    };

    class end_of_central_dir_t : public kaitai::kstruct {

    public:

        end_of_central_dir_t(kaitai::kstream* p__io, zip_t::pk_section_t* p__parent = 0, zip_t* p__root = 0);

    private:
        void _read();

    public:
        ~end_of_central_dir_t();

    private:
        uint16_t m_disk_of_end_of_central_dir;
        uint16_t m_disk_of_central_dir;
        uint16_t m_num_central_dir_entries_on_disk;
        uint16_t m_num_central_dir_entries_total;
        uint32_t m_len_central_dir;
        uint32_t m_ofs_central_dir;
        uint16_t m_len_comment;
        std::string m_comment;
        zip_t* m__root;
        zip_t::pk_section_t* m__parent;

    public:
        uint16_t disk_of_end_of_central_dir() const { return m_disk_of_end_of_central_dir; }
        uint16_t disk_of_central_dir() const { return m_disk_of_central_dir; }
        uint16_t num_central_dir_entries_on_disk() const { return m_num_central_dir_entries_on_disk; }
        uint16_t num_central_dir_entries_total() const { return m_num_central_dir_entries_total; }
        uint32_t len_central_dir() const { return m_len_central_dir; }
        uint32_t ofs_central_dir() const { return m_ofs_central_dir; }
        uint16_t len_comment() const { return m_len_comment; }
        std::string comment() const { return m_comment; }
        zip_t* _root() const { return m__root; }
        zip_t::pk_section_t* _parent() const { return m__parent; }
    };

private:
    std::vector<pk_section_t*>* m_sections;
    zip_t* m__root;
    kaitai::kstruct* m__parent;

public:
    std::vector<pk_section_t*>* sections() const { return m_sections; }
    zip_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
};

#endif  // ZIP_H_

zip.cpp

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "zip.h"



zip_t::zip_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = this;
    _read();
}

void zip_t::_read() {
    m_sections = new std::vector<pk_section_t*>();
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_sections->push_back(new pk_section_t(m__io, this, m__root));
            i++;
        }
    }
}

zip_t::~zip_t() {
    for (std::vector<pk_section_t*>::iterator it = m_sections->begin(); it != m_sections->end(); ++it) {
        delete *it;
    }
    delete m_sections;
}

zip_t::local_file_t::local_file_t(kaitai::kstream* p__io, zip_t::pk_section_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::local_file_t::_read() {
    m_header = new local_file_header_t(m__io, this, m__root);
    m_body = m__io->read_bytes(header()->len_body_compressed());
}

zip_t::local_file_t::~local_file_t() {
    delete m_header;
}

zip_t::data_descriptor_t::data_descriptor_t(kaitai::kstream* p__io, zip_t::pk_section_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::data_descriptor_t::_read() {
    m_crc32 = m__io->read_u4le();
    m_len_body_compressed = m__io->read_u4le();
    m_len_body_uncompressed = m__io->read_u4le();
}

zip_t::data_descriptor_t::~data_descriptor_t() {
}

zip_t::extra_field_t::extra_field_t(kaitai::kstream* p__io, zip_t::extras_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::extra_field_t::_read() {
    m_code = static_cast<zip_t::extra_codes_t>(m__io->read_u2le());
    m_len_body = m__io->read_u2le();
    n_body = true;
    switch (code()) {
    case EXTRA_CODES_NTFS: {
        n_body = false;
        m__raw_body = m__io->read_bytes(len_body());
        m__io__raw_body = new kaitai::kstream(m__raw_body);
        m_body = new ntfs_t(m__io__raw_body, this, m__root);
        break;
    }
    case EXTRA_CODES_EXTENDED_TIMESTAMP: {
        n_body = false;
        m__raw_body = m__io->read_bytes(len_body());
        m__io__raw_body = new kaitai::kstream(m__raw_body);
        m_body = new extended_timestamp_t(m__io__raw_body, this, m__root);
        break;
    }
    case EXTRA_CODES_INFOZIP_UNIX_VAR_SIZE: {
        n_body = false;
        m__raw_body = m__io->read_bytes(len_body());
        m__io__raw_body = new kaitai::kstream(m__raw_body);
        m_body = new infozip_unix_var_size_t(m__io__raw_body, this, m__root);
        break;
    }
    default: {
        m__raw_body = m__io->read_bytes(len_body());
        break;
    }
    }
}

zip_t::extra_field_t::~extra_field_t() {
    if (!n_body) {
        delete m__io__raw_body;
        delete m_body;
    }
}

zip_t::extra_field_t::ntfs_t::ntfs_t(kaitai::kstream* p__io, zip_t::extra_field_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::extra_field_t::ntfs_t::_read() {
    m_reserved = m__io->read_u4le();
    m_attributes = new std::vector<attribute_t*>();
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_attributes->push_back(new attribute_t(m__io, this, m__root));
            i++;
        }
    }
}

zip_t::extra_field_t::ntfs_t::~ntfs_t() {
    for (std::vector<attribute_t*>::iterator it = m_attributes->begin(); it != m_attributes->end(); ++it) {
        delete *it;
    }
    delete m_attributes;
}

zip_t::extra_field_t::ntfs_t::attribute_t::attribute_t(kaitai::kstream* p__io, zip_t::extra_field_t::ntfs_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::extra_field_t::ntfs_t::attribute_t::_read() {
    m_tag = m__io->read_u2le();
    m_len_body = m__io->read_u2le();
    n_body = true;
    switch (tag()) {
    case 1: {
        n_body = false;
        m__raw_body = m__io->read_bytes(len_body());
        m__io__raw_body = new kaitai::kstream(m__raw_body);
        m_body = new attribute_1_t(m__io__raw_body, this, m__root);
        break;
    }
    default: {
        m__raw_body = m__io->read_bytes(len_body());
        break;
    }
    }
}

zip_t::extra_field_t::ntfs_t::attribute_t::~attribute_t() {
    if (!n_body) {
        delete m__io__raw_body;
        delete m_body;
    }
}

zip_t::extra_field_t::ntfs_t::attribute_1_t::attribute_1_t(kaitai::kstream* p__io, zip_t::extra_field_t::ntfs_t::attribute_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::extra_field_t::ntfs_t::attribute_1_t::_read() {
    m_last_mod_time = m__io->read_u8le();
    m_last_access_time = m__io->read_u8le();
    m_creation_time = m__io->read_u8le();
}

zip_t::extra_field_t::ntfs_t::attribute_1_t::~attribute_1_t() {
}

zip_t::extra_field_t::extended_timestamp_t::extended_timestamp_t(kaitai::kstream* p__io, zip_t::extra_field_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::extra_field_t::extended_timestamp_t::_read() {
    m_flags = m__io->read_u1();
    m_mod_time = m__io->read_u4le();
    n_access_time = true;
    if (!(_io()->is_eof())) {
        n_access_time = false;
        m_access_time = m__io->read_u4le();
    }
    n_create_time = true;
    if (!(_io()->is_eof())) {
        n_create_time = false;
        m_create_time = m__io->read_u4le();
    }
}

zip_t::extra_field_t::extended_timestamp_t::~extended_timestamp_t() {
    if (!n_access_time) {
    }
    if (!n_create_time) {
    }
}

zip_t::extra_field_t::infozip_unix_var_size_t::infozip_unix_var_size_t(kaitai::kstream* p__io, zip_t::extra_field_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::extra_field_t::infozip_unix_var_size_t::_read() {
    m_version = m__io->read_u1();
    m_len_uid = m__io->read_u1();
    m_uid = m__io->read_bytes(len_uid());
    m_len_gid = m__io->read_u1();
    m_gid = m__io->read_bytes(len_gid());
}

zip_t::extra_field_t::infozip_unix_var_size_t::~infozip_unix_var_size_t() {
}

zip_t::central_dir_entry_t::central_dir_entry_t(kaitai::kstream* p__io, zip_t::pk_section_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_local_header = false;
    _read();
}

void zip_t::central_dir_entry_t::_read() {
    m_version_made_by = m__io->read_u2le();
    m_version_needed_to_extract = m__io->read_u2le();
    m_flags = m__io->read_u2le();
    m_compression_method = static_cast<zip_t::compression_t>(m__io->read_u2le());
    m_last_mod_file_time = m__io->read_u2le();
    m_last_mod_file_date = m__io->read_u2le();
    m_crc32 = m__io->read_u4le();
    m_len_body_compressed = m__io->read_u4le();
    m_len_body_uncompressed = m__io->read_u4le();
    m_len_file_name = m__io->read_u2le();
    m_len_extra = m__io->read_u2le();
    m_len_comment = m__io->read_u2le();
    m_disk_number_start = m__io->read_u2le();
    m_int_file_attr = m__io->read_u2le();
    m_ext_file_attr = m__io->read_u4le();
    m_ofs_local_header = m__io->read_s4le();
    m_file_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_file_name()), std::string("UTF-8"));
    m__raw_extra = m__io->read_bytes(len_extra());
    m__io__raw_extra = new kaitai::kstream(m__raw_extra);
    m_extra = new extras_t(m__io__raw_extra, this, m__root);
    m_comment = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_comment()), std::string("UTF-8"));
}

zip_t::central_dir_entry_t::~central_dir_entry_t() {
    delete m__io__raw_extra;
    delete m_extra;
    if (f_local_header) {
        delete m_local_header;
    }
}

zip_t::pk_section_t* zip_t::central_dir_entry_t::local_header() {
    if (f_local_header)
        return m_local_header;
    std::streampos _pos = m__io->pos();
    m__io->seek(ofs_local_header());
    m_local_header = new pk_section_t(m__io, this, m__root);
    m__io->seek(_pos);
    f_local_header = true;
    return m_local_header;
}

zip_t::pk_section_t::pk_section_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::pk_section_t::_read() {
    m_magic = m__io->ensure_fixed_contents(std::string("\x50\x4B", 2));
    m_section_type = m__io->read_u2le();
    n_body = true;
    switch (section_type()) {
    case 513: {
        n_body = false;
        m_body = new central_dir_entry_t(m__io, this, m__root);
        break;
    }
    case 1027: {
        n_body = false;
        m_body = new local_file_t(m__io, this, m__root);
        break;
    }
    case 1541: {
        n_body = false;
        m_body = new end_of_central_dir_t(m__io, this, m__root);
        break;
    }
    case 2055: {
        n_body = false;
        m_body = new data_descriptor_t(m__io, this, m__root);
        break;
    }
    }
}

zip_t::pk_section_t::~pk_section_t() {
    if (!n_body) {
        delete m_body;
    }
}

zip_t::extras_t::extras_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::extras_t::_read() {
    m_entries = new std::vector<extra_field_t*>();
    {
        int i = 0;
        while (!m__io->is_eof()) {
            m_entries->push_back(new extra_field_t(m__io, this, m__root));
            i++;
        }
    }
}

zip_t::extras_t::~extras_t() {
    for (std::vector<extra_field_t*>::iterator it = m_entries->begin(); it != m_entries->end(); ++it) {
        delete *it;
    }
    delete m_entries;
}

zip_t::local_file_header_t::local_file_header_t(kaitai::kstream* p__io, zip_t::local_file_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::local_file_header_t::_read() {
    m_version = m__io->read_u2le();
    m_flags = m__io->read_u2le();
    m_compression_method = static_cast<zip_t::compression_t>(m__io->read_u2le());
    m_file_mod_time = m__io->read_u2le();
    m_file_mod_date = m__io->read_u2le();
    m_crc32 = m__io->read_u4le();
    m_len_body_compressed = m__io->read_u4le();
    m_len_body_uncompressed = m__io->read_u4le();
    m_len_file_name = m__io->read_u2le();
    m_len_extra = m__io->read_u2le();
    m_file_name = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_file_name()), std::string("UTF-8"));
    m__raw_extra = m__io->read_bytes(len_extra());
    m__io__raw_extra = new kaitai::kstream(m__raw_extra);
    m_extra = new extras_t(m__io__raw_extra, this, m__root);
}

zip_t::local_file_header_t::~local_file_header_t() {
    delete m__io__raw_extra;
    delete m_extra;
}

zip_t::end_of_central_dir_t::end_of_central_dir_t(kaitai::kstream* p__io, zip_t::pk_section_t* p__parent, zip_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void zip_t::end_of_central_dir_t::_read() {
    m_disk_of_end_of_central_dir = m__io->read_u2le();
    m_disk_of_central_dir = m__io->read_u2le();
    m_num_central_dir_entries_on_disk = m__io->read_u2le();
    m_num_central_dir_entries_total = m__io->read_u2le();
    m_len_central_dir = m__io->read_u4le();
    m_ofs_central_dir = m__io->read_u4le();
    m_len_comment = m__io->read_u2le();
    m_comment = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_comment()), std::string("UTF-8"));
}

zip_t::end_of_central_dir_t::~end_of_central_dir_t() {
}