1 /* Copyright 2015 the unarr project authors (see AUTHORS file).
2    License: LGPLv3 */
3 
4 #ifndef zip_zip_h
5 #define zip_zip_h
6 
7 #include "../common/unarr-imp.h"
8 
9 #ifdef HAVE_ZLIB
10 #include <zlib.h>
11 #endif
12 #include "inflate.h"
13 #ifdef HAVE_BZIP2
14 #include <bzlib.h>
15 #endif
16 #include "../lzmasdk/LzmaDec.h"
17 #include "../lzmasdk/Ppmd8.h"
18 
19 typedef struct ar_archive_zip_s ar_archive_zip;
20 
21 /***** parse-zip *****/
22 
23 enum zip_signatures {
24     SIG_LOCAL_FILE_HEADER = 0x04034B50,
25     SIG_CENTRAL_DIRECTORY = 0x02014B50,
26     SIG_END_OF_CENTRAL_DIRECTORY_64 = 0x06064B50,
27     SIG_END_OF_CENTRAL_DIRECTORY_64_LOCATOR = 0x07064B50,
28     SIG_END_OF_CENTRAL_DIRECTORY = 0x06054B50,
29 };
30 
31 enum compression_method {
32     METHOD_STORE = 0, METHOD_DEFLATE = 8,
33     METHOD_DEFLATE64 = 9, METHOD_BZIP2 = 12, METHOD_LZMA = 14,
34     METHOD_PPMD = 98,
35 };
36 
37 #define ZIP_LOCAL_ENTRY_FIXED_SIZE 30
38 #define ZIP_DIR_ENTRY_FIXED_SIZE 46
39 #define ZIP_END_OF_CENTRAL_DIR_SIZE 22
40 
41 struct zip_entry {
42     uint32_t signature;
43     uint16_t version;
44     uint16_t min_version;
45     uint16_t flags;
46     uint16_t method;
47     uint32_t dosdate;
48     uint32_t crc;
49     uint64_t datasize;
50     uint64_t uncompressed;
51     uint16_t namelen;
52     uint16_t extralen;
53     uint16_t commentlen;
54     uint32_t disk;
55     uint16_t attr_internal;
56     uint32_t attr_external;
57     off64_t header_offset;
58 };
59 
60 struct zip_eocd64 {
61     uint32_t signature;
62     uint16_t version;
63     uint16_t min_version;
64     uint32_t diskno;
65     uint32_t diskno_dir;
66     uint64_t numentries_disk;
67     uint64_t numentries;
68     uint64_t dir_size;
69     off64_t dir_offset;
70     uint16_t commentlen;
71 };
72 
73 struct ar_archive_zip_entry {
74     off64_t offset;
75     uint16_t method;
76     uint16_t flags;
77     uint32_t crc;
78     char *name;
79     uint32_t dosdate;
80 };
81 
82 bool zip_seek_to_compressed_data(ar_archive_zip *zip);
83 bool zip_parse_local_file_entry(ar_archive_zip *zip, struct zip_entry *entry);
84 off64_t zip_find_next_local_file_entry(ar_stream *stream, off64_t offset);
85 bool zip_parse_directory_entry(ar_archive_zip *zip, struct zip_entry *entry);
86 off64_t zip_find_end_of_last_directory_entry(ar_stream *stream, struct zip_eocd64 *eocd);
87 bool zip_parse_end_of_central_directory(ar_stream *stream, struct zip_eocd64 *eocd);
88 off64_t zip_find_end_of_central_directory(ar_stream *stream);
89 const char *zip_get_name(ar_archive *ar);
90 
91 /***** uncompress-zip *****/
92 
93 struct ar_archive_zip_uncomp;
94 
95 typedef uint32_t (* zip_uncomp_uncompress_data_fn)(struct ar_archive_zip_uncomp *uncomp, void *buffer, uint32_t buffer_size, bool is_last_chunk);
96 typedef void (* zip_uncomp_clear_state_fn)(struct ar_archive_zip_uncomp *uncomp);
97 
98 struct InputBuffer {
99     uint8_t data[4096];
100     uint16_t offset;
101     uint16_t bytes_left;
102     bool at_eof;
103 };
104 
105 struct ByteReader {
106     IByteIn super;
107     struct InputBuffer *input;
108     ar_archive_zip *zip;
109 };
110 
111 struct ar_archive_zip_uncomp {
112     bool initialized;
113     zip_uncomp_uncompress_data_fn uncompress_data;
114     zip_uncomp_clear_state_fn clear_state;
115     union {
116 #ifdef HAVE_ZLIB
117         z_stream zstream;
118 #endif
119         inflate_state *inflate;
120 #ifdef HAVE_BZIP2
121         bz_stream bstream;
122 #endif
123         struct {
124             CLzmaDec dec;
125             ELzmaFinishMode finish;
126             ISzAlloc alloc;
127         } lzma;
128         struct {
129             CPpmd8 ctx;
130             struct ByteReader bytein;
131             ISzAlloc alloc;
132         } ppmd8;
133     } state;
134     struct InputBuffer input;
135 };
136 
137 bool zip_uncompress_part(ar_archive_zip *zip, void *buffer, size_t buffer_size);
138 void zip_clear_uncompress(struct ar_archive_zip_uncomp *uncomp);
139 
140 /***** zip *****/
141 
142 struct ar_archive_zip_dir {
143     /* off64_t offset; // use ar_archive::entry_offset_first */
144     off64_t end_offset;
145 };
146 
147 struct ar_archive_zip_progress {
148     size_t data_left;
149     size_t bytes_done;
150     uint32_t crc;
151 };
152 
153 struct ar_archive_zip_s {
154     ar_archive super;
155     struct ar_archive_zip_dir dir;
156     struct ar_archive_zip_entry entry;
157     struct ar_archive_zip_uncomp uncomp;
158     struct ar_archive_zip_progress progress;
159     bool deflatedonly;
160     off64_t comment_offset;
161     uint16_t comment_size;
162 };
163 
164 #endif
165