Coverage Report

Created: 2024-05-20 06:23

/src/mupdf/source/fitz/zip.c
Line
Count
Source (jump to first uncovered line)
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
0
#define ZIP_LOCAL_FILE_SIG 0x04034b50
34
0
#define ZIP_CENTRAL_DIRECTORY_SIG 0x02014b50
35
0
#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
0
{
48
0
  int offset = fz_tell_output(ctx, zip->output);
49
0
  int sum;
50
51
0
  sum = crc32(0, NULL, 0);
52
0
  sum = crc32(sum, buf->data, (uInt)buf->len);
53
54
  /* bit 11 of general purpose bit flag indicates UTF-8. */
55
0
  fz_append_int32_le(ctx, zip->central, ZIP_CENTRAL_DIRECTORY_SIG);
56
0
  fz_append_int16_le(ctx, zip->central, 0); /* version made by: MS-DOS */
57
0
  fz_append_int16_le(ctx, zip->central, 20); /* version to extract: 2.0 */
58
0
  fz_append_int16_le(ctx, zip->central, 1<<11); /* general purpose bit flag */
59
0
  fz_append_int16_le(ctx, zip->central, 0); /* compression method: store */
60
0
  fz_append_int16_le(ctx, zip->central, 0); /* TODO: last mod file time */
61
0
  fz_append_int16_le(ctx, zip->central, 0); /* TODO: last mod file date */
62
0
  fz_append_int32_le(ctx, zip->central, sum); /* crc-32 */
63
0
  fz_append_int32_le(ctx, zip->central, (int)buf->len); /* csize */
64
0
  fz_append_int32_le(ctx, zip->central, (int)buf->len); /* usize */
65
0
  fz_append_int16_le(ctx, zip->central, (int)strlen(name)); /* file name length */
66
0
  fz_append_int16_le(ctx, zip->central, 0); /* extra field length */
67
0
  fz_append_int16_le(ctx, zip->central, 0); /* file comment length */
68
0
  fz_append_int16_le(ctx, zip->central, 0); /* disk number start */
69
0
  fz_append_int16_le(ctx, zip->central, 0); /* internal file attributes */
70
0
  fz_append_int32_le(ctx, zip->central, 0); /* external file attributes */
71
0
  fz_append_int32_le(ctx, zip->central, offset); /* relative offset of local header */
72
0
  fz_append_string(ctx, zip->central, name);
73
74
0
  fz_write_int32_le(ctx, zip->output, ZIP_LOCAL_FILE_SIG);
75
0
  fz_write_int16_le(ctx, zip->output, 20); /* version to extract: 2.0 */
76
0
  fz_write_int16_le(ctx, zip->output, 1<<11); /* general purpose bit flag */
77
0
  fz_write_int16_le(ctx, zip->output, 0); /* compression method: store */
78
0
  fz_write_int16_le(ctx, zip->output, 0); /* TODO: last mod file time */
79
0
  fz_write_int16_le(ctx, zip->output, 0); /* TODO: last mod file date */
80
0
  fz_write_int32_le(ctx, zip->output, sum); /* crc-32 */
81
0
  fz_write_int32_le(ctx, zip->output, (int)buf->len); /* csize */
82
0
  fz_write_int32_le(ctx, zip->output, (int)buf->len); /* usize */
83
0
  fz_write_int16_le(ctx, zip->output, (int)strlen(name)); /* file name length */
84
0
  fz_write_int16_le(ctx, zip->output, 0); /* extra field length */
85
0
  fz_write_data(ctx, zip->output, name, strlen(name));
86
0
  fz_write_data(ctx, zip->output, buf->data, buf->len);
87
88
0
  ++zip->count;
89
0
}
90
91
void
92
fz_close_zip_writer(fz_context *ctx, fz_zip_writer *zip)
93
0
{
94
0
  int64_t offset = fz_tell_output(ctx, zip->output);
95
96
0
  fz_write_data(ctx, zip->output, zip->central->data, zip->central->len);
97
98
0
  fz_write_int32_le(ctx, zip->output, ZIP_END_OF_CENTRAL_DIRECTORY_SIG);
99
0
  fz_write_int16_le(ctx, zip->output, 0); /* number of this disk */
100
0
  fz_write_int16_le(ctx, zip->output, 0); /* number of disk where central directory starts */
101
0
  fz_write_int16_le(ctx, zip->output, zip->count); /* entries in central directory in this disk */
102
0
  fz_write_int16_le(ctx, zip->output, zip->count); /* entries in central directory in total */
103
0
  fz_write_int32_le(ctx, zip->output, (int)zip->central->len); /* size of the central directory */
104
0
  fz_write_int32_le(ctx, zip->output, (int)offset); /* offset of the central directory */
105
0
  fz_write_int16_le(ctx, zip->output, 5); /* zip file comment length */
106
107
0
  fz_write_data(ctx, zip->output, "MuPDF", 5);
108
109
0
  fz_close_output(ctx, zip->output);
110
111
0
  zip->closed = 1;
112
0
}
113
114
void
115
fz_drop_zip_writer(fz_context *ctx, fz_zip_writer *zip)
116
0
{
117
0
  if (!zip)
118
0
    return;
119
0
  if (!zip->closed)
120
0
    fz_warn(ctx, "dropping unclosed zip writer");
121
0
  fz_drop_output(ctx, zip->output);
122
0
  fz_drop_buffer(ctx, zip->central);
123
0
  fz_free(ctx, zip);
124
0
}
125
126
fz_zip_writer *
127
fz_new_zip_writer_with_output(fz_context *ctx, fz_output *out)
128
0
{
129
0
  fz_zip_writer *zip = NULL;
130
131
0
  fz_var(zip);
132
133
0
  fz_try(ctx)
134
0
  {
135
0
    zip = fz_malloc_struct(ctx, fz_zip_writer);
136
0
    zip->output = out;
137
0
    zip->central = fz_new_buffer(ctx, 0);
138
0
  }
139
0
  fz_catch(ctx)
140
0
  {
141
0
    fz_drop_output(ctx, out);
142
0
    if (zip)
143
0
      fz_drop_buffer(ctx, zip->central);
144
0
    fz_free(ctx, zip);
145
0
    fz_rethrow(ctx);
146
0
  }
147
0
  return zip;
148
0
}
149
150
fz_zip_writer *
151
fz_new_zip_writer(fz_context *ctx, const char *filename)
152
0
{
153
0
  fz_output *out = fz_new_output_with_path(ctx, filename, 0);
154
0
  fz_zip_writer *zip = NULL;
155
0
  fz_try(ctx)
156
0
    zip = fz_new_zip_writer_with_output(ctx, out);
157
0
  fz_catch(ctx)
158
0
  {
159
0
    fz_drop_output(ctx, out);
160
0
    fz_rethrow(ctx);
161
0
  }
162
0
  return zip;
163
0
}