This source file includes following definitions.
- zip_file_extra_field_delete
- zip_file_extra_field_delete_by_id
- zip_file_extra_field_get
- zip_file_extra_field_get_by_id
- zip_file_extra_fields_count
- zip_file_extra_fields_count_by_id
- zip_file_extra_field_set
- _zip_file_extra_field_prepare_for_change
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include "zipint.h"
37
38
39
40 ZIP_EXTERN int
41 zip_file_extra_field_delete(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags)
42 {
43 struct zip_dirent *de;
44
45 if ((flags & ZIP_EF_BOTH) == 0) {
46 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
47 return -1;
48 }
49
50 if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) {
51 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
52 return -1;
53 }
54
55 if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
56 return -1;
57
58 if (ZIP_IS_RDONLY(za)) {
59 _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
60 return -1;
61 }
62
63 if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
64 return -1;
65
66 de = za->entry[idx].changes;
67
68 de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags);
69 return 0;
70 }
71
72
73
74 ZIP_EXTERN int
75 zip_file_extra_field_delete_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags)
76 {
77 struct zip_dirent *de;
78
79 if ((flags & ZIP_EF_BOTH) == 0) {
80 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
81 return -1;
82 }
83
84 if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) {
85 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
86 return -1;
87 }
88
89 if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
90 return -1;
91
92 if (ZIP_IS_RDONLY(za)) {
93 _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
94 return -1;
95 }
96
97 if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
98 return -1;
99
100 de = za->entry[idx].changes;
101
102 de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags);
103 return 0;
104 }
105
106
107
108 ZIP_EXTERN const zip_uint8_t *
109 zip_file_extra_field_get(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags)
110 {
111 static const zip_uint8_t empty[1] = { '\0' };
112
113 struct zip_dirent *de;
114 struct zip_extra_field *ef;
115 int i;
116
117 if ((flags & ZIP_EF_BOTH) == 0) {
118 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
119 return NULL;
120 }
121
122 if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
123 return NULL;
124
125 if (flags & ZIP_FL_LOCAL)
126 if (_zip_read_local_ef(za, idx) < 0)
127 return NULL;
128
129 i = 0;
130 for (ef=de->extra_fields; ef; ef=ef->next) {
131 if (ef->flags & flags & ZIP_EF_BOTH) {
132 if (i < ef_idx) {
133 i++;
134 continue;
135 }
136
137 if (idp)
138 *idp = ef->id;
139 if (lenp)
140 *lenp = ef->size;
141 if (ef->size > 0)
142 return ef->data;
143 else
144 return empty;
145 }
146 }
147
148 _zip_error_set(&za->error, ZIP_ER_NOENT, 0);
149 return NULL;
150
151 }
152
153
154
155 ZIP_EXTERN const zip_uint8_t *
156 zip_file_extra_field_get_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags)
157 {
158 struct zip_dirent *de;
159
160 if ((flags & ZIP_EF_BOTH) == 0) {
161 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
162 return NULL;
163 }
164
165 if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
166 return NULL;
167
168 if (flags & ZIP_FL_LOCAL)
169 if (_zip_read_local_ef(za, idx) < 0)
170 return NULL;
171
172 return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error);
173 }
174
175
176
177 ZIP_EXTERN zip_int16_t
178 zip_file_extra_fields_count(struct zip *za, zip_uint64_t idx, zip_flags_t flags)
179 {
180 struct zip_dirent *de;
181 struct zip_extra_field *ef;
182 zip_uint16_t n;
183
184 if ((flags & ZIP_EF_BOTH) == 0) {
185 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
186 return -1;
187 }
188
189 if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
190 return -1;
191
192 if (flags & ZIP_FL_LOCAL)
193 if (_zip_read_local_ef(za, idx) < 0)
194 return -1;
195
196 n = 0;
197 for (ef=de->extra_fields; ef; ef=ef->next)
198 if (ef->flags & flags & ZIP_EF_BOTH)
199 n++;
200
201 return (zip_int16_t)n;
202 }
203
204
205
206 ZIP_EXTERN zip_int16_t
207 zip_file_extra_fields_count_by_id(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags)
208 {
209 struct zip_dirent *de;
210 struct zip_extra_field *ef;
211 zip_uint16_t n;
212
213 if ((flags & ZIP_EF_BOTH) == 0) {
214 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
215 return -1;
216 }
217
218 if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
219 return -1;
220
221 if (flags & ZIP_FL_LOCAL)
222 if (_zip_read_local_ef(za, idx) < 0)
223 return -1;
224
225 n = 0;
226 for (ef=de->extra_fields; ef; ef=ef->next)
227 if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
228 n++;
229
230 return (zip_int16_t)n;
231 }
232
233
234
235 ZIP_EXTERN int
236 zip_file_extra_field_set(struct zip *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags)
237 {
238 struct zip_dirent *de;
239 zip_uint16_t ls, cs;
240 struct zip_extra_field *ef, *ef_prev, *ef_new;
241 int i, found, new_len;
242
243 if ((flags & ZIP_EF_BOTH) == 0) {
244 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
245 return -1;
246 }
247
248 if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
249 return -1;
250
251 if (ZIP_IS_RDONLY(za)) {
252 _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
253 return -1;
254 }
255
256 if (ZIP_EF_IS_INTERNAL(ef_id)) {
257 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
258 return -1;
259 }
260
261 if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
262 return -1;
263
264 de = za->entry[idx].changes;
265
266 ef = de->extra_fields;
267 ef_prev = NULL;
268 i = 0;
269 found = 0;
270
271 for (; ef; ef=ef->next) {
272 if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
273 if (i == ef_idx) {
274 found = 1;
275 break;
276 }
277 i++;
278 }
279 ef_prev = ef;
280 }
281
282 if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) {
283 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
284 return -1;
285 }
286
287 if (flags & ZIP_EF_LOCAL)
288 ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
289 else
290 ls = 0;
291 if (flags & ZIP_EF_CENTRAL)
292 cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
293 else
294 cs = 0;
295
296 new_len = ls > cs ? ls : cs;
297 if (found)
298 new_len -= ef->size + 4;
299 new_len += len + 4;
300
301 if (new_len > ZIP_UINT16_MAX) {
302 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
303 return -1;
304 }
305
306 if ((ef_new=_zip_ef_new(ef_id, len, data, flags)) == NULL) {
307 _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
308 return -1;
309 }
310
311 if (found) {
312 if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) {
313 ef_new->next = ef->next;
314 ef->next = NULL;
315 _zip_ef_free(ef);
316 if (ef_prev)
317 ef_prev->next = ef_new;
318 else
319 de->extra_fields = ef_new;
320 }
321 else {
322 ef->flags &= ~(flags & ZIP_EF_BOTH);
323 ef_new->next = ef->next;
324 ef->next = ef_new;
325 }
326 }
327 else if (ef_prev) {
328 ef_new->next = ef_prev->next;
329 ef_prev->next = ef_new;
330 }
331 else
332 de->extra_fields = ef_new;
333
334 return 0;
335 }
336
337
338
339 int
340 _zip_file_extra_field_prepare_for_change(struct zip *za, zip_uint64_t idx)
341 {
342 struct zip_entry *e;
343
344 if (idx >= za->nentry) {
345 _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
346 return -1;
347 }
348
349 e = za->entry+idx;
350
351 if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
352 return 0;
353
354 if (e->orig) {
355 if (_zip_read_local_ef(za, idx) < 0)
356 return -1;
357 }
358
359 if (e->changes == NULL) {
360 if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
361 _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
362 return -1;
363 }
364 }
365
366 if (e->orig && e->orig->extra_fields) {
367 if ((e->changes->extra_fields=_zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
368 return -1;
369 }
370 e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;
371
372 return 0;
373 }
374