Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 1 | /* |
| 2 | zip_extra_field.c -- manipulate extra fields |
Thomas Klausner | a1415de | 2015-04-29 15:36:30 +0200 | [diff] [blame] | 3 | Copyright (C) 2012-2015 Dieter Baron and Thomas Klausner |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 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 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 34 | #include <stdlib.h> |
| 35 | #include <string.h> |
| 36 | |
Thomas Klausner | 5118060 | 2015-08-21 13:36:26 +0200 | [diff] [blame] | 37 | #include "zipint.h" |
| 38 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 39 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 40 | zip_extra_field_t * |
| 41 | _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) |
Dieter Baron | 6fad8b6 | 2012-10-12 15:18:04 +0200 | [diff] [blame] | 42 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 43 | zip_extra_field_t *head, *prev, *def; |
Dieter Baron | 6fad8b6 | 2012-10-12 15:18:04 +0200 | [diff] [blame] | 44 | |
| 45 | head = prev = NULL; |
| 46 | |
| 47 | while (ef) { |
| 48 | if ((def=_zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 49 | zip_error_set(error, ZIP_ER_MEMORY, 0); |
Dieter Baron | 6fad8b6 | 2012-10-12 15:18:04 +0200 | [diff] [blame] | 50 | _zip_ef_free(head); |
| 51 | return NULL; |
| 52 | } |
| 53 | |
| 54 | if (head == NULL) |
| 55 | head = def; |
| 56 | if (prev) |
| 57 | prev->next = def; |
| 58 | prev = def; |
Thomas Klausner | 95d6fdf | 2013-02-20 11:47:10 +0100 | [diff] [blame] | 59 | |
| 60 | ef = ef->next; |
Dieter Baron | 6fad8b6 | 2012-10-12 15:18:04 +0200 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | return head; |
| 64 | } |
| 65 | |
| 66 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 67 | zip_extra_field_t * |
| 68 | _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 69 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 70 | zip_extra_field_t *head, *prev; |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 71 | int i; |
| 72 | |
| 73 | i = 0; |
| 74 | head = ef; |
| 75 | prev = NULL; |
| 76 | for (; ef; ef=(prev ? prev->next : head)) { |
Thomas Klausner | 17bf6d3 | 2013-07-31 16:29:24 +0200 | [diff] [blame] | 77 | if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) { |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 78 | if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) { |
| 79 | ef->flags &= ~(flags & ZIP_EF_BOTH); |
| 80 | if ((ef->flags & ZIP_EF_BOTH) == 0) { |
| 81 | if (prev) |
| 82 | prev->next = ef->next; |
| 83 | else |
| 84 | head = ef->next; |
| 85 | ef->next = NULL; |
| 86 | _zip_ef_free(ef); |
| 87 | |
| 88 | if (id_idx == ZIP_EXTRA_FIELD_ALL) |
| 89 | continue; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | i++; |
| 94 | if (i > id_idx) |
| 95 | break; |
| 96 | } |
| 97 | prev = ef; |
| 98 | } |
| 99 | |
| 100 | return head; |
| 101 | } |
| 102 | |
| 103 | |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 104 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 105 | void |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 106 | _zip_ef_free(zip_extra_field_t *ef) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 107 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 108 | zip_extra_field_t *ef2; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 109 | |
| 110 | while (ef) { |
| 111 | ef2 = ef->next; |
| 112 | free(ef->data); |
| 113 | free(ef); |
| 114 | ef = ef2; |
| 115 | } |
| 116 | } |
| 117 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 118 | |
| 119 | const zip_uint8_t * |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 120 | _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, zip_error_t *error) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 121 | { |
Dieter Baron | 837f5ce | 2013-03-14 12:21:04 +0100 | [diff] [blame] | 122 | static const zip_uint8_t empty[1] = { '\0' }; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 123 | |
| 124 | int i; |
| 125 | |
| 126 | i = 0; |
| 127 | for (; ef; ef=ef->next) { |
| 128 | if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) { |
| 129 | if (i < id_idx) { |
| 130 | i++; |
| 131 | continue; |
| 132 | } |
| 133 | |
| 134 | if (lenp) |
| 135 | *lenp = ef->size; |
| 136 | if (ef->size > 0) |
| 137 | return ef->data; |
| 138 | else |
| 139 | return empty; |
| 140 | } |
| 141 | } |
| 142 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 143 | zip_error_set(error, ZIP_ER_NOENT, 0); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 144 | return NULL; |
| 145 | } |
| 146 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 147 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 148 | zip_extra_field_t * |
| 149 | _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 150 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 151 | zip_extra_field_t *ef2, *tt, *tail; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 152 | int duplicate; |
| 153 | |
| 154 | if (to == NULL) |
| 155 | return from; |
| 156 | |
| 157 | for (tail=to; tail->next; tail=tail->next) |
| 158 | ; |
| 159 | |
| 160 | for (; from; from=ef2) { |
| 161 | ef2 = from->next; |
| 162 | |
| 163 | duplicate = 0; |
| 164 | for (tt=to; tt; tt=tt->next) { |
| 165 | if (tt->id == from->id && tt->size == from->size && memcmp(tt->data, from->data, tt->size) == 0) { |
| 166 | tt->flags |= (from->flags & ZIP_EF_BOTH); |
| 167 | duplicate = 1; |
| 168 | break; |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | from->next = NULL; |
| 173 | if (duplicate) |
| 174 | _zip_ef_free(from); |
| 175 | else |
| 176 | tail = tail->next = from; |
| 177 | } |
| 178 | |
| 179 | return to; |
| 180 | } |
| 181 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 182 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 183 | zip_extra_field_t * |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 184 | _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 185 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 186 | zip_extra_field_t *ef; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 187 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 188 | if ((ef=(zip_extra_field_t *)malloc(sizeof(*ef))) == NULL) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 189 | return NULL; |
| 190 | |
| 191 | ef->next = NULL; |
| 192 | ef->flags = flags; |
| 193 | ef->id = id; |
| 194 | ef->size = size; |
| 195 | if (size > 0) { |
Thomas Klausner | 84c2c08 | 2013-03-17 22:20:14 +0100 | [diff] [blame] | 196 | if ((ef->data=(zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) { |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 197 | free(ef); |
| 198 | return NULL; |
| 199 | } |
| 200 | } |
| 201 | else |
| 202 | ef->data = NULL; |
| 203 | |
| 204 | return ef; |
| 205 | } |
| 206 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 207 | |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 208 | bool |
| 209 | _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 210 | { |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 211 | zip_buffer_t *buffer; |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 212 | zip_extra_field_t *ef, *ef2, *ef_head; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 213 | |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 214 | if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) { |
| 215 | zip_error_set(error, ZIP_ER_MEMORY, 0); |
Thomas Klausner | 8b3895f | 2016-02-06 09:06:06 +0100 | [diff] [blame] | 216 | return false; |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 217 | } |
| 218 | |
Thomas Klausner | d683c12 | 2014-03-10 16:13:59 +0100 | [diff] [blame] | 219 | ef_head = ef = NULL; |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 220 | |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 221 | while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) { |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 222 | zip_uint16_t fid, flen; |
| 223 | zip_uint8_t *ef_data; |
| 224 | |
| 225 | fid = _zip_buffer_get_16(buffer); |
| 226 | flen = _zip_buffer_get_16(buffer); |
| 227 | ef_data = _zip_buffer_get(buffer, flen); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 228 | |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 229 | if (ef_data == NULL) { |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 230 | zip_error_set(error, ZIP_ER_INCONS, 0); |
| 231 | _zip_buffer_free(buffer); |
| 232 | _zip_ef_free(ef_head); |
| 233 | return false; |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 234 | } |
| 235 | |
| 236 | if ((ef2=_zip_ef_new(fid, flen, ef_data, flags)) == NULL) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 237 | zip_error_set(error, ZIP_ER_MEMORY, 0); |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 238 | _zip_buffer_free(buffer); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 239 | _zip_ef_free(ef_head); |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 240 | return false; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 241 | } |
| 242 | |
| 243 | if (ef_head) { |
| 244 | ef->next = ef2; |
| 245 | ef = ef2; |
| 246 | } |
| 247 | else |
| 248 | ef_head = ef = ef2; |
| 249 | } |
| 250 | |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 251 | if (!_zip_buffer_eof(buffer)) { |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 252 | /* Android APK files align stored file data with padding in extra fields; ignore. */ |
| 253 | /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */ |
| 254 | size_t glen = _zip_buffer_left(buffer); |
| 255 | zip_uint8_t *garbage; |
Dieter Baron | 0ed6495 | 2016-01-21 10:23:44 +0100 | [diff] [blame] | 256 | garbage = _zip_buffer_get(buffer, glen); |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 257 | if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) { |
| 258 | zip_error_set(error, ZIP_ER_INCONS, 0); |
| 259 | _zip_buffer_free(buffer); |
| 260 | _zip_ef_free(ef_head); |
| 261 | return false; |
| 262 | } |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 263 | } |
| 264 | |
| 265 | _zip_buffer_free(buffer); |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 266 | |
| 267 | if (ef_head_p) { |
| 268 | *ef_head_p = ef_head; |
| 269 | } |
Dieter Baron | 42df64a | 2016-01-21 10:02:46 +0100 | [diff] [blame] | 270 | else { |
| 271 | _zip_ef_free(ef_head); |
| 272 | } |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 273 | |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 274 | return true; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 275 | } |
| 276 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 277 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 278 | zip_extra_field_t * |
| 279 | _zip_ef_remove_internal(zip_extra_field_t *ef) |
Dieter Baron | c332cc7 | 2012-10-13 18:32:44 +0200 | [diff] [blame] | 280 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 281 | zip_extra_field_t *ef_head; |
| 282 | zip_extra_field_t *prev, *next; |
Dieter Baron | c332cc7 | 2012-10-13 18:32:44 +0200 | [diff] [blame] | 283 | |
Dieter Baron | 837f5ce | 2013-03-14 12:21:04 +0100 | [diff] [blame] | 284 | ef_head = ef; |
Dieter Baron | 7f433be | 2012-10-13 18:55:35 +0200 | [diff] [blame] | 285 | prev = NULL; |
Dieter Baron | c332cc7 | 2012-10-13 18:32:44 +0200 | [diff] [blame] | 286 | |
| 287 | while (ef) { |
| 288 | if (ZIP_EF_IS_INTERNAL(ef->id)) { |
| 289 | next = ef->next; |
| 290 | if (ef_head == ef) |
| 291 | ef_head = next; |
| 292 | ef->next = NULL; |
| 293 | _zip_ef_free(ef); |
| 294 | if (prev) |
| 295 | prev->next = next; |
| 296 | ef = next; |
| 297 | } |
| 298 | else { |
| 299 | prev = ef; |
| 300 | ef = ef->next; |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | return ef_head; |
| 305 | } |
| 306 | |
| 307 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 308 | zip_uint16_t |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 309 | _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 310 | { |
| 311 | zip_uint16_t size; |
| 312 | |
| 313 | size = 0; |
| 314 | for (; ef; ef=ef->next) { |
| 315 | if (ef->flags & flags & ZIP_EF_BOTH) |
Thomas Klausner | 03ca1c1 | 2014-09-24 01:02:15 +0200 | [diff] [blame] | 316 | size = (zip_uint16_t)(size+4+ef->size); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 317 | } |
| 318 | |
| 319 | return size; |
| 320 | } |
| 321 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 322 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 323 | int |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 324 | _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 325 | { |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 326 | zip_uint8_t b[4]; |
| 327 | zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b)); |
Thomas Klausner | af5e63b | 2015-04-22 21:25:06 +0200 | [diff] [blame] | 328 | |
| 329 | if (buffer == NULL) { |
| 330 | return -1; |
| 331 | } |
| 332 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 333 | for (; ef; ef=ef->next) { |
| 334 | if (ef->flags & flags & ZIP_EF_BOTH) { |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 335 | _zip_buffer_set_offset(buffer, 0); |
| 336 | _zip_buffer_put_16(buffer, ef->id); |
| 337 | _zip_buffer_put_16(buffer, ef->size); |
| 338 | if (!_zip_buffer_ok(buffer)) { |
| 339 | zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); |
| 340 | _zip_buffer_free(buffer); |
| 341 | return -1; |
| 342 | } |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 343 | if (_zip_write(za, b, 4) < 0) { |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 344 | _zip_buffer_free(buffer); |
| 345 | return -1; |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 346 | } |
| 347 | if (ef->size > 0) { |
| 348 | if (_zip_write(za, ef->data, ef->size) < 0) { |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 349 | _zip_buffer_free(buffer); |
| 350 | return -1; |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 351 | } |
| 352 | } |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 353 | } |
| 354 | } |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 355 | |
| 356 | _zip_buffer_free(buffer); |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 357 | return 0; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 358 | } |
| 359 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 360 | |
| 361 | int |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 362 | _zip_read_local_ef(zip_t *za, zip_uint64_t idx) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 363 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 364 | zip_entry_t *e; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 365 | unsigned char b[4]; |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 366 | zip_buffer_t *buffer; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 367 | zip_uint16_t fname_len, ef_len; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 368 | |
| 369 | if (idx >= za->nentry) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 370 | zip_error_set(&za->error, ZIP_ER_INVAL, 0); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 371 | return -1; |
| 372 | } |
| 373 | |
| 374 | e = za->entry+idx; |
| 375 | |
| 376 | if (e->orig == NULL || e->orig->local_extra_fields_read) |
| 377 | return 0; |
| 378 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 379 | if (e->orig->offset + 26 > ZIP_INT64_MAX) { |
| 380 | zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG); |
| 381 | return -1; |
| 382 | } |
Dieter Baron | abc6fd7 | 2012-07-22 15:49:45 +0200 | [diff] [blame] | 383 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 384 | if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) { |
Thomas Klausner | d97f544 | 2014-09-23 17:02:03 +0200 | [diff] [blame] | 385 | _zip_error_set_from_source(&za->error, za->src); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 386 | return -1; |
| 387 | } |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 388 | |
| 389 | if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) { |
| 390 | return -1; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 391 | } |
Dieter Baron | ee25b7d | 2014-10-11 18:30:13 +0200 | [diff] [blame] | 392 | |
| 393 | fname_len = _zip_buffer_get_16(buffer); |
| 394 | ef_len = _zip_buffer_get_16(buffer); |
| 395 | |
| 396 | if (!_zip_buffer_eof(buffer)) { |
| 397 | _zip_buffer_free(buffer); |
| 398 | zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); |
| 399 | return -1; |
| 400 | } |
| 401 | |
| 402 | _zip_buffer_free(buffer); |
| 403 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 404 | if (ef_len > 0) { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 405 | zip_extra_field_t *ef; |
Thomas Klausner | 9244705 | 2013-03-20 00:34:05 +0100 | [diff] [blame] | 406 | zip_uint8_t *ef_raw; |
| 407 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 408 | if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) { |
| 409 | zip_error_set(&za->error, ZIP_ER_SEEK, errno); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 410 | return -1; |
| 411 | } |
| 412 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 413 | ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 414 | |
| 415 | if (ef_raw == NULL) |
| 416 | return -1; |
| 417 | |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 418 | if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) { |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 419 | free(ef_raw); |
| 420 | return -1; |
| 421 | } |
| 422 | free(ef_raw); |
Thomas Klausner | dc5ea3f | 2016-01-19 13:27:40 +0100 | [diff] [blame] | 423 | |
| 424 | if (ef) { |
| 425 | ef = _zip_ef_remove_internal(ef); |
| 426 | e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); |
| 427 | } |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 428 | } |
| 429 | |
| 430 | e->orig->local_extra_fields_read = 1; |
| 431 | |
| 432 | if (e->changes && e->changes->local_extra_fields_read == 0) { |
| 433 | e->changes->extra_fields = e->orig->extra_fields; |
| 434 | e->changes->local_extra_fields_read = 1; |
| 435 | } |
| 436 | |
| 437 | return 0; |
| 438 | } |