From 16cfe2d3bad524f7d33fe54518fcff3fdc78c31c Mon Sep 17 00:00:00 2001 From: Rob Swindell <rob@synchro.net> Date: Mon, 3 Jan 2022 17:39:55 -0800 Subject: [PATCH] Add overwrite argument to extract_file_from_archive and Archive.extract Previously, extracted files were always overwritten (so that is the "default" for Archive.extract() and mostly what I'm specifying in the C/C++ code by default now), but this caused a problem with DIZ extraction: archives that contained multiple DIZ files (e.g in sub-directories), the last to be extracted would be used. A maximum of 3 DIZs can be extracted, so it would usually be the 3rd DIZ in the archive if there were that many. Another solution would be to *only* extract DIZ files from the root of the archive and I should look into that as well, but the always-overwrite behavior also seemed to be wrong, so that *also* needed fixing (allow caller to control behavior). This fixes issue #317, at least for archives where the root DIZ exists *before* any nested DIZ files. I'll have to try and create a purposeful archive to test the other conditions (where the root DIZ would appear *after* the nested DIZ(s)). --- src/sbbs3/filedat.c | 5 ++++- src/sbbs3/filedat.h | 2 +- src/sbbs3/js_archive.c | 9 +++++++-- src/sbbs3/pack_qwk.cpp | 1 + src/sbbs3/pack_rep.cpp | 1 + src/sbbs3/sbbsecho.c | 2 +- src/sbbs3/un_qwk.cpp | 1 + src/sbbs3/un_rep.cpp | 1 + 8 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/sbbs3/filedat.c b/src/sbbs3/filedat.c index 074114f2a0..51679e5346 100644 --- a/src/sbbs3/filedat.c +++ b/src/sbbs3/filedat.c @@ -809,7 +809,7 @@ long create_archive(const char* archive, const char* format } long extract_files_from_archive(const char* archive, const char* outdir, const char* allowed_filename_chars - ,bool with_path, long max_files, str_list_t file_list, char* error, size_t maxerrlen) + ,bool with_path, bool overwrite, long max_files, str_list_t file_list, char* error, size_t maxerrlen) { int result; struct archive *ar; @@ -884,6 +884,8 @@ long extract_files_from_archive(const char* archive, const char* outdir, const c SAFECOPY(fpath, outdir); backslash(fpath); SAFECAT(fpath, pathname); + if(!overwrite && fexist(fpath)) + continue; FILE* fp = fopen(fpath, "wb"); if(fp == NULL) { char err[256]; @@ -945,6 +947,7 @@ bool extract_diz(scfg_t* cfg, file_t* f, str_list_t diz_fnames, char* path, size ,/* outdir: */cfg->temp_dir ,/* allowed_filename_chars: */NULL /* any */ ,/* with_path: */false + ,/* overwrite: */false ,/* max_files: */strListCount(diz_fnames) ,/* file_list: */diz_fnames ,/* error: */NULL, 0) >= 0) { diff --git a/src/sbbs3/filedat.h b/src/sbbs3/filedat.h index b598014706..de68269df5 100644 --- a/src/sbbs3/filedat.h +++ b/src/sbbs3/filedat.h @@ -72,7 +72,7 @@ DLLEXPORT long create_archive(const char* archive, const char* format ,bool with_path, str_list_t file_list, char* error, size_t maxerrlen); DLLEXPORT char* cmdstr(scfg_t*, user_t*, const char* instr, const char* fpath, const char* fspec, char* cmd, size_t); DLLEXPORT long extract_files_from_archive(const char* archive, const char* outdir, const char* allowed_filename_chars - ,bool with_path, long max_files, str_list_t file_list, char* error, size_t); + ,bool with_path, bool overwrite, long max_files, str_list_t file_list, char* error, size_t); DLLEXPORT int archive_type(const char* archive, char* str, size_t size); extern const char* supported_archive_formats[]; diff --git a/src/sbbs3/js_archive.c b/src/sbbs3/js_archive.c index 608da5a3ae..34e754f8e6 100644 --- a/src/sbbs3/js_archive.c +++ b/src/sbbs3/js_archive.c @@ -109,6 +109,7 @@ js_extract(JSContext *cx, uintN argc, jsval *arglist) char* allowed_filename_chars = SAFEST_FILENAME_CHARS; str_list_t file_list = NULL; bool with_path = false; + bool overwrite = true; int32 max_files = 0; char error[256] = ""; jsrefcount rc; @@ -136,6 +137,10 @@ js_extract(JSContext *cx, uintN argc, jsval *arglist) allowed_filename_chars = NULL; // We trust this archive argn++; } + if(argc > argn && JSVAL_IS_BOOLEAN(argv[argn])) { + overwrite = JSVAL_TO_BOOLEAN(argv[argn]); + argn++; + } if(argc > argn && JSVAL_IS_NUMBER(argv[argn])) { if(!JS_ValueToInt32(cx, argv[argn], &max_files)) { free(outdir); @@ -154,7 +159,7 @@ js_extract(JSContext *cx, uintN argc, jsval *arglist) rc = JS_SUSPENDREQUEST(cx); long extracted = extract_files_from_archive(filename, outdir, allowed_filename_chars - ,with_path, (ulong)max_files, file_list, error, sizeof(error)); + ,with_path, overwrite, (ulong)max_files, file_list, error, sizeof(error)); strListFree(&file_list); free(outdir); JS_RESUMEREQUEST(cx, rc); @@ -538,7 +543,7 @@ static jsSyncMethodSpec js_archive_functions[] = { ,31900 }, { "extract", js_extract, 1, JSTYPE_NUMBER - ,JSDOCSTR("output_directory [,boolean with_path = false] [,number max_files = 0] [,string file/pattern [...]]") + ,JSDOCSTR("output_directory [,boolean with_path = false] [,boolean overwrite = true] [,number max_files = 0] [,string file/pattern [...]]") ,JSDOCSTR("Extract files from an archive to specified output directory.<br>" "Returns the number of files extracted.<br>" "Will throw exception upon error.") diff --git a/src/sbbs3/pack_qwk.cpp b/src/sbbs3/pack_qwk.cpp index f680480fa2..0727e71969 100644 --- a/src/sbbs3/pack_qwk.cpp +++ b/src/sbbs3/pack_qwk.cpp @@ -73,6 +73,7 @@ bool sbbs_t::pack_qwk(char *packet, ulong *msgcnt, bool prepack) ,/* outdir: */cfg.temp_dir ,/* allowed_filename_chars: */NULL /* any */ ,/* with_path: */false + ,/* overwrite: */true ,/* max_files: */0 /* unlimited */ ,/* file_list: */NULL /* all files */ ,error, sizeof(error)); diff --git a/src/sbbs3/pack_rep.cpp b/src/sbbs3/pack_rep.cpp index 190bba9ebb..8f70d9069e 100644 --- a/src/sbbs3/pack_rep.cpp +++ b/src/sbbs3/pack_rep.cpp @@ -67,6 +67,7 @@ bool sbbs_t::pack_rep(uint hubnum) ,/* outdir: */cfg.temp_dir ,/* allowed_filename_chars: */NULL /* any */ ,/* with_path: */false + ,/* overwrite: */true ,/* max_files: */0 /* unlimited */ ,/* file_list: */NULL /* all files */ ,error, sizeof(error)); diff --git a/src/sbbs3/sbbsecho.c b/src/sbbs3/sbbsecho.c index 982e328aa3..fcb4a24123 100644 --- a/src/sbbs3/sbbsecho.c +++ b/src/sbbs3/sbbsecho.c @@ -2266,7 +2266,7 @@ int unpack(const char *infile, const char* outdir) long file_count; file_count = extract_files_from_archive(infile, outdir - ,/* allowed_filename_chars: */SAFEST_FILENAME_CHARS, /* with_path */false + ,/* allowed_filename_chars: */SAFEST_FILENAME_CHARS, /* with_path */false, /* overwrite: */true ,/* max_files: */0, /* file_list = ALL */NULL, error, sizeof(error)); if(file_count > 0) { lprintf(LOG_DEBUG, "libarchive extracted %lu files from %s", file_count, infile); diff --git a/src/sbbs3/un_qwk.cpp b/src/sbbs3/un_qwk.cpp index ac05baf2f7..6f4096015c 100644 --- a/src/sbbs3/un_qwk.cpp +++ b/src/sbbs3/un_qwk.cpp @@ -80,6 +80,7 @@ bool sbbs_t::unpack_qwk(char *packet,uint hubnum) ,/* outdir: */cfg.temp_dir ,/* allowed_filename_chars: */NULL /* any */ ,/* with_path: */false + ,/* overwrite: */true ,/* max_files: */0 /* unlimited */ ,/* file_list: */NULL /* all files */ ,error, sizeof(error)); diff --git a/src/sbbs3/un_rep.cpp b/src/sbbs3/un_rep.cpp index 7db302217e..918949d01c 100644 --- a/src/sbbs3/un_rep.cpp +++ b/src/sbbs3/un_rep.cpp @@ -76,6 +76,7 @@ bool sbbs_t::unpack_rep(char* repfile) ,/* outdir: */cfg.temp_dir ,/* allowed_filename_chars: */SAFEST_FILENAME_CHARS ,/* with_path: */false + ,/* overwrite: */true ,/* max_files */1000 ,/* file_list: */NULL /* all files */ ,error, sizeof(error)); -- GitLab