root/ext/zip/lib/zip_extra_field_api.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zip_file_extra_field_delete
  2. zip_file_extra_field_delete_by_id
  3. zip_file_extra_field_get
  4. zip_file_extra_field_get_by_id
  5. zip_file_extra_fields_count
  6. zip_file_extra_fields_count_by_id
  7. zip_file_extra_field_set
  8. _zip_file_extra_field_prepare_for_change

   1 /*
   2   zip_extra_field_api.c -- public extra fields API functions
   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 
  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 

/* [<][>][^][v][top][bottom][index][help] */