DOSBox-X
|
00001 00002 #ifndef ZIPFILE_H 00003 #define ZIPFILE_H 00004 00005 #include <stdint.h> 00006 00007 extern "C" { 00008 #include "zipcrc.h" 00009 } 00010 00011 #include <map> 00012 00013 #pragma pack(push,1) 00014 struct ZIPLocalFileHeader { /* ZIP File Format Specification v6.3.4 sec 4.3.7 Local file header */ 00015 uint32_t local_file_header_signature; /* +0x00 0x04034b50 */ 00016 uint16_t version_needed_to_extract; /* +0x04 */ 00017 uint16_t general_purpose_bit_flag; /* +0x06 */ 00018 uint16_t compression_method; /* +0x08 */ 00019 uint16_t last_mod_file_time; /* +0x0A */ 00020 uint16_t last_mod_file_date; /* +0x0C */ 00021 uint32_t crc_32; /* +0x0E */ 00022 uint32_t compressed_size; /* +0x12 */ 00023 uint32_t uncompressed_size; /* +0x16 */ 00024 uint16_t file_name_length; /* +0x1A */ 00025 uint16_t extra_field_length; /* +0x1C */ 00026 }; /* =0x1E */ 00027 #pragma pack(pop) 00028 00029 #pragma pack(push,1) 00030 # define PKZIP_CENTRAL_DIRECTORY_HEADER_SIG (0x02014B50UL) 00031 00032 struct pkzip_central_directory_header_main { /* PKZIP APPNOTE 2.0: General Format of a ZIP file section C */ 00033 uint32_t sig; /* 4 bytes +0x00 0x02014B50 = 'PK\x01\x02' */ 00034 uint16_t version_made_by; /* 2 bytes +0x04 version made by */ 00035 uint16_t version_needed_to_extract; /* 2 bytes +0x06 version needed to extract */ 00036 uint16_t general_purpose_bit_flag; /* 2 bytes +0x08 general purpose bit flag */ 00037 uint16_t compression_method; /* 2 bytes +0x0A compression method */ 00038 uint16_t last_mod_file_time; /* 2 bytes +0x0C */ 00039 uint16_t last_mod_file_date; /* 2 bytes +0x0E */ 00040 uint32_t crc32; /* 4 bytes +0x10 */ 00041 uint32_t compressed_size; /* 4 bytes +0x14 */ 00042 uint32_t uncompressed_size; /* 4 bytes +0x18 */ 00043 uint16_t filename_length; /* 2 bytes +0x1C */ 00044 uint16_t extra_field_length; /* 2 bytes +0x1E */ 00045 uint16_t file_comment_length; /* 2 bytes +0x20 */ 00046 uint16_t disk_number_start; /* 2 bytes +0x22 */ 00047 uint16_t internal_file_attributes; /* 2 bytes +0x24 */ 00048 uint32_t external_file_attributes; /* 4 bytes +0x26 */ 00049 uint32_t relative_offset_of_local_header;/* 4 bytes +0x2A */ 00050 }; /* =0x2E */ 00051 /* filename and extra field follow, then file data */ 00052 #pragma pack(pop) 00053 00054 #pragma pack(push,1) 00055 # define PKZIP_CENTRAL_DIRECTORY_END_SIG (0x06054B50UL) 00056 00057 struct pkzip_central_directory_header_end { /* PKZIP APPNOTE 2.0: General Format of a ZIP file section C */ 00058 uint32_t sig; /* 4 bytes +0x00 0x06054B50 = 'PK\x05\x06' */ 00059 uint16_t number_of_this_disk; /* 2 bytes +0x04 */ 00060 uint16_t number_of_disk_with_start_of_central_directory; 00061 /* 2 bytes +0x06 */ 00062 uint16_t total_number_of_entries_of_central_dir_on_this_disk; 00063 /* 2 bytes +0x08 */ 00064 uint16_t total_number_of_entries_of_central_dir; 00065 /* 2 bytes +0x0A */ 00066 uint32_t size_of_central_directory; /* 4 bytes +0x0C */ 00067 uint32_t offset_of_central_directory_from_start_disk; 00068 /* 4 bytes +0x10 */ 00069 uint16_t zipfile_comment_length; /* 2 bytes +0x14 */ 00070 }; /* =0x16 */ 00071 /* filename and extra field follow, then file data */ 00072 #pragma pack(pop) 00073 00074 class ZIPFile; 00075 00076 class ZIPFileEntry { 00077 public: 00078 bool can_write = false; 00079 off_t file_length = 0; 00080 off_t file_offset = 0; 00081 off_t file_header_offset = 0; 00082 off_t position = 0; 00083 std::string name; 00084 ZIPFile* file = NULL; 00085 zipcrc_t write_crc = 0; 00086 public: 00087 bool rewind(void); 00088 int read(void *buffer,size_t count); 00089 int write(const void *buffer,size_t count); 00090 private: /* encourage code that uses this C++ class to stream-read so that 00091 this code can add deflate compression support later without pain and hacks */ 00092 off_t seek_file(off_t pos); 00093 }; 00094 00095 class ZIPFile { 00096 public: 00097 int file_fd = -1; 00098 std::string filename; 00099 std::map<std::string,ZIPFileEntry> entries; 00100 off_t write_pos = 0; 00101 bool can_write = false; 00102 bool wrote_trailer = false; 00103 std::string current_entry; /* currently writing entry */ 00104 public: 00105 ZIPFile(); 00106 ~ZIPFile(); 00107 public: 00108 void close(void); 00109 ZIPFileEntry *get_entry(const char *name); 00110 ZIPFileEntry *new_entry(const char *name); 00111 off_t end_of_file(void); 00112 void close_current(void); 00113 int open(const char *path,int mode); 00114 off_t seek_file(off_t pos); 00115 int read(void *buffer,size_t count); 00116 int write(const void *buffer,size_t count); 00117 void writeZIPFooter(void); 00118 }; 00119 00120 class zip_nv_pair_map : public std::map<std::string, std::string> { 00121 public: 00122 zip_nv_pair_map(); 00123 zip_nv_pair_map(ZIPFileEntry &ent); 00124 public: 00125 std::string &get(const char *name); 00126 bool get_bool(const char *name); 00127 long get_long(const char *name); 00128 unsigned long get_ulong(const char *name); 00129 void process_line(char *line/*will modify, assume caller has put NUL at the end*/); 00130 void read_nv_pairs(ZIPFileEntry &ent); 00131 }; 00132 00133 void zip_nv_write(ZIPFileEntry &ent,const char *name,bool val); 00134 void zip_nv_write(ZIPFileEntry &ent,const char *name,long val); 00135 void zip_nv_write_hex(ZIPFileEntry &ent,const char *name,unsigned long val); 00136 #endif //ZIPFILE_H 00137