#ifndef ZIPFILE_H #define ZIPFILE_H #include extern "C" { #include "zipcrc.h" } #include #pragma pack(push,1) struct ZIPLocalFileHeader { /* ZIP File Format Specification v6.3.4 sec 4.3.7 Local file header */ uint32_t local_file_header_signature; /* +0x00 0x04034b50 */ uint16_t version_needed_to_extract; /* +0x04 */ uint16_t general_purpose_bit_flag; /* +0x06 */ uint16_t compression_method; /* +0x08 */ uint16_t last_mod_file_time; /* +0x0A */ uint16_t last_mod_file_date; /* +0x0C */ uint32_t crc_32; /* +0x0E */ uint32_t compressed_size; /* +0x12 */ uint32_t uncompressed_size; /* +0x16 */ uint16_t file_name_length; /* +0x1A */ uint16_t extra_field_length; /* +0x1C */ }; /* =0x1E */ #pragma pack(pop) #pragma pack(push,1) # define PKZIP_CENTRAL_DIRECTORY_HEADER_SIG (0x02014B50UL) struct pkzip_central_directory_header_main { /* PKZIP APPNOTE 2.0: General Format of a ZIP file section C */ uint32_t sig; /* 4 bytes +0x00 0x02014B50 = 'PK\x01\x02' */ uint16_t version_made_by; /* 2 bytes +0x04 version made by */ uint16_t version_needed_to_extract; /* 2 bytes +0x06 version needed to extract */ uint16_t general_purpose_bit_flag; /* 2 bytes +0x08 general purpose bit flag */ uint16_t compression_method; /* 2 bytes +0x0A compression method */ uint16_t last_mod_file_time; /* 2 bytes +0x0C */ uint16_t last_mod_file_date; /* 2 bytes +0x0E */ uint32_t crc32; /* 4 bytes +0x10 */ uint32_t compressed_size; /* 4 bytes +0x14 */ uint32_t uncompressed_size; /* 4 bytes +0x18 */ uint16_t filename_length; /* 2 bytes +0x1C */ uint16_t extra_field_length; /* 2 bytes +0x1E */ uint16_t file_comment_length; /* 2 bytes +0x20 */ uint16_t disk_number_start; /* 2 bytes +0x22 */ uint16_t internal_file_attributes; /* 2 bytes +0x24 */ uint32_t external_file_attributes; /* 4 bytes +0x26 */ uint32_t relative_offset_of_local_header;/* 4 bytes +0x2A */ }; /* =0x2E */ /* filename and extra field follow, then file data */ #pragma pack(pop) #pragma pack(push,1) # define PKZIP_CENTRAL_DIRECTORY_END_SIG (0x06054B50UL) struct pkzip_central_directory_header_end { /* PKZIP APPNOTE 2.0: General Format of a ZIP file section C */ uint32_t sig; /* 4 bytes +0x00 0x06054B50 = 'PK\x05\x06' */ uint16_t number_of_this_disk; /* 2 bytes +0x04 */ uint16_t number_of_disk_with_start_of_central_directory; /* 2 bytes +0x06 */ uint16_t total_number_of_entries_of_central_dir_on_this_disk; /* 2 bytes +0x08 */ uint16_t total_number_of_entries_of_central_dir; /* 2 bytes +0x0A */ uint32_t size_of_central_directory; /* 4 bytes +0x0C */ uint32_t offset_of_central_directory_from_start_disk; /* 4 bytes +0x10 */ uint16_t zipfile_comment_length; /* 2 bytes +0x14 */ }; /* =0x16 */ /* filename and extra field follow, then file data */ #pragma pack(pop) class ZIPFile; class ZIPFileEntry { public: bool can_write = false; off_t file_length = 0; off_t file_offset = 0; off_t file_header_offset = 0; off_t position = 0; std::string name; ZIPFile* file = NULL; zipcrc_t write_crc = 0; public: bool rewind(void); int read(void *buffer,size_t count); int write(const void *buffer,size_t count); private: /* encourage code that uses this C++ class to stream-read so that this code can add deflate compression support later without pain and hacks */ off_t seek_file(off_t pos); }; class ZIPFile { public: int file_fd = -1; std::string filename; std::map entries; off_t write_pos = 0; bool can_write = false; bool wrote_trailer = false; std::string current_entry; /* currently writing entry */ public: ZIPFile(); ~ZIPFile(); public: void close(void); ZIPFileEntry *get_entry(const char *name); ZIPFileEntry *new_entry(const char *name); off_t end_of_file(void); void close_current(void); int open(const char *path,int mode); off_t seek_file(off_t pos); int read(void *buffer,size_t count); int write(const void *buffer,size_t count); void writeZIPFooter(void); }; class zip_nv_pair_map : public std::map { public: zip_nv_pair_map(); zip_nv_pair_map(ZIPFileEntry &ent); public: std::string &get(const char *name); bool get_bool(const char *name); long get_long(const char *name); unsigned long get_ulong(const char *name); void process_line(char *line/*will modify, assume caller has put NUL at the end*/); void read_nv_pairs(ZIPFileEntry &ent); }; void zip_nv_write(ZIPFileEntry &ent,const char *name,bool val); void zip_nv_write(ZIPFileEntry &ent,const char *name,long val); void zip_nv_write_hex(ZIPFileEntry &ent,const char *name,unsigned long val); #endif //ZIPFILE_H