1 /*
2 zip_extra_field.c -- manipulate extra fields
3 Copyright (C) 2012-2015 Dieter Baron and Thomas Klausner
4
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <libzip@nih.at>
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in
15 the documentation and/or other materials provided with the
16 distribution.
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
19 written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35
36 #include "zipint.h"
37
38 #include <errno.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42
43
44 struct zip_extra_field *
_zip_ef_clone(const struct zip_extra_field * ef,struct zip_error * error)45 _zip_ef_clone(const struct zip_extra_field *ef, struct zip_error *error)
46 {
47 struct zip_extra_field *head, *prev, *def;
48
49 head = prev = NULL;
50
51 while (ef) {
52 if ((def=_zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
53 _zip_error_set(error, ZIP_ER_MEMORY, 0);
54 _zip_ef_free(head);
55 return NULL;
56 }
57
58 if (head == NULL)
59 head = def;
60 if (prev)
61 prev->next = def;
62 prev = def;
63
64 ef = ef->next;
65 }
66
67 return head;
68 }
69
70
71 struct zip_extra_field *
_zip_ef_delete_by_id(struct zip_extra_field * ef,zip_uint16_t id,zip_uint16_t id_idx,zip_flags_t flags)72 _zip_ef_delete_by_id(struct zip_extra_field *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags)
73 {
74 struct zip_extra_field *head, *prev;
75 int i;
76
77 i = 0;
78 head = ef;
79 prev = NULL;
80 for (; ef; ef=(prev ? prev->next : head)) {
81 if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
82 if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
83 ef->flags &= ~(flags & ZIP_EF_BOTH);
84 if ((ef->flags & ZIP_EF_BOTH) == 0) {
85 if (prev)
86 prev->next = ef->next;
87 else
88 head = ef->next;
89 ef->next = NULL;
90 _zip_ef_free(ef);
91
92 if (id_idx == ZIP_EXTRA_FIELD_ALL)
93 continue;
94 }
95 }
96
97 i++;
98 if (i > id_idx)
99 break;
100 }
101 prev = ef;
102 }
103
104 return head;
105 }
106
107
108
109
110 void
_zip_ef_free(struct zip_extra_field * ef)111 _zip_ef_free(struct zip_extra_field *ef)
112 {
113 struct zip_extra_field *ef2;
114
115 while (ef) {
116 ef2 = ef->next;
117 free(ef->data);
118 free(ef);
119 ef = ef2;
120 }
121 }
122
123
124
125 const zip_uint8_t *
_zip_ef_get_by_id(const struct zip_extra_field * ef,zip_uint16_t * lenp,zip_uint16_t id,zip_uint16_t id_idx,zip_flags_t flags,struct zip_error * error)126 _zip_ef_get_by_id(const struct zip_extra_field *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, struct zip_error *error)
127 {
128 static const zip_uint8_t empty[1] = { '\0' };
129
130 int i;
131
132 i = 0;
133 for (; ef; ef=ef->next) {
134 if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
135 if (i < id_idx) {
136 i++;
137 continue;
138 }
139
140 if (lenp)
141 *lenp = ef->size;
142 if (ef->size > 0)
143 return ef->data;
144 else
145 return empty;
146 }
147 }
148
149 _zip_error_set(error, ZIP_ER_NOENT, 0);
150 return NULL;
151 }
152
153
154
155 struct zip_extra_field *
_zip_ef_merge(struct zip_extra_field * to,struct zip_extra_field * from)156 _zip_ef_merge(struct zip_extra_field *to, struct zip_extra_field *from)
157 {
158 struct zip_extra_field *ef2, *tt, *tail;
159 int duplicate;
160
161 if (to == NULL)
162 return from;
163
164 for (tail=to; tail->next; tail=tail->next)
165 ;
166
167 for (; from; from=ef2) {
168 ef2 = from->next;
169
170 duplicate = 0;
171 for (tt=to; tt; tt=tt->next) {
172 if (tt->id == from->id && tt->size == from->size && memcmp(tt->data, from->data, tt->size) == 0) {
173 tt->flags |= (from->flags & ZIP_EF_BOTH);
174 duplicate = 1;
175 break;
176 }
177 }
178
179 from->next = NULL;
180 if (duplicate)
181 _zip_ef_free(from);
182 else
183 tail = tail->next = from;
184 }
185
186 return to;
187 }
188
189
190
191 struct zip_extra_field *
_zip_ef_new(zip_uint16_t id,zip_uint16_t size,const zip_uint8_t * data,zip_flags_t flags)192 _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags)
193 {
194 struct zip_extra_field *ef;
195
196 if ((ef=(struct zip_extra_field *)malloc(sizeof(*ef))) == NULL)
197 return NULL;
198
199 ef->next = NULL;
200 ef->flags = flags;
201 ef->id = id;
202 ef->size = size;
203 if (size > 0) {
204 if ((ef->data=(zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
205 free(ef);
206 return NULL;
207 }
208 }
209 else
210 ef->data = NULL;
211
212 return ef;
213 }
214
215
216
217 struct zip_extra_field *
_zip_ef_parse(const zip_uint8_t * data,zip_uint16_t len,zip_flags_t flags,struct zip_error * error)218 _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, struct zip_error *error)
219 {
220 struct zip_extra_field *ef, *ef2, *ef_head;
221 const zip_uint8_t *p;
222 zip_uint16_t fid, flen;
223
224 ef_head = NULL;
225 for (p=data; p<data+len; p+=flen) {
226 if (p+4 > data+len) {
227 _zip_error_set(error, ZIP_ER_INCONS, 0);
228 _zip_ef_free(ef_head);
229 return NULL;
230 }
231
232 fid = _zip_read2(&p);
233 flen = _zip_read2(&p);
234
235 if (p+flen > data+len) {
236 _zip_error_set(error, ZIP_ER_INCONS, 0);
237 _zip_ef_free(ef_head);
238 return NULL;
239 }
240
241 if ((ef2=_zip_ef_new(fid, flen, p, flags)) == NULL) {
242 _zip_error_set(error, ZIP_ER_MEMORY, 0);
243 _zip_ef_free(ef_head);
244 return NULL;
245 }
246
247 if (ef_head) {
248 ef->next = ef2;
249 ef = ef2;
250 }
251 else
252 ef_head = ef = ef2;
253 }
254
255 return ef_head;
256 }
257
258
259
260 struct zip_extra_field *
_zip_ef_remove_internal(struct zip_extra_field * ef)261 _zip_ef_remove_internal(struct zip_extra_field *ef)
262 {
263 struct zip_extra_field *ef_head;
264 struct zip_extra_field *prev, *next;
265
266 ef_head = ef;
267 prev = NULL;
268
269 while (ef) {
270 if (ZIP_EF_IS_INTERNAL(ef->id)) {
271 next = ef->next;
272 if (ef_head == ef)
273 ef_head = next;
274 ef->next = NULL;
275 _zip_ef_free(ef);
276 if (prev)
277 prev->next = next;
278 ef = next;
279 }
280 else {
281 prev = ef;
282 ef = ef->next;
283 }
284 }
285
286 return ef_head;
287 }
288
289
290 zip_uint16_t
_zip_ef_size(const struct zip_extra_field * ef,zip_flags_t flags)291 _zip_ef_size(const struct zip_extra_field *ef, zip_flags_t flags)
292 {
293 zip_uint16_t size;
294
295 size = 0;
296 for (; ef; ef=ef->next) {
297 if (ef->flags & flags & ZIP_EF_BOTH)
298 size += 4+ef->size;
299 }
300
301 return size;
302 }
303
304
305
306 void
_zip_ef_write(const struct zip_extra_field * ef,zip_flags_t flags,FILE * f)307 _zip_ef_write(const struct zip_extra_field *ef, zip_flags_t flags, FILE *f)
308 {
309 for (; ef; ef=ef->next) {
310 if (ef->flags & flags & ZIP_EF_BOTH) {
311 _zip_write2(ef->id, f);
312 _zip_write2(ef->size, f);
313 if (ef->size > 0)
314 fwrite(ef->data, ef->size, 1, f);
315 }
316 }
317 }
318
319
320
321 int
_zip_read_local_ef(struct zip * za,zip_uint64_t idx)322 _zip_read_local_ef(struct zip *za, zip_uint64_t idx)
323 {
324 struct zip_entry *e;
325 unsigned char b[4];
326 const unsigned char *p;
327 zip_uint16_t fname_len, ef_len;
328
329 if (idx >= za->nentry) {
330 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
331 return -1;
332 }
333
334 e = za->entry+idx;
335
336 if (e->orig == NULL || e->orig->local_extra_fields_read)
337 return 0;
338
339
340 if (fseeko(za->zp, (off_t)(e->orig->offset + 26), SEEK_SET) < 0) {
341 _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
342 return -1;
343 }
344
345 if (fread(b, sizeof(b), 1, za->zp) != 1) {
346 _zip_error_set(&za->error, ZIP_ER_READ, errno);
347 return -1;
348 }
349
350 p = b;
351 fname_len = _zip_read2(&p);
352 ef_len = _zip_read2(&p);
353
354 if (ef_len > 0) {
355 struct zip_extra_field *ef;
356 zip_uint8_t *ef_raw;
357
358 if (fseek(za->zp, fname_len, SEEK_CUR) < 0) {
359 _zip_error_set(&za->error, ZIP_ER_SEEK, errno);
360 return -1;
361 }
362
363 ef_raw = _zip_read_data(NULL, za->zp, ef_len, 0, &za->error);
364
365 if (ef_raw == NULL)
366 return -1;
367
368 if ((ef=_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &za->error)) == NULL) {
369 free(ef_raw);
370 return -1;
371 }
372 free(ef_raw);
373
374 ef = _zip_ef_remove_internal(ef);
375 e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
376 }
377
378 e->orig->local_extra_fields_read = 1;
379
380 if (e->changes && e->changes->local_extra_fields_read == 0) {
381 e->changes->extra_fields = e->orig->extra_fields;
382 e->changes->local_extra_fields_read = 1;
383 }
384
385 return 0;
386 }
387