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

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