diff options
Diffstat (limited to 'ext/zip/lib/zip_set_name.c')
-rw-r--r-- | ext/zip/lib/zip_set_name.c | 74 |
1 files changed, 58 insertions, 16 deletions
diff --git a/ext/zip/lib/zip_set_name.c b/ext/zip/lib/zip_set_name.c index 2a90601bfe..02fa1272d6 100644 --- a/ext/zip/lib/zip_set_name.c +++ b/ext/zip/lib/zip_set_name.c @@ -1,6 +1,6 @@ /* zip_set_name.c -- rename helper function - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -41,35 +41,77 @@ int -_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name) +_zip_set_name(struct zip *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { - char *s; + struct zip_entry *e; + struct zip_string *str; + int changed; zip_int64_t i; - - if (idx >= za->nentry || name == NULL) { + + if (idx >= za->nentry) { _zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } - if ((i=_zip_name_locate(za, name, 0, NULL)) != -1 && i != idx) { + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (name && strlen(name) > 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 == idx) + if (i>=0 && (zip_uint64_t)i == idx) { + _zip_string_free(str); return 0; - - if ((s=strdup(name)) == NULL) { - _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return -1; } - - if (za->entry[idx].state == ZIP_ST_UNCHANGED) - za->entry[idx].state = ZIP_ST_RENAMED; - free(za->entry[idx].ch_filename); - za->entry[idx].ch_filename = s; + 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); + _zip_string_free(str); + 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; } |