static int _zip_headercomp(const struct zip_dirent *central, const struct zip_dirent *local) { if ((central->version_needed != local->version_needed) #if 0 /* some zip-files have different values in local and global headers for the bitflags */ || (central->bitflags != local->bitflags) #endif || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename)) return -1; if ((central->crc != local->crc) || (central->comp_size != local->comp_size) || (central->uncomp_size != local->uncomp_size)) { /* InfoZip stores valid values in local header even when data descriptor is used. This is in violation of the appnote. */ if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0)) return -1; } return 0; }
ZIP_EXTERN int zip_set_archive_comment(struct zip *za, const char *comment, zip_uint16_t len) { struct zip_string *cstr; if (ZIP_IS_RDONLY(za)) { _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (len < 0 || len > MAXCOMLEN || (len > 0 && comment == NULL)) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (len > 0) { if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL) return -1; if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) { _zip_string_free(cstr); _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } } else cstr = NULL; _zip_string_free(za->comment_changes); za->comment_changes = NULL; if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) || (za->comment_orig == NULL && cstr == NULL))) { _zip_string_free(cstr); za->comment_changed = 0; } else { za->comment_changes = cstr; za->comment_changed = 1; } return 0; }
int _zip_set_name(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { struct zip_entry *e; struct zip_string *str; int changed; zip_int64_t i; if (idx >= za->nentry) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (ZIP_IS_RDONLY(za)) { _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (name && strlen(name) > 0) { /* XXX: check for string too long */ if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) return -1; if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) str->encoding = ZIP_ENCODING_UTF8_KNOWN; } else str = NULL; /* XXX: encoding flags needed for CP437? */ if ((i=_zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) { _zip_string_free(str); _zip_error_set(&za->error, ZIP_ER_EXISTS, 0); return -1; } /* no effective name change */ if (i>=0 && (zip_uint64_t)i == idx) { _zip_string_free(str); return 0; } e = za->entry+idx; if (e->changes) { _zip_string_free(e->changes->filename); e->changes->filename = NULL; e->changes->changed &= ~ZIP_DIRENT_FILENAME; } if (e->orig) changed = !_zip_string_equal(e->orig->filename, str); else changed = 1; if (changed) { if (e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } } e->changes->filename = str; e->changes->changed |= ZIP_DIRENT_FILENAME; } else { _zip_string_free(str); if (e->changes && e->changes->changed == 0) { _zip_dirent_free(e->changes); e->changes = NULL; } } return 0; }
ZIP_EXTERN int zip_file_set_comment(struct zip *za, zip_uint64_t idx, const char *comment, zip_uint16_t len, zip_flags_t flags) { struct zip_entry *e; struct zip_string *cstr; struct zip_dirent *de; int changed; if ((de=_zip_get_dirent(za, idx, 0, NULL)) == NULL) return -1; if (ZIP_IS_RDONLY(za)) { _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (len > 0 && comment == NULL) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (len > 0) { if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL) return -1; if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) cstr->encoding = ZIP_ENCODING_UTF8_KNOWN; } else cstr = NULL; e = za->entry+idx; if (e->changes) { _zip_string_free(e->changes->comment); e->changes->comment = NULL; e->changes->changed &= ~ZIP_DIRENT_COMMENT; } if (e->orig && e->orig->comment) changed = !_zip_string_equal(e->orig->comment, cstr); else changed = (cstr != NULL); if (changed) { if (e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } } e->changes->comment = cstr; e->changes->changed |= ZIP_DIRENT_COMMENT; } else { _zip_string_free(cstr); if (e->changes && e->changes->changed == 0) { _zip_dirent_free(e->changes); e->changes = NULL; } } return 0; }
int _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { zip_entry_t *e; zip_string_t *str; bool same_as_orig; zip_int64_t i; const zip_uint8_t *old_name, *new_name; zip_string_t *old_str; if (idx >= za->nentry) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } if (ZIP_IS_RDONLY(za)) { zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (name && name[0] != '\0') { /* TODO: check for string too long */ if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) return -1; if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) str->encoding = ZIP_ENCODING_UTF8_KNOWN; } else str = NULL; /* TODO: encoding flags needed for CP437? */ if ((i=_zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) { _zip_string_free(str); zip_error_set(&za->error, ZIP_ER_EXISTS, 0); return -1; } /* no effective name change */ if (i>=0 && (zip_uint64_t)i == idx) { _zip_string_free(str); return 0; } e = za->entry+idx; if (e->orig) same_as_orig = _zip_string_equal(e->orig->filename, str); else same_as_orig = false; if (!same_as_orig && e->changes == NULL) { if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { zip_error_set(&za->error, ZIP_ER_MEMORY, 0); _zip_string_free(str); return -1; } } if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) { _zip_string_free(str); return -1; } if (e->changes) { old_str = e->changes->filename; } else if (e->orig) { old_str = e->orig->filename; } else { old_str = NULL; } if (old_str) { if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) { _zip_string_free(str); return -1; } } else { old_name = NULL; } if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) { _zip_string_free(str); return -1; } if (old_name) { _zip_hash_delete(za->names, old_name, NULL); } if (same_as_orig) { if (e->changes) { if (e->changes->changed & ZIP_DIRENT_FILENAME) { _zip_string_free(e->changes->filename); e->changes->changed &= ~ZIP_DIRENT_FILENAME; if (e->changes->changed == 0) { _zip_dirent_free(e->changes); e->changes = NULL; } else { /* TODO: what if not cloned? can that happen? */ e->changes->filename = e->orig->filename; } } } _zip_string_free(str); } else { if (e->changes->changed & ZIP_DIRENT_FILENAME) { _zip_string_free(e->changes->filename); } e->changes->changed |= ZIP_DIRENT_FILENAME; e->changes->filename = str; } return 0; }