comparison mupdf-source/source/fitz/zip.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 // Copyright (C) 2004-2021 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24
25 #include <string.h>
26
27 #include <zlib.h>
28
29 #if !defined (INT32_MAX)
30 #define INT32_MAX 2147483647L
31 #endif
32
33 #define ZIP_LOCAL_FILE_SIG 0x04034b50
34 #define ZIP_CENTRAL_DIRECTORY_SIG 0x02014b50
35 #define ZIP_END_OF_CENTRAL_DIRECTORY_SIG 0x06054b50
36
37 struct fz_zip_writer
38 {
39 fz_output *output;
40 fz_buffer *central;
41 int count;
42 int closed;
43 };
44
45 void
46 fz_write_zip_entry(fz_context *ctx, fz_zip_writer *zip, const char *name, fz_buffer *buf, int compress)
47 {
48 int offset = fz_tell_output(ctx, zip->output);
49 int sum;
50
51 sum = crc32(0, NULL, 0);
52 sum = crc32(sum, buf->data, (uInt)buf->len);
53
54 /* bit 11 of general purpose bit flag indicates UTF-8. */
55 fz_append_int32_le(ctx, zip->central, ZIP_CENTRAL_DIRECTORY_SIG);
56 fz_append_int16_le(ctx, zip->central, 0); /* version made by: MS-DOS */
57 fz_append_int16_le(ctx, zip->central, 20); /* version to extract: 2.0 */
58 fz_append_int16_le(ctx, zip->central, 1<<11); /* general purpose bit flag */
59 fz_append_int16_le(ctx, zip->central, 0); /* compression method: store */
60 fz_append_int16_le(ctx, zip->central, 0); /* TODO: last mod file time */
61 fz_append_int16_le(ctx, zip->central, 0); /* TODO: last mod file date */
62 fz_append_int32_le(ctx, zip->central, sum); /* crc-32 */
63 fz_append_int32_le(ctx, zip->central, (int)buf->len); /* csize */
64 fz_append_int32_le(ctx, zip->central, (int)buf->len); /* usize */
65 fz_append_int16_le(ctx, zip->central, (int)strlen(name)); /* file name length */
66 fz_append_int16_le(ctx, zip->central, 0); /* extra field length */
67 fz_append_int16_le(ctx, zip->central, 0); /* file comment length */
68 fz_append_int16_le(ctx, zip->central, 0); /* disk number start */
69 fz_append_int16_le(ctx, zip->central, 0); /* internal file attributes */
70 fz_append_int32_le(ctx, zip->central, 0); /* external file attributes */
71 fz_append_int32_le(ctx, zip->central, offset); /* relative offset of local header */
72 fz_append_string(ctx, zip->central, name);
73
74 fz_write_int32_le(ctx, zip->output, ZIP_LOCAL_FILE_SIG);
75 fz_write_int16_le(ctx, zip->output, 20); /* version to extract: 2.0 */
76 fz_write_int16_le(ctx, zip->output, 1<<11); /* general purpose bit flag */
77 fz_write_int16_le(ctx, zip->output, 0); /* compression method: store */
78 fz_write_int16_le(ctx, zip->output, 0); /* TODO: last mod file time */
79 fz_write_int16_le(ctx, zip->output, 0); /* TODO: last mod file date */
80 fz_write_int32_le(ctx, zip->output, sum); /* crc-32 */
81 fz_write_int32_le(ctx, zip->output, (int)buf->len); /* csize */
82 fz_write_int32_le(ctx, zip->output, (int)buf->len); /* usize */
83 fz_write_int16_le(ctx, zip->output, (int)strlen(name)); /* file name length */
84 fz_write_int16_le(ctx, zip->output, 0); /* extra field length */
85 fz_write_data(ctx, zip->output, name, strlen(name));
86 fz_write_data(ctx, zip->output, buf->data, buf->len);
87
88 ++zip->count;
89 }
90
91 void
92 fz_close_zip_writer(fz_context *ctx, fz_zip_writer *zip)
93 {
94 int64_t offset = fz_tell_output(ctx, zip->output);
95
96 fz_write_data(ctx, zip->output, zip->central->data, zip->central->len);
97
98 fz_write_int32_le(ctx, zip->output, ZIP_END_OF_CENTRAL_DIRECTORY_SIG);
99 fz_write_int16_le(ctx, zip->output, 0); /* number of this disk */
100 fz_write_int16_le(ctx, zip->output, 0); /* number of disk where central directory starts */
101 fz_write_int16_le(ctx, zip->output, zip->count); /* entries in central directory in this disk */
102 fz_write_int16_le(ctx, zip->output, zip->count); /* entries in central directory in total */
103 fz_write_int32_le(ctx, zip->output, (int)zip->central->len); /* size of the central directory */
104 fz_write_int32_le(ctx, zip->output, (int)offset); /* offset of the central directory */
105 fz_write_int16_le(ctx, zip->output, 5); /* zip file comment length */
106
107 fz_write_data(ctx, zip->output, "MuPDF", 5);
108
109 fz_close_output(ctx, zip->output);
110
111 zip->closed = 1;
112 }
113
114 void
115 fz_drop_zip_writer(fz_context *ctx, fz_zip_writer *zip)
116 {
117 if (!zip)
118 return;
119 if (!zip->closed)
120 fz_warn(ctx, "dropping unclosed zip writer");
121 fz_drop_output(ctx, zip->output);
122 fz_drop_buffer(ctx, zip->central);
123 fz_free(ctx, zip);
124 }
125
126 fz_zip_writer *
127 fz_new_zip_writer_with_output(fz_context *ctx, fz_output *out)
128 {
129 fz_zip_writer *zip = NULL;
130
131 fz_var(zip);
132
133 fz_try(ctx)
134 {
135 zip = fz_malloc_struct(ctx, fz_zip_writer);
136 zip->output = out;
137 zip->central = fz_new_buffer(ctx, 0);
138 }
139 fz_catch(ctx)
140 {
141 fz_drop_output(ctx, out);
142 if (zip)
143 fz_drop_buffer(ctx, zip->central);
144 fz_free(ctx, zip);
145 fz_rethrow(ctx);
146 }
147 return zip;
148 }
149
150 fz_zip_writer *
151 fz_new_zip_writer(fz_context *ctx, const char *filename)
152 {
153 fz_output *out = fz_new_output_with_path(ctx, filename, 0);
154 fz_zip_writer *zip = NULL;
155 fz_try(ctx)
156 zip = fz_new_zip_writer_with_output(ctx, out);
157 fz_catch(ctx)
158 {
159 fz_drop_output(ctx, out);
160 fz_rethrow(ctx);
161 }
162 return zip;
163 }