diff --git a/android/phoenix/jni/apk-extract/apk-extract.c b/android/phoenix/jni/apk-extract/apk-extract.c index d8f245a7bb..e2312103ad 100644 --- a/android/phoenix/jni/apk-extract/apk-extract.c +++ b/android/phoenix/jni/apk-extract/apk-extract.c @@ -20,7 +20,8 @@ struct userdata const char *dest; }; -static bool zlib_cb(const char *name, const uint8_t *cdata, +static bool zlib_cb(const char *name, const char *valid_exts, + const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t crc32, void *userdata) { @@ -57,7 +58,8 @@ static bool zlib_cb(const char *name, const uint8_t *cdata, break; case 8: /* Deflate */ - if (!zlib_inflate_data_to_file(path, cdata, csize, size, crc32)) + if (!zlib_inflate_data_to_file(path, valid_exts, cdata, + csize, size, crc32)) { RARCH_ERR("Failed to deflate to: %s.\n", path); return false; @@ -85,7 +87,7 @@ JNIEXPORT jboolean JNICALL Java_com_retroarch_browser_NativeInterface_extractArc .dest = dest_c, }; - if (!zlib_parse_file(archive_c, zlib_cb, &data)) + if (!zlib_parse_file(archive_c, NULL, zlib_cb, &data)) { RARCH_ERR("Failed to parse APK: %s.\n", archive_c); ret = JNI_FALSE; diff --git a/apple/iOS/browser.m b/apple/iOS/browser.m index 9ea0c99cdc..86e5d317c4 100644 --- a/apple/iOS/browser.m +++ b/apple/iOS/browser.m @@ -71,7 +71,7 @@ static void unzip_file(const char* path, const char* output_directory) apple_display_alert("Output directory for zip must not already exist.", "Action Failed"); else if (!path_mkdir(output_directory)) apple_display_alert("Could not create output directory to extract zip.", "Action Failed"); - else if (!zlib_parse_file(path, zlib_extract_callback, (void*)output_directory)) + else if (!zlib_parse_file(path, NULL, zlib_extract_callback, (void*)output_directory)) apple_display_alert("Could not process zip file.", "Action Failed"); } diff --git a/core_info.c b/core_info.c index 47d1a9e680..d4892648eb 100644 --- a/core_info.c +++ b/core_info.c @@ -390,7 +390,7 @@ void core_info_list_get_supported_cores(core_info_list_t *core_info_list, #ifdef HAVE_ZLIB if (!strcasecmp(path_get_extension(path), "zip")) - list = zlib_get_file_list(path); + list = zlib_get_file_list(path, NULL); core_info_tmp_list = list; #endif diff --git a/decompress/zip_support.c b/decompress/zip_support.c index 1e69291e18..532f3e3266 100644 --- a/decompress/zip_support.c +++ b/decompress/zip_support.c @@ -189,112 +189,4 @@ int read_zip_file(const char * archive_path, return bytes_read; } -struct string_list *compressed_zip_file_list_new(const char *path, - const char* ext) -{ - uLong i; - unz_global_info global_info; - unzFile *zipfile = NULL; - ssize_t bytes_read = -1; - bool finished_reading = false; - struct string_list *ext_list = NULL; - struct string_list *list = string_list_new(); - - if (!list) - return NULL; - - if (ext) - ext_list = string_split(ext, "|"); - - zipfile = (unzFile*)unzOpen( path ); - - (void)finished_reading; - (void)bytes_read; - - if (!zipfile) - { - RARCH_ERR("Could not open ZIP file %s.\n",path); - goto error; - } - - /* Get info about the zip file */ - if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK) - { - RARCH_ERR("Could not get global zipfile info of %s." - "Could be only a GZIP file without the ZIP part.\n", - path); - unzClose(zipfile); - goto error; - } - - for ( i = 0; i < global_info.number_entry; ++i ) - { - /* Get info about current file. */ - unz_file_info file_info; - char filename[PATH_MAX_LENGTH]; - char last_char = ' '; - - if (unzGetCurrentFileInfo( - zipfile, - &file_info, - filename, - PATH_MAX_LENGTH, - NULL, 0, NULL, 0 ) != UNZ_OK) - { - RARCH_ERR("Could not read file info in ZIP %s.\n", path); - unzClose(zipfile); - goto error; - } - - /* Check if this entry is a directory or file. */ - last_char = filename[strlen(filename)-1]; - - if ( last_char == '/' || last_char == '\\' ) - { - /* We skip directories */ - } - else - { - const char *file_ext = path_get_extension(filename); - bool supported_by_core = false; - union string_list_elem_attr attr; - - if (string_list_find_elem_prefix(ext_list, ".", file_ext)) - supported_by_core = true; - - if (supported_by_core) - { - attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE; - if (!string_list_append(list, filename, attr)) - { - RARCH_ERR("Could not append item to string list.\n"); - unzCloseCurrentFile(zipfile); - break; - } - } - - } - - unzCloseCurrentFile(zipfile); - - if ((i + 1) < global_info.number_entry) - { - if (unzGoToNextFile(zipfile) != UNZ_OK ) - { - RARCH_ERR( "Could not iterate to next file in %s. ZIP file might be corrupt.\n",path ); - unzClose(zipfile); - goto error; - } - } - } - - unzClose(zipfile); - - return list; -error: - string_list_free(list); - string_list_free(ext_list); - return NULL; -} - #undef RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX diff --git a/decompress/zip_support.h b/decompress/zip_support.h index 769006f861..dd3e5efedd 100644 --- a/decompress/zip_support.h +++ b/decompress/zip_support.h @@ -24,9 +24,6 @@ extern "C" { int read_zip_file(const char * archive_path, const char *relative_path, void **buf, const char* optional_outfile); -struct string_list *compressed_zip_file_list_new(const char *path, - const char* ext); - #ifdef __cplusplus } #endif diff --git a/file_extract.c b/file_extract.c index 9ad5836d5f..5e95a01bfb 100644 --- a/file_extract.c +++ b/file_extract.c @@ -19,6 +19,7 @@ #include #include #include +#include "general.h" #include "retroarch_logger.h" #include #include @@ -213,6 +214,8 @@ static uint32_t read_le(const uint8_t *data, unsigned size) /** * zlib_inflate_data_to_file: * @path : filename path of archive. + * @valid_exts : Valid extensions of archive to be parsed. + * If NULL, allow all. * @cdata : input data. * @csize : size of input data. * @size : output file size @@ -222,8 +225,8 @@ static uint32_t read_le(const uint8_t *data, unsigned size) * * Returns: true (1) on success, otherwise false (0). **/ -bool zlib_inflate_data_to_file(const char *path, const uint8_t *cdata, - uint32_t csize, uint32_t size, uint32_t checksum) +bool zlib_inflate_data_to_file(const char *path, const char *valid_exts, + const uint8_t *cdata, uint32_t csize, uint32_t size, uint32_t checksum) { bool ret = true; uint32_t real_checksum = 0; @@ -264,6 +267,8 @@ end: /** * zlib_parse_file: * @file : filename path of archive + * @valid_exts : Valid extensions of archive to be parsed. + * If NULL, allow all. * @file_cb : file_cb function pointer * @userdata : userdata to pass to file_cb function pointer. * @@ -272,7 +277,8 @@ end: * * Returns: true (1) on success, otherwise false (0). **/ -bool zlib_parse_file(const char *file, zlib_file_cb file_cb, void *userdata) +bool zlib_parse_file(const char *file, const char *valid_exts, + zlib_file_cb file_cb, void *userdata) { void *handle; const uint8_t *footer = NULL; @@ -285,6 +291,8 @@ bool zlib_parse_file(const char *file, zlib_file_cb file_cb, void *userdata) if (!backend) return false; + (void)valid_exts; + handle = backend->open(file); if (!handle) GOTO_END_ERROR(); @@ -347,7 +355,8 @@ bool zlib_parse_file(const char *file, zlib_file_cb file_cb, void *userdata) offsetNL + offsetEL, csize, size); #endif - if (!file_cb(filename, cdata, cmode, csize, size, checksum, userdata)) + if (!file_cb(filename, valid_exts, cdata, cmode, + csize, size, checksum, userdata)) break; directory += 46 + namelength + extralength + commentlength; @@ -368,7 +377,8 @@ struct zip_extract_userdata bool found_content; }; -static bool zip_extract_cb(const char *name, const uint8_t *cdata, +static bool zip_extract_cb(const char *name, const char *valid_exts, + const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t checksum, void *userdata) { @@ -396,7 +406,8 @@ static bool zip_extract_cb(const char *name, const uint8_t *cdata, return false; /* Deflate. */ case 8: - if (zlib_inflate_data_to_file(new_path, cdata, csize, size, checksum)) + if (zlib_inflate_data_to_file(new_path, valid_exts, + cdata, csize, size, checksum)) { strlcpy(data->zip_path, new_path, data->zip_path_size); data->found_content = true; @@ -446,7 +457,7 @@ bool zlib_extract_first_content_file(char *zip_path, size_t zip_path_size, userdata.extraction_directory = extraction_directory; userdata.ext = list; - if (!zlib_parse_file(zip_path, zip_extract_cb, &userdata)) + if (!zlib_parse_file(zip_path, valid_exts, zip_extract_cb, &userdata)) { RARCH_ERR("Parsing ZIP failed.\n"); GOTO_END_ERROR(); @@ -464,11 +475,14 @@ end: return ret; } -static bool zlib_get_file_list_cb(const char *path, const uint8_t *cdata, +static bool zlib_get_file_list_cb(const char *path, const char *valid_exts, + const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t checksum, void *userdata) { union string_list_elem_attr attr; + struct string_list *ext_list = NULL; + const char *file_ext = NULL; struct string_list *list = (struct string_list*)userdata; (void)cdata; @@ -476,10 +490,39 @@ static bool zlib_get_file_list_cb(const char *path, const uint8_t *cdata, (void)csize; (void)size; (void)checksum; + (void)valid_exts; + (void)file_ext; + (void)ext_list; memset(&attr, 0, sizeof(attr)); + if (valid_exts) + ext_list = string_split(valid_exts, "|"); + + if (ext_list) + { + char last_char = ' '; + + /* Checks if this entry is a directory or a file. */ + last_char = path[strlen(path)-1]; + + if (last_char == '/' || last_char == '\\' ) /* Skip if directory. */ + goto error; + + file_ext = path_get_extension(path); + + if (!file_ext || + !string_list_find_elem_prefix(ext_list, ".", file_ext)) + goto error; + + attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE; + string_list_free(ext_list); + } + return string_list_append(list, path, attr); +error: + string_list_free(ext_list); + return false; } /** @@ -488,14 +531,15 @@ static bool zlib_get_file_list_cb(const char *path, const uint8_t *cdata, * * Returns: string listing of files from archive on success, otherwise NULL. **/ -struct string_list *zlib_get_file_list(const char *path) +struct string_list *zlib_get_file_list(const char *path, const char *valid_exts) { struct string_list *list = string_list_new(); if (!list) return NULL; - if (!zlib_parse_file(path, zlib_get_file_list_cb, list)) + if (!zlib_parse_file(path, valid_exts, + zlib_get_file_list_cb, list)) { RARCH_ERR("Parsing ZIP failed.\n"); string_list_free(list); @@ -516,7 +560,7 @@ struct string_list *compressed_file_list_new(const char *path, #endif #ifdef HAVE_ZLIB if (strcasecmp(file_ext,"zip") == 0) - return compressed_zip_file_list_new(path,ext); + return zlib_get_file_list(path, ext); #endif #endif diff --git a/file_extract.h b/file_extract.h index c875ef8d3a..a9dbe4b0b2 100644 --- a/file_extract.h +++ b/file_extract.h @@ -30,13 +30,15 @@ #endif /* Returns true when parsing should continue. False to stop. */ -typedef bool (*zlib_file_cb)(const char *name, +typedef bool (*zlib_file_cb)(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t crc32, void *userdata); /** * zlib_parse_file: * @file : filename path of archive + * @valid_exts : Valid extensions of archive to be parsed. + * If NULL, allow all. * @file_cb : file_cb function pointer * @userdata : userdata to pass to file_cb function pointer. * @@ -45,7 +47,8 @@ typedef bool (*zlib_file_cb)(const char *name, * * Returns: true (1) on success, otherwise false (0). **/ -bool zlib_parse_file(const char *file, zlib_file_cb file_cb, void *userdata); +bool zlib_parse_file(const char *file, const char *valid_exts, + zlib_file_cb file_cb, void *userdata); /** * zlib_extract_first_content_file: @@ -65,10 +68,12 @@ bool zlib_extract_first_content_file(char *zip_path, size_t zip_path_size, /** * zlib_get_file_list: * @path : filename path of archive + * @valid_exts : Valid extensions of archive to be parsed. + * If NULL, allow all. * * Returns: string listing of files from archive on success, otherwise NULL. **/ -struct string_list *zlib_get_file_list(const char *path); +struct string_list *zlib_get_file_list(const char *path, const char *valid_exts); /** * zlib_inflate_data_to_file: @@ -82,8 +87,8 @@ struct string_list *zlib_get_file_list(const char *path); * * Returns: true (1) on success, otherwise false (0). **/ -bool zlib_inflate_data_to_file(const char *path, const uint8_t *data, - uint32_t csize, uint32_t size, uint32_t crc32); +bool zlib_inflate_data_to_file(const char *path, const char *valid_exts, + const uint8_t *data, uint32_t csize, uint32_t size, uint32_t crc32); struct string_list *compressed_file_list_new(const char *filename, const char* ext);