From c04da1926fe60312f704cd30da5ba32c66668fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Podg=C3=B3rski?= Date: Tue, 7 Nov 2017 16:51:32 +0100 Subject: [PATCH] Zip entry open/fix 13 (#15) * Internally replace '\' by '/' for entry name. * Add tests --- src/zip.c | 33 +++++++++++++++++++++++++++++++-- test/test.c | 10 +++++----- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/zip.c b/src/zip.c index 35165c8..b70af89 100644 --- a/src/zip.c +++ b/src/zip.c @@ -82,6 +82,21 @@ static int mkpath(const char *path) { return 0; } +static char *strrpl(const char *str, char old, char new) { + char *rpl = (char *)malloc(sizeof(char) * (1 + strlen(str))); + char *begin = rpl; + char c; + while((c = *str++)) { + if (c == old) { + c = new; + } + *rpl++ = c; + } + *rpl = '\0'; + + return begin; +} + struct zip_entry_t { int index; const char *name; @@ -174,6 +189,7 @@ void zip_close(struct zip_t *zip) { } int zip_entry_open(struct zip_t *zip, const char *entryname) { + char *locname = NULL; size_t entrylen = 0; mz_zip_archive *pzip = NULL; mz_uint num_alignment_padding_bytes, level; @@ -188,14 +204,27 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { } pzip = &(zip->archive); + /* + .ZIP File Format Specification Version: 6.3.3 + + 4.4.17.1 The name of the file, with optional relative path. + The path stored MUST not contain a drive or + device letter, or a leading slash. All slashes + MUST be forward slashes '/' as opposed to + backwards slashes '\' for compatibility with Amiga + and UNIX file systems etc. If input came from standard + input, there is no file name field. + */ + locname = strrpl(entryname, '\\', '/'); if (zip->mode == 'r') { - zip->entry.index = mz_zip_reader_locate_file(pzip, entryname, NULL, 0); + zip->entry.index = mz_zip_reader_locate_file(pzip, locname, NULL, 0); + CLEANUP(locname); return (zip->entry.index < 0) ? -1 : 0; } zip->entry.index = zip->archive.m_total_files; - zip->entry.name = STRCLONE(entryname); + zip->entry.name = locname; if (!zip->entry.name) { // Cannot parse zip entry name return -1; diff --git a/test/test.c b/test/test.c index 4a0e7e7..0b9c9f7 100644 --- a/test/test.c +++ b/test/test.c @@ -13,7 +13,7 @@ static void test_write(void) { struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); assert(zip != NULL); - assert(0 == zip_entry_open(zip, "test-1.txt")); + assert(0 == zip_entry_open(zip, "test/test-1.txt")); assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); assert(0 == zip_entry_close(zip)); @@ -24,7 +24,7 @@ static void test_append(void) { struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'a'); assert(zip != NULL); - assert(0 == zip_entry_open(zip, "test-2.txt")); + assert(0 == zip_entry_open(zip, "test\\test-2.txt")); assert(0 == zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2))); assert(0 == zip_entry_close(zip)); @@ -37,7 +37,7 @@ static void test_read(void) { struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); assert(zip != NULL); - assert(0 == zip_entry_open(zip, "test-1.txt")); + assert(0 == zip_entry_open(zip, "test\\test-1.txt")); assert(0 == zip_entry_read(zip, (void **)&buf, &bufsize)); assert(bufsize == strlen(TESTDATA1)); assert(0 == strncmp(buf, TESTDATA1, bufsize)); @@ -46,7 +46,7 @@ static void test_read(void) { buf = NULL; bufsize = 0; - assert(0 == zip_entry_open(zip, "test-2.txt")); + assert(0 == zip_entry_open(zip, "test/test-2.txt")); assert(0 == zip_entry_read(zip, (void **)&buf, &bufsize)); assert(bufsize == strlen(TESTDATA2)); assert(0 == strncmp(buf, TESTDATA2, bufsize)); @@ -82,7 +82,7 @@ static void test_extract(void) { struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); assert(zip != NULL); - assert(0 == zip_entry_open(zip, "test-1.txt")); + assert(0 == zip_entry_open(zip, "test/test-1.txt")); assert(0 == zip_entry_extract(zip, on_extract, &buf)); assert(buf.size == strlen(TESTDATA1));