fix: unzipping with backslashes in the name on UNIX

This commit is contained in:
Cœur 2024-11-24 19:09:36 +01:00 committed by Nathan Moinvaziri
parent b83e9ef8a2
commit c7b6cb09e9
6 changed files with 25 additions and 16 deletions

28
mz_os.c
View File

@ -46,7 +46,7 @@ int32_t mz_path_append_slash(char *path, int32_t max_path, char slash) {
int32_t path_len = (int32_t)strlen(path); int32_t path_len = (int32_t)strlen(path);
if ((path_len + 2) >= max_path) if ((path_len + 2) >= max_path)
return MZ_BUF_ERROR; return MZ_BUF_ERROR;
if (path[path_len - 1] != '\\' && path[path_len - 1] != '/') { if (!mz_os_is_dir_separator(path[path_len - 1])) {
path[path_len] = slash; path[path_len] = slash;
path[path_len + 1] = 0; path[path_len + 1] = 0;
} }
@ -56,7 +56,7 @@ int32_t mz_path_append_slash(char *path, int32_t max_path, char slash) {
int32_t mz_path_remove_slash(char *path) { int32_t mz_path_remove_slash(char *path) {
int32_t path_len = (int32_t)strlen(path); int32_t path_len = (int32_t)strlen(path);
while (path_len > 0) { while (path_len > 0) {
if (path[path_len - 1] == '\\' || path[path_len - 1] == '/') if (mz_os_is_dir_separator(path[path_len - 1]))
path[path_len - 1] = 0; path[path_len - 1] = 0;
else else
break; break;
@ -68,7 +68,7 @@ int32_t mz_path_remove_slash(char *path) {
int32_t mz_path_has_slash(const char *path) { int32_t mz_path_has_slash(const char *path) {
int32_t path_len = (int32_t)strlen(path); int32_t path_len = (int32_t)strlen(path);
if (path_len > 0 && path[path_len - 1] != '\\' && path[path_len - 1] != '/') if (path_len > 0 && !mz_os_is_dir_separator(path[path_len - 1]))
return MZ_EXIST_ERROR; return MZ_EXIST_ERROR;
return MZ_OK; return MZ_OK;
} }
@ -77,7 +77,7 @@ int32_t mz_path_convert_slashes(char *path, char slash) {
int32_t i = 0; int32_t i = 0;
for (i = 0; i < (int32_t)strlen(path); i += 1) { for (i = 0; i < (int32_t)strlen(path); i += 1) {
if (path[i] == '\\' || path[i] == '/') if (mz_os_is_dir_separator(path[i]))
path[i] = slash; path[i] = slash;
} }
return MZ_OK; return MZ_OK;
@ -136,12 +136,12 @@ int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) {
while (*source != 0 && max_output > 1) { while (*source != 0 && max_output > 1) {
check = source; check = source;
if (*check == '\\' || *check == '/') if (mz_os_is_dir_separator(*check))
check += 1; check += 1;
if (source == path || target == output || check != source) { if (source == path || target == output || check != source) {
/* Skip double paths */ /* Skip double paths */
if (*check == '\\' || *check == '/') { if (mz_os_is_dir_separator(*check)) {
source += 1; source += 1;
continue; continue;
} }
@ -158,7 +158,7 @@ int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) {
continue; continue;
} }
/* Remove . if not at end of string */ /* Remove . if not at end of string */
else if (*check == '\\' || *check == '/') { else if (mz_os_is_dir_separator(*check)) {
source += (check - source); source += (check - source);
/* Skip slash if at beginning of string */ /* Skip slash if at beginning of string */
if (target == output && *source != 0) if (target == output && *source != 0)
@ -168,14 +168,14 @@ int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) {
/* Go to parent directory .. */ /* Go to parent directory .. */
else if (*check == '.') { else if (*check == '.') {
check += 1; check += 1;
if (*check == 0 || (*check == '\\' || *check == '/')) { if (*check == 0 || mz_os_is_dir_separator(*check)) {
source += (check - source); source += (check - source);
/* Search backwards for previous slash or the start of the output string */ /* Search backwards for previous slash or the start of the output string */
if (target != output) { if (target != output) {
target -= 1; target -= 1;
do { do {
if (target == output || *target == '\\' || *target == '/') if (target == output || mz_os_is_dir_separator(*target))
break; break;
target -= 1; target -= 1;
@ -185,7 +185,7 @@ int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) {
if ((target == output) && *source != 0) if ((target == output) && *source != 0)
source += 1; source += 1;
if ((*target == '\\' || *target == '/') && *source == 0) if (mz_os_is_dir_separator(*target) && *source == 0)
target += 1; target += 1;
*target = 0; *target = 0;
@ -219,7 +219,7 @@ int32_t mz_path_remove_filename(char *path) {
path_ptr = path + strlen(path) - 1; path_ptr = path + strlen(path) - 1;
while (path_ptr > path) { while (path_ptr > path) {
if ((*path_ptr == '/') || (*path_ptr == '\\')) { if (mz_os_is_dir_separator(*path_ptr)) {
*path_ptr = 0; *path_ptr = 0;
break; break;
} }
@ -242,7 +242,7 @@ int32_t mz_path_remove_extension(char *path) {
path_ptr = path + strlen(path) - 1; path_ptr = path + strlen(path) - 1;
while (path_ptr > path) { while (path_ptr > path) {
if ((*path_ptr == '/') || (*path_ptr == '\\')) if (mz_os_is_dir_separator(*path_ptr))
break; break;
if (*path_ptr == '.') { if (*path_ptr == '.') {
*path_ptr = 0; *path_ptr = 0;
@ -267,7 +267,7 @@ int32_t mz_path_get_filename(const char *path, const char **filename) {
*filename = NULL; *filename = NULL;
for (match = path; *match != 0; match += 1) { for (match = path; *match != 0; match += 1) {
if ((*match == '\\') || (*match == '/')) if (mz_os_is_dir_separator(*match))
*filename = match + 1; *filename = match + 1;
} }
@ -296,7 +296,7 @@ int32_t mz_dir_make(const char *path) {
if (err != MZ_OK) { if (err != MZ_OK) {
match = current_dir + 1; match = current_dir + 1;
while (1) { while (1) {
while (*match != 0 && *match != '\\' && *match != '/') while (*match != 0 && !mz_os_is_dir_separator(*match))
match += 1; match += 1;
hold = *match; hold = *match;
*match = 0; *match = 0;

View File

@ -150,6 +150,9 @@ struct dirent *mz_os_read_dir(DIR *dir);
int32_t mz_os_close_dir(DIR *dir); int32_t mz_os_close_dir(DIR *dir);
/* Closes a directory that has been opened for listing */ /* Closes a directory that has been opened for listing */
int32_t mz_os_is_dir_separator(const char c);
/* Checks to see if character is a directory separator */
int32_t mz_os_is_dir(const char *path); int32_t mz_os_is_dir(const char *path);
/* Checks to see if path is a directory */ /* Checks to see if path is a directory */

View File

@ -289,6 +289,10 @@ int32_t mz_os_close_dir(DIR *dir) {
return MZ_OK; return MZ_OK;
} }
int32_t mz_os_is_dir_separator(const char c) {
return c == '/';
}
int32_t mz_os_is_dir(const char *path) { int32_t mz_os_is_dir(const char *path) {
struct stat path_stat; struct stat path_stat;

View File

@ -434,6 +434,10 @@ int32_t mz_os_close_dir(DIR *dir) {
return MZ_OK; return MZ_OK;
} }
int32_t mz_os_is_dir_separator(const char c) {
return c == '\\' || c == '/';
}
int32_t mz_os_is_dir(const char *path) { int32_t mz_os_is_dir(const char *path) {
wchar_t *path_wide = NULL; wchar_t *path_wide = NULL;
uint32_t attribs = 0; uint32_t attribs = 0;

View File

@ -654,11 +654,9 @@ int32_t mz_zip_reader_entry_save_file(void *handle, const char *path) {
if (!reader->file_info || !path) if (!reader->file_info || !path)
return MZ_PARAM_ERROR; return MZ_PARAM_ERROR;
/* Convert to forward slashes for unix which doesn't like backslashes */
pathwfs = (char *)strdup(path); pathwfs = (char *)strdup(path);
if (!pathwfs) if (!pathwfs)
return MZ_MEM_ERROR; return MZ_MEM_ERROR;
mz_path_convert_slashes(pathwfs, MZ_PATH_SLASH_UNIX);
if (reader->entry_cb) if (reader->entry_cb)
reader->entry_cb(handle, reader->entry_userdata, reader->file_info, pathwfs); reader->entry_cb(handle, reader->entry_userdata, reader->file_info, pathwfs);