comparison mupdf-source/thirdparty/extract/src/zip-test.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /* Crude programme to show detailed information about a zip file. */
2
3 #include "memento.h"
4 #include "outf.h"
5
6 #include <assert.h>
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12
13 static int s_native_little_endinesss(void)
14 {
15 static const char a[] = { 1, 2};
16 uint16_t b = *(uint16_t*) a;
17 if (b == 1 + 2*256) {
18 /* Native little-endiness. */
19 return 1;
20 }
21 else if (b == 2 + 1*256) {
22 return 0;
23 }
24 abort();
25 }
26
27
28 static int s_show(const char* filename)
29 {
30 outf("Looking at filename=%s", filename);
31 assert(s_native_little_endinesss());
32 FILE* f = fopen(filename, "r");
33 assert(f);
34 size_t datasize = 10*1000*1000;
35 char* data = extract_malloc(datasize);
36 assert(data);
37 size_t n = fread(data, 1, datasize, f);
38 assert(n < datasize);
39 datasize = n;
40 outf("datasize=%zi", datasize);
41 fclose(f);
42
43 /* look for End of central directory (EOCD) record. */
44 uint32_t magic = 0x06054b50;
45 char* pos = data + datasize - 22;
46 for(;;) {
47 if (!memcmp(pos, &magic, sizeof(magic))) break;
48 assert(pos > data);
49 pos -= 1;
50 }
51 outf("found EOCD at offset=%li", pos-data);
52 uint16_t disk_number = *(uint16_t*)(pos+4);
53 uint16_t disk_cd = *(uint16_t*)(pos+6);
54 uint16_t num_records_on_disk = *(uint16_t*)(pos+8);
55 uint16_t num_records = *(uint16_t*)(pos+10);
56 uint32_t size_cd = *(uint32_t*)(pos+12);
57 uint32_t offset_cd = *(uint32_t*)(pos+16);
58 uint16_t comment_length = *(uint16_t*)(pos+20);
59 char* comment = extract_malloc(comment_length + 1);
60 assert(comment);
61 memcpy(comment, pos+22, comment_length);
62 comment[comment_length] = 0;
63 assert(strlen(comment) == comment_length);
64 outf(" EOCD:");
65 outf(" disk_number=%i", disk_number);
66 outf(" disk_cd=%i", disk_cd);
67 outf(" num_records_on_disk=%i", num_records_on_disk);
68 outf(" num_records=%i", num_records);
69 outf(" size_cd=%i", size_cd);
70 outf(" offset_cd=%i", offset_cd);
71 outf(" comment_length=%i", comment_length);
72 outf(" comment=%s", comment);
73
74 if (pos != data + datasize - 22 - comment_length) {
75 outf("file does not end with EOCD. datasize=%zi pos-data=%li datasize-22-comment_length=%zi",
76 datasize,
77 pos-data,
78 datasize-22-comment_length
79 );
80 /* I think this isn't actually an error according to the Zip standard,
81 but zip files created by us should always pass this test. Note that
82 Word doesn't like trailing data after the EOCD record, but will repair
83 the file. */
84 assert(0);
85 }
86
87 pos = data + offset_cd;
88 int i;
89 for (i=0; i<num_records_on_disk; ++i) {
90 outf(" file %i: offset=%i", i, pos - data);
91 magic = 0x02014b50;
92 assert(!memcmp(pos, &magic, sizeof(magic)));
93 uint16_t version_made_by = *(uint16_t*)(pos+4);
94 uint16_t version_needed = *(uint16_t*)(pos+6);
95 uint16_t general_bit_flag = *(uint16_t*)(pos+8);
96 uint16_t compression_method = *(uint16_t*)(pos+10);
97 uint16_t mtime = *(uint16_t*)(pos+12);
98 uint16_t mdate = *(uint16_t*)(pos+14);
99 uint32_t crc = *(uint32_t*)(pos+16);
100 uint32_t size_compressed = *(uint32_t*)(pos+20);
101 uint32_t size_uncompressed = *(uint32_t*)(pos+24);
102 uint16_t filename_length = *(uint16_t*)(pos+28);
103 uint16_t extrafield_length = *(uint16_t*)(pos+30);
104 uint16_t filecomment_length = *(uint16_t*)(pos+32);
105 uint16_t disk_number = *(uint16_t*)(pos+34);
106 uint16_t internal_attributes = *(uint16_t*)(pos+36);
107 uint32_t external_attributes = *(uint32_t*)(pos+38);
108 uint32_t offset = *(uint32_t*)(pos+42);
109 char* filename = extract_malloc(filename_length + 1);
110 assert(filename);
111 memcpy(filename, pos+46, filename_length);
112 filename[filename_length] = 0;
113
114 char* comment = extract_malloc(filecomment_length + 1);
115 assert(comment);
116 memcpy(comment, pos+46+filename_length+extrafield_length, filecomment_length);
117 comment[filecomment_length] = 0;
118 assert(strlen(comment) == filecomment_length);
119 outf(" version_made_by=0x%x", version_made_by);
120 outf(" version_needed=0x%x", version_needed);
121 outf(" general_bit_flag=0x%x", general_bit_flag);
122 outf(" compression_method=%i", compression_method);
123 outf(" mtime=%i", mtime);
124 outf(" mdate=%i", mdate);
125 outf(" crc=%i", crc);
126 outf(" size_compressed=%i", size_compressed);
127 outf(" size_uncompressed=%i", size_uncompressed);
128 outf(" filename_length=%i", filename_length);
129 outf(" extrafield_length=%i", extrafield_length);
130 outf(" filecomment_length=%i", filecomment_length);
131 outf(" disk_number=%i", disk_number);
132 outf(" internal_attributes=0x%x", internal_attributes);
133 outf(" external_attributes=0x%x", external_attributes);
134 outf(" offset=%i", offset);
135 outf(" filename=%s", filename);
136
137 if (extrafield_length) {
138 outf( " extra:");
139 fprintf(stderr, " ");
140 char* extra = pos + 46+filename_length;
141 int j;
142 for (j=0; j<extrafield_length; ++j) {
143 unsigned char c = extra[j];
144 if (isprint(c) && c != '\\') fputc(c, stderr);
145 else fprintf(stderr, "\\x%02x", c);
146 }
147 fputc('\n', stderr);
148 }
149
150 /* show local file header. */
151 {
152 char* local_pos = data + offset;
153 outf(" local header offset=%i", i, local_pos - data);
154 magic = 0x04034b50;
155 assert(!memcmp(local_pos, &magic, sizeof(magic)));
156
157 uint16_t version_needed = *(uint16_t*)(local_pos+4);
158 uint16_t general_bit_flag = *(uint16_t*)(local_pos+6);
159 uint16_t compression_method = *(uint16_t*)(local_pos+8);
160 uint16_t mtime = *(uint16_t*)(local_pos+10);
161 uint16_t mdate = *(uint16_t*)(local_pos+12);
162 uint32_t crc = *(uint32_t*)(local_pos+14);
163 uint32_t size_compressed = *(uint32_t*)(local_pos+18);
164 uint32_t size_uncompressed = *(uint32_t*)(local_pos+22);
165 uint16_t filename_length = *(uint16_t*)(local_pos+26);
166 uint16_t extrafield_length = *(uint16_t*)(local_pos+28);
167
168 char* filename = extract_malloc(filename_length + 1);
169 assert(filename);
170 memcpy(filename, local_pos+30, filename_length);
171 filename[filename_length] = 0;
172
173 outf(" version_needed=0x%x", version_needed);
174 outf(" general_bit_flag=0x%x", general_bit_flag);
175 outf(" compression_method=%i", compression_method);
176 outf(" mtime=%i", mtime);
177 outf(" mdate=%i", mdate);
178 outf(" crc=%i", crc);
179 outf(" size_compressed=%i", size_compressed);
180 outf(" size_uncompressed=%i", size_uncompressed);
181 outf(" filename_length=%i", filename_length);
182 outf(" extrafield_length=%i", extrafield_length);
183 outf(" filecomment_length=%i", filecomment_length);
184 outf(" disk_number=%i", disk_number);
185 outf(" internal_attributes=0x%x", internal_attributes);
186 outf(" external_attributes=0x%x", external_attributes);
187 outf(" offset=%i", offset);
188 outf(" filename=%s", filename);
189
190 if (extrafield_length) {
191 outf( " extra:");
192 fprintf(stderr, " ");
193 char* extra = local_pos + 30 + filename_length;
194 int j;
195 for (j=0; j<extrafield_length; ++j) {
196 unsigned char c = extra[j];
197 if (isprint(c) && c != '\\') fputc(c, stderr);
198 else fprintf(stderr, "\\x%02x", c);
199 }
200 fputc('\n', stderr);
201 }
202
203 }
204
205 outf(" comment=%s", comment);
206
207 pos += 46 + filename_length + extrafield_length + filecomment_length;
208 }
209
210 outf("finished");
211 extract_free(&data);
212
213 return 0;
214 }
215
216 int main(int argc, char** argv)
217 {
218 outf_level_set(1);
219 int i;
220 for (i=1; i<argc; ++i) {
221 s_show(argv[i]);
222 }
223 return 0;
224 }