Mercurial > hgrepos > Python2 > PyMuPDF
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 } |
