DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
include/zipfile.h
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